Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/MapServer/src/maporaclespatial.c
Line
Count
Source
1
/******************************************************************************
2
 * Project: MapServer
3
 * Purpose: Native access to Oracle Spatial (SDO) data.
4
 * Author:  Fernando Simon (fsimon@univali.br)
5
 *          Rodrigo Becke Cabral
6
 *          Adriana Gomes Alves
7
 *
8
 * Notes: Developed under several funding agreements:
9
 *
10
 *   1) n.45/00 between CTTMAR/UNIVALI (www.cttmar.univali.br)
11
 *      and CEPSUL/IBAMA (www.ibama.gov.br)
12
 *
13
 *   2) CNPq (www.cnpq.br) under process 401263.03-7
14
 *
15
 *   3) FUNCITEC (www.funcitec.rct-sc.br) under process FCTP1523-031
16
 *
17
 ******************************************************************************
18
 * Copyright (c) 1996-2008 Regents of the University of Minnesota.
19
 *
20
 * Permission is hereby granted, free of charge, to any person obtaining a
21
 * copy of this software and associated documentation files (the "Software"),
22
 * to deal in the Software without restriction, including without limitation
23
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
24
 * and/or sell copies of the Software, and to permit persons to whom the
25
 * Software is furnished to do so, subject to the following conditions:
26
 *
27
 * The above copyright notice and this permission notice shall be included in
28
 * all copies of this Software or works derived from this Software.
29
 *
30
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
31
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
33
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
35
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36
 * DEALINGS IN THE SOFTWARE.
37
 *****************************************************************************/
38
39
#include "mapserver.h"
40
#include "maptime.h"
41
#include "mapows.h"
42
#include <assert.h>
43
44
#if defined(USE_ORACLESPATIAL) || defined(USE_ORACLE_PLUGIN)
45
46
#include <oci.h>
47
#include <ctype.h>
48
49
#define ARRAY_SIZE 1024
50
#define QUERY_SIZE 1
51
#define TEXT_SIZE 4000 /* ticket #2260 */
52
#define TYPE_OWNER "MDSYS"
53
#define SDO_GEOMETRY TYPE_OWNER ".SDO_GEOMETRY"
54
#define SDO_ORDINATE_ARRAY TYPE_OWNER ".SDO_ORDINATE_ARRAY"
55
#define SDO_GEOMETRY_LEN strlen(SDO_GEOMETRY)
56
#define FUNCTION_FILTER 1
57
#define FUNCTION_RELATE 2
58
#define FUNCTION_GEOMRELATE 3
59
#define FUNCTION_NONE 4
60
#define VERSION_8i 1
61
#define VERSION_9i 2
62
#define VERSION_10g 3
63
#define TOLERANCE 0.001
64
#define NULLERRCODE 1405
65
#define TABLE_NAME_SIZE 2000
66
67
typedef struct {
68
  OCINumber x;
69
  OCINumber y;
70
  OCINumber z;
71
} SDOPointObj;
72
73
typedef struct {
74
  OCINumber gtype;
75
  OCINumber srid;
76
  SDOPointObj point;
77
  OCIArray *elem_info;
78
  OCIArray *ordinates;
79
} SDOGeometryObj;
80
81
typedef struct {
82
  OCIInd _atomic;
83
  OCIInd x;
84
  OCIInd y;
85
  OCIInd z;
86
} SDOPointInd;
87
88
typedef struct {
89
  OCIInd _atomic;
90
  OCIInd gtype;
91
  OCIInd srid;
92
  SDOPointInd point;
93
  OCIInd elem_info;
94
  OCIInd ordinates;
95
} SDOGeometryInd;
96
97
typedef text item_text[TEXT_SIZE];
98
99
typedef item_text item_text_array[ARRAY_SIZE];
100
101
typedef item_text item_text_array_query[QUERY_SIZE];
102
103
typedef ub2 query_dtype[ARRAY_SIZE];
104
105
typedef struct {
106
  /*Oracle handlers (global to connection)*/
107
  OCIEnv *envhp;
108
  OCIError *errhp;
109
  OCISvcCtx *svchp;
110
  int last_oci_status;
111
  text last_oci_error[2048];
112
  /* This references counter is to avoid the cache freed if there are other
113
   * layers that could use it */
114
  int ref_count;
115
} msOracleSpatialHandler;
116
117
typedef struct {
118
  /* Oracle data handlers (global to connection) */
119
  OCIDescribe *dschp;
120
  OCIType *tdo;
121
} msOracleSpatialDataHandler;
122
123
typedef struct {
124
  OCIStmt *stmthp;
125
126
  /* fetch data buffer */
127
  ub4 rows_count;   /* total number of rows (so far) within cursor */
128
  ub4 row_num;      /* current row index within cursor results */
129
  ub4 rows_fetched; /* total number of rows fetched into our buffer */
130
  ub4 row;          /* current row index within our buffer */
131
132
  item_text_array *items;             /* items buffer */
133
  item_text_array_query *items_query; /* items buffer */
134
  SDOGeometryObj *obj[ARRAY_SIZE];    /* spatial object buffer */
135
  SDOGeometryInd *ind[ARRAY_SIZE];    /* object indicator (null) buffer */
136
137
  int uniqueidindex; /*allows to keep which attribute id index is used as unique
138
                        id*/
139
140
} msOracleSpatialStatement;
141
142
typedef struct {
143
  /* oracle handlers */
144
  msOracleSpatialHandler *orahandlers;
145
146
  /* oracle data handlers */
147
  msOracleSpatialDataHandler *oradatahandlers;
148
  msOracleSpatialStatement *orastmt;
149
150
  /* Following items are setup by WhichShapes
151
   * used by NextShape, ResultGetShape
152
   * disposed by CloseLayer (if set)
153
   */
154
  msOracleSpatialStatement *orastmt2;
155
  /* Driver handling of pagination, enabled by default */
156
  int paging;
157
158
} msOracleSpatialLayerInfo;
159
160
static OCIType *ordinates_tdo = NULL;
161
static OCIArray *ordinates;
162
163
/* local prototypes */
164
static int TRY(msOracleSpatialHandler *hand, sword status);
165
static int ERROR(char *routine, msOracleSpatialHandler *hand,
166
                 msOracleSpatialDataHandler *dthand);
167
static void msSplitLogin(char *connection, mapObj *map, char **username,
168
                         char **password, char **dblink);
169
static int msSplitData(char *data, char **geometry_column_name,
170
                       char **table_name, char **unique, char **srid,
171
                       char **indexfield, int *function, int *version);
172
static void msOCICloseConnection(void *layerinfo);
173
static msOracleSpatialHandler *msOCISetHandlers(char *username, char *password,
174
                                                char *dblink);
175
static int msOCISetDataHandlers(msOracleSpatialHandler *hand,
176
                                msOracleSpatialDataHandler *dthand);
177
static void msOCICloseDataHandlers(msOracleSpatialDataHandler *dthand);
178
static void msOCICloseHandlers(msOracleSpatialHandler *hand);
179
static void msOCIClearLayerInfo(msOracleSpatialLayerInfo *layerinfo);
180
static int msOCIOpenStatement(msOracleSpatialHandler *hand,
181
                              msOracleSpatialStatement *sthand);
182
static void msOCIFinishStatement(msOracleSpatialStatement *sthand);
183
static int msOCIGet2DOrdinates(msOracleSpatialHandler *hand,
184
                               SDOGeometryObj *obj, int s, int e, pointObj *pt);
185
static int msOCIGet3DOrdinates(msOracleSpatialHandler *hand,
186
                               SDOGeometryObj *obj, int s, int e, pointObj *pt);
187
static int msOCIGet4DOrdinates(msOracleSpatialHandler *hand,
188
                               SDOGeometryObj *obj, int s, int e, pointObj *pt);
189
static int msOCIConvertCircle(pointObj *pt);
190
static char *osFilteritem(layerObj *layer, int function, char *query_str,
191
                          int mode);
192
static char *osAggrGetExtent(layerObj *layer, char *query_str,
193
                             char *geom_column_name, char *table_name);
194
static char *osGeodeticData(int function, char *query_str,
195
                            char *geom_column_name, char *index_column_name);
196
static char *osNoGeodeticData(int function, int version, char *query_str,
197
                              char *geom_column_name, char *index_column_name);
198
static double osCalculateArcRadius(pointObj *pnt);
199
static void osCalculateArc(pointObj *pnt, int data3d, int data4d, double radius,
200
                           double npoints, int side, lineObj arcline,
201
                           shapeObj *shape);
202
static void osGenerateArc(shapeObj *shape, lineObj arcline, lineObj points,
203
                          int i, int data3d, int data4d);
204
static void osShapeBounds(shapeObj *shp);
205
static void osCloneShape(shapeObj *shape, shapeObj *newshape, int data3d,
206
                         int data4d);
207
static void osPointCluster(msOracleSpatialHandler *hand, shapeObj *shape,
208
                           SDOGeometryObj *obj, int start, int end,
209
                           lineObj points, int interpretation, int data3d,
210
                           int data4d);
211
static void osPoint(msOracleSpatialHandler *hand, shapeObj *shape,
212
                    SDOGeometryObj *obj, int start, int end, lineObj points,
213
                    pointObj *pnt, int data3d, int data4d);
214
static void osClosedPolygon(msOracleSpatialHandler *hand, shapeObj *shape,
215
                            SDOGeometryObj *obj, int start, int end,
216
                            lineObj points, int elem_type, int data3d,
217
                            int data4d);
218
static void osRectangle(msOracleSpatialHandler *hand, shapeObj *shape,
219
                        SDOGeometryObj *obj, int start, int end, lineObj points,
220
                        pointObj *pnt, int data3d, int data4d);
221
static void osCircle(msOracleSpatialHandler *hand, shapeObj *shape,
222
                     SDOGeometryObj *obj, int start, int end, lineObj points,
223
                     pointObj *pnt, int data3d, int data4d);
224
static void osArcPolygon(msOracleSpatialHandler *hand, shapeObj *shape,
225
                         SDOGeometryObj *obj, int start, int end,
226
                         lineObj arcpoints, int elem_type, int data3d,
227
                         int data4d);
228
static int osGetOrdinates(msOracleSpatialDataHandler *dthand,
229
                          msOracleSpatialHandler *hand, shapeObj *shape,
230
                          SDOGeometryObj *obj, SDOGeometryInd *ind);
231
static int osCheck2DGtype(int pIntGtype);
232
static int osCheck3DGtype(int pIntGtype);
233
static int osCheck4DGtype(int pIntGtype);
234
235
/******************************************************************************
236
 *                          Local Helper Functions                            *
237
 ******************************************************************************/
238
239
/* if an error occurred call msSetError, sets last_oci_status to MS_FAILURE and
240
 * return 0; otherwise returns 1 */
241
static int TRY(msOracleSpatialHandler *hand, sword status) {
242
  sb4 errcode = 0;
243
244
  if (hand->last_oci_status == MS_FAILURE)
245
    return 0; /* error from previous call */
246
247
  switch (status) {
248
  case OCI_SUCCESS_WITH_INFO:
249
  case OCI_ERROR:
250
    OCIErrorGet((dvoid *)hand->errhp, (ub4)1, (text *)NULL, &errcode,
251
                hand->last_oci_error, (ub4)sizeof(hand->last_oci_error),
252
                OCI_HTYPE_ERROR);
253
    if (errcode == NULLERRCODE) {
254
      hand->last_oci_error[0] = (text)'\0';
255
      return 1;
256
    }
257
    hand->last_oci_error[sizeof(hand->last_oci_error) - 1] =
258
        0; /* terminate string!? */
259
    break;
260
  case OCI_NEED_DATA:
261
    strlcpy((char *)hand->last_oci_error, "OCI_NEED_DATA",
262
            sizeof(hand->last_oci_error));
263
    break;
264
  case OCI_INVALID_HANDLE:
265
    strlcpy((char *)hand->last_oci_error, "OCI_INVALID_HANDLE",
266
            sizeof(hand->last_oci_error));
267
    break;
268
  case OCI_STILL_EXECUTING:
269
    ((char *)hand->last_oci_error)[sizeof(hand->last_oci_error) - 1] = 0;
270
    break;
271
  case OCI_CONTINUE:
272
    strlcpy((char *)hand->last_oci_error, "OCI_CONTINUE",
273
            sizeof(hand->last_oci_error));
274
    break;
275
  default:
276
    return 1; /* no error */
277
  }
278
279
  /* if I got here, there was an error */
280
  hand->last_oci_status = MS_FAILURE;
281
282
  return 0; /* error! */
283
}
284
285
OCIType *get_tdo(char *typename, msOracleSpatialHandler *hand,
286
                 msOracleSpatialDataHandler *dthand) {
287
  OCIParam *paramp = NULL;
288
  OCIRef *type_ref = NULL;
289
  OCIType *tdoe = NULL;
290
  int success = 0;
291
292
  success =
293
      TRY(hand, OCIDescribeAny(hand->svchp, hand->errhp, (text *)typename,
294
                               (ub4)strlen((char *)typename), OCI_OTYPE_NAME,
295
                               (ub1)1, (ub1)OCI_PTYPE_TYPE, dthand->dschp)) &&
296
      TRY(hand, OCIAttrGet((dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE,
297
                           (dvoid *)&paramp, (ub4 *)0, (ub4)OCI_ATTR_PARAM,
298
                           hand->errhp)) &&
299
      TRY(hand,
300
          OCIAttrGet((dvoid *)paramp, (ub4)OCI_DTYPE_PARAM, (dvoid *)&type_ref,
301
                     (ub4 *)0, (ub4)OCI_ATTR_REF_TDO, hand->errhp)) &&
302
      TRY(hand,
303
          OCIObjectPin(hand->envhp, hand->errhp, type_ref,
304
                       (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION,
305
                       OCI_LOCK_NONE, (dvoid **)&tdoe));
306
  if (success)
307
    return tdoe;
308
309
  /* if failure, return NULL*/
310
  return NULL;
311
}
312
313
/* check last_oci_status for MS_FAILURE (set by TRY()) if an error occurred
314
 * return 1; otherwise, returns 0 */
315
static int ERROR(char *routine, msOracleSpatialHandler *hand,
316
                 msOracleSpatialDataHandler *dthand) {
317
  (void)dthand;
318
  if (hand->last_oci_status == MS_FAILURE) {
319
    /* there was an error */
320
    msSetError(
321
        MS_ORACLESPATIALERR,
322
        "OracleSpatial server returned an error, check logs for more details",
323
        routine);
324
    msDebug("OracleSpatial server returned an error in function (%s): %s.\n",
325
            routine, (char *)hand->last_oci_error);
326
327
    /* reset error flag */
328
    hand->last_oci_status = MS_SUCCESS;
329
330
    return 1; /* error processed */
331
  } else
332
    return 0; /* no error */
333
}
334
335
/* break layer->connection (username/password@dblink) into username, password
336
 * and dblink */
337
static void msSplitLogin(char *connection, mapObj *map, char **username,
338
                         char **password, char **dblink) {
339
  char *src, *tgt, *conn_decrypted;
340
  size_t buffer_size = 0;
341
342
  /* bad 'connection' */
343
  if (connection == NULL)
344
    return;
345
346
  buffer_size = strlen(connection) + 1;
347
  *username = (char *)malloc(buffer_size);
348
  *password = (char *)malloc(buffer_size);
349
  *dblink = (char *)malloc(buffer_size);
350
351
  /* clearup */
352
  **username = **password = **dblink = 0;
353
354
  /* Decrypt any encrypted token */
355
  conn_decrypted = msDecryptStringTokens(map, connection);
356
  if (conn_decrypted == NULL)
357
    return;
358
359
  /* ok, split connection */
360
  for (tgt = *username, src = conn_decrypted; *src; src++, tgt++)
361
    if (*src == '/' || *src == '@')
362
      break;
363
    else
364
      *tgt = *src;
365
  *tgt = 0;
366
  if (*src == '/') {
367
    for (tgt = *password, ++src; *src; src++, tgt++)
368
      if (*src == '@')
369
        break;
370
      else
371
        *tgt = *src;
372
    *tgt = 0;
373
  }
374
  if (*src == '@') {
375
    strlcpy(*dblink, ++src, buffer_size);
376
  }
377
378
  msFree(conn_decrypted);
379
}
380
381
/* break layer->data into geometry_column_name, table_name and srid */
382
static int msSplitData(char *data, char **geometry_column_name,
383
                       char **table_name, char **unique, char **srid,
384
                       char **indexfield, int *function, int *version) {
385
  char *tok_from = "from";
386
  char *tok_using = "using";
387
  char *tok_unique = "unique";
388
  char *tok_srid = "srid";
389
  char *tok_indexfield = "indexfield";
390
  char *tok_version = "version";
391
  char data_version[4] = "";
392
  char tok_function[11] = "";
393
  int parenthesis, i;
394
  char *src = data, *tgt;
395
  int table_name_size = TABLE_NAME_SIZE;
396
  size_t buffer_size = 0;
397
398
  /* bad 'data' */
399
  if (data == NULL)
400
    return 0;
401
402
  buffer_size = strlen(data) + 1;
403
  *geometry_column_name = (char *)malloc(buffer_size);
404
  *unique = (char *)malloc(buffer_size);
405
  *srid = (char *)malloc(buffer_size);
406
  *indexfield = (char *)malloc(buffer_size);
407
408
  /* clearup */
409
  **geometry_column_name = **table_name = 0;
410
411
  /* parsing 'geometry_column_name' */
412
  for (; *src && isspace(*src); src++)
413
    ; /* skip blanks */
414
  for (tgt = *geometry_column_name; *src; src++, tgt++)
415
    if (isspace(*src))
416
      break;
417
    else
418
      *tgt = *src;
419
  *tgt = 0;
420
421
  /* parsing 'from' */
422
  for (; *src && isspace(*src); src++)
423
    ; /* skip blanks */
424
  for (; *src && *tok_from && tolower(*src) == *tok_from; src++, tok_from++)
425
    ;
426
  if (*tok_from != '\0')
427
    return 0;
428
429
  /* parsing 'table_name' or '(SELECT stmt)' */
430
  i = 0;
431
  for (; *src && isspace(*src); src++)
432
    ; /* skip blanks */
433
  for (tgt = *table_name, parenthesis = 0; *src; src++, tgt++, ++i) {
434
    if (*src == '(')
435
      parenthesis++;
436
    else if (*src == ')')
437
      parenthesis--;
438
    else if (parenthesis == 0 && isspace(*src))
439
      break; /* stop on spaces */
440
    /* double the size of the table_name array if necessary */
441
    if (i == table_name_size) {
442
      size_t tgt_offset = tgt - *table_name;
443
      table_name_size *= 2;
444
      *table_name =
445
          (char *)realloc(*table_name, sizeof(char *) * table_name_size);
446
      tgt = *table_name + tgt_offset;
447
    }
448
    *tgt = *src;
449
  }
450
  *tgt = 0;
451
452
  strlcpy(*unique, "", buffer_size);
453
  strlcpy(*srid, "NULL", buffer_size);
454
  strlcpy(*indexfield, "", buffer_size);
455
456
  *function = -1;
457
  *version = -1;
458
459
  /* parsing 'unique' */
460
  for (; *src && isspace(*src); src++)
461
    ; /* skip blanks */
462
  if (*src != '\0') {
463
    /* parse 'using' */
464
    for (; *src && *tok_using && tolower(*src) == *tok_using;
465
         src++, tok_using++)
466
      ;
467
    if (*tok_using != '\0')
468
      return 0;
469
470
    /* parsing 'unique' */
471
    for (; *src && isspace(*src); src++)
472
      ; /* skip blanks */
473
    for (; *src && *tok_unique && tolower(*src) == *tok_unique;
474
         src++, tok_unique++)
475
      ;
476
477
    if (*tok_unique == '\0') {
478
      for (; *src && isspace(*src); src++)
479
        ; /* skip blanks */
480
      if (*src == '\0')
481
        return 0;
482
      for (tgt = *unique; *src; src++, tgt++)
483
        if (isspace(*src))
484
          break;
485
        else
486
          *tgt = *src;
487
      *tgt = 0;
488
489
      if (*tok_unique != '\0')
490
        return 0;
491
    }
492
493
    /* parsing 'srid' */
494
    for (; *src && isspace(*src); src++)
495
      ; /* skip blanks */
496
    for (; *src && *tok_srid && tolower(*src) == *tok_srid; src++, tok_srid++)
497
      ;
498
    if (*tok_srid == '\0') {
499
      for (; *src && isspace(*src); src++)
500
        ; /* skip blanks */
501
      if (*src == '\0')
502
        return 0;
503
      for (tgt = *srid; *src; src++, tgt++)
504
        if (isspace(*src))
505
          break;
506
        else
507
          *tgt = *src;
508
      *tgt = 0;
509
510
      if (*tok_srid != '\0')
511
        return 0;
512
    }
513
514
    /* parsing 'indexfield' */
515
    for (; *src && isspace(*src); src++)
516
      ; /* skip blanks */
517
    for (; *src && *tok_indexfield && tolower(*src) == *tok_indexfield;
518
         src++, tok_indexfield++)
519
      ;
520
521
    if (*tok_indexfield == '\0') {
522
      for (; *src && isspace(*src); src++)
523
        ; /* skip blanks */
524
      if (*src == '\0')
525
        return 0;
526
      for (tgt = *indexfield; *src; src++, tgt++)
527
        if (isspace(*src))
528
          break;
529
        else
530
          *tgt = *src;
531
      *tgt = 0;
532
533
      if (*tok_indexfield != '\0')
534
        return 0;
535
    }
536
537
    /*parsing function/version */
538
    for (; *src && isspace(*src); src++)
539
      ;
540
    if (*src != '\0') {
541
      for (tgt = tok_function; *src; src++, tgt++)
542
        if (isspace(*src))
543
          break;
544
        else
545
          *tgt = *src;
546
      *tgt = 0;
547
    }
548
549
    /*Upcase conversion for the FUNCTION/VERSION token*/
550
    for (i = 0; tok_function[i] != '\0'; i++)
551
      tok_function[i] = toupper(tok_function[i]);
552
553
    if (strcmp(tok_function, "VERSION")) {
554
      if (!strcmp(tok_function, "FILTER") || !strcmp(tok_function, ""))
555
        *function = FUNCTION_FILTER;
556
      else if (!strcmp(tok_function, "RELATE"))
557
        *function = FUNCTION_RELATE;
558
      else if (!strcmp(tok_function, "GEOMRELATE"))
559
        *function = FUNCTION_GEOMRELATE;
560
      else if (!strcmp(tok_function, "NONE"))
561
        *function = FUNCTION_NONE;
562
      else {
563
        *function = -1;
564
        return 0;
565
      }
566
567
      /*parsing VERSION token when user defined one function*/
568
      for (; *src && isspace(*src); src++)
569
        ;
570
      for (; *src && *tok_version && tolower(*src) == *tok_version;
571
           src++, tok_version++)
572
        ;
573
    } else {
574
      for (tgt = "VERSION";
575
           *tgt && *tok_version && toupper(*tgt) == toupper(*tok_version);
576
           tgt++, tok_version++)
577
        ;
578
      *function = FUNCTION_FILTER;
579
    }
580
581
    /*parsing version*/
582
    if (*tok_version == '\0') {
583
      for (; *src && isspace(*src); src++)
584
        ; /* skip blanks */
585
      for (tgt = data_version; *src; src++, tgt++)
586
        if (isspace(*src))
587
          break;
588
        else
589
          *tgt = *src;
590
      *tgt = 0;
591
592
      for (i = 0; data_version[i] != '\0'; i++)
593
        data_version[i] = tolower(data_version[i]);
594
595
      if (!strcmp(data_version, "8i"))
596
        *version = VERSION_8i;
597
      else if (!strcmp(data_version, "9i"))
598
        *version = VERSION_9i;
599
      else if (!strcmp(data_version, "10g"))
600
        *version = VERSION_10g;
601
      else
602
        return 0;
603
    }
604
  }
605
  /* finish parsing */
606
  for (; *src && isspace(*src); src++)
607
    ; /* skip blanks */
608
609
  return (*src == '\0');
610
}
611
612
/******************************************************************************
613
 *                          OCI Helper Functions                              *
614
 ******************************************************************************/
615
616
/* create statement handle from database connection */
617
static int msOCIOpenStatement(msOracleSpatialHandler *hand,
618
                              msOracleSpatialStatement *sthand) {
619
  int success = 0;
620
  char *cmd = "";
621
622
  /* allocate stmthp */
623
  success =
624
      TRY(hand, OCIHandleAlloc((dvoid *)hand->envhp, (dvoid **)&sthand->stmthp,
625
                               (ub4)OCI_HTYPE_STMT, (size_t)0, (dvoid **)0));
626
627
  sthand->rows_count = 0;
628
  sthand->row_num = 0;
629
  sthand->rows_fetched = 0;
630
  sthand->row = 0;
631
  sthand->items = NULL;
632
  sthand->items_query = NULL;
633
634
  /* setting environment values to enable time parsing */
635
636
  cmd = "alter session set NLS_DATE_FORMAT='yyyy-mm-dd hh24:mi:ss'";
637
  success = TRY(hand, OCIStmtPrepare(sthand->stmthp, hand->errhp,
638
                                     (const OraText *)cmd, (ub4)strlen(cmd),
639
                                     (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT));
640
  success =
641
      TRY(hand, OCIStmtExecute(hand->svchp, sthand->stmthp, hand->errhp,
642
                               (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL,
643
                               (OCISnapshot *)NULL, (ub4)OCI_DEFAULT));
644
645
  cmd = "alter session set NLS_TIMESTAMP_TZ_FORMAT='yyyy-mm-dd hh24:mi:ss'";
646
  success = TRY(hand, OCIStmtPrepare(sthand->stmthp, hand->errhp,
647
                                     (const OraText *)cmd, (ub4)strlen(cmd),
648
                                     (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT));
649
  success =
650
      TRY(hand, OCIStmtExecute(hand->svchp, sthand->stmthp, hand->errhp,
651
                               (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL,
652
                               (OCISnapshot *)NULL, (ub4)OCI_DEFAULT));
653
654
  cmd = "alter session set NLS_TIMESTAMP_FORMAT = 'yyyy-mm-dd hh24:mi:ss'";
655
  success = TRY(hand, OCIStmtPrepare(sthand->stmthp, hand->errhp,
656
                                     (const OraText *)cmd, (ub4)strlen(cmd),
657
                                     (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT));
658
  success =
659
      TRY(hand, OCIStmtExecute(hand->svchp, sthand->stmthp, hand->errhp,
660
                               (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL,
661
                               (OCISnapshot *)NULL, (ub4)OCI_DEFAULT));
662
663
  cmd = "alter session set time_zone = 'GMT'";
664
  success = TRY(hand, OCIStmtPrepare(sthand->stmthp, hand->errhp,
665
                                     (const OraText *)cmd, (ub4)strlen(cmd),
666
                                     (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT));
667
  success =
668
      TRY(hand, OCIStmtExecute(hand->svchp, sthand->stmthp, hand->errhp,
669
                               (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL,
670
                               (OCISnapshot *)NULL, (ub4)OCI_DEFAULT));
671
672
  /* fprintf(stderr, "Creating statement handle at %p\n", sthand->stmthp); */
673
674
  return success;
675
}
676
677
/* create statement handle from database connection */
678
static void msOCIFinishStatement(msOracleSpatialStatement *sthand) {
679
  if (sthand != NULL) {
680
    /* fprintf(stderr, "Freeing statement handle at %p\n", sthand->stmthp); */
681
682
    if (sthand->stmthp != NULL)
683
      OCIHandleFree((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT);
684
    if (sthand->items != NULL)
685
      free(sthand->items);
686
    if (sthand->items_query != NULL)
687
      free(sthand->items_query);
688
    memset(sthand, 0, sizeof(msOracleSpatialStatement));
689
    free(sthand);
690
  }
691
}
692
693
static int msOCISetDataHandlers(msOracleSpatialHandler *hand,
694
                                msOracleSpatialDataHandler *dthand) {
695
  int success = 0;
696
  OCIParam *paramp = NULL;
697
  OCIRef *type_ref = NULL;
698
699
  success =
700
      TRY(hand,
701
          /* allocate dschp */
702
          OCIHandleAlloc(hand->envhp, (dvoid **)&dthand->dschp,
703
                         (ub4)OCI_HTYPE_DESCRIBE, (size_t)0, (dvoid **)0)) &&
704
      TRY(hand,
705
          /* describe SDO_GEOMETRY in svchp (dschp) */
706
          OCIDescribeAny(hand->svchp, hand->errhp, (text *)SDO_GEOMETRY,
707
                         (ub4)SDO_GEOMETRY_LEN, OCI_OTYPE_NAME, (ub1)1,
708
                         (ub1)OCI_PTYPE_TYPE, dthand->dschp)) &&
709
      TRY(hand,
710
          /* get param for SDO_GEOMETRY */
711
          OCIAttrGet((dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE,
712
                     (dvoid *)&paramp, (ub4 *)0, (ub4)OCI_ATTR_PARAM,
713
                     hand->errhp)) &&
714
      TRY(hand,
715
          /* get type_ref for SDO_GEOMETRY */
716
          OCIAttrGet((dvoid *)paramp, (ub4)OCI_DTYPE_PARAM, (dvoid *)&type_ref,
717
                     (ub4 *)0, (ub4)OCI_ATTR_REF_TDO, hand->errhp)) &&
718
      TRY(hand,
719
          /* get TDO for SDO_GEOMETRY */
720
          OCIObjectPin(hand->envhp, hand->errhp, type_ref,
721
                       (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION,
722
                       OCI_LOCK_NONE, (dvoid **)&dthand->tdo));
723
724
  return success;
725
}
726
727
/* connect to database */
728
static msOracleSpatialHandler *msOCISetHandlers(char *username, char *password,
729
                                                char *dblink) {
730
  int success;
731
732
  msOracleSpatialHandler *hand = NULL;
733
734
  hand = (msOracleSpatialHandler *)malloc(sizeof(msOracleSpatialHandler));
735
  if (hand == NULL) {
736
    msSetError(MS_MEMERR, NULL, "msOCISetHandlers()");
737
    return NULL;
738
  }
739
  memset(hand, 0, sizeof(msOracleSpatialHandler));
740
741
  hand->ref_count = 1;
742
  hand->last_oci_status = MS_SUCCESS;
743
  hand->last_oci_error[0] = (text)'\0';
744
745
  success = TRY(hand,
746
  /* allocate envhp */
747
#ifdef USE_THREAD
748
                OCIEnvCreate(&hand->envhp, OCI_OBJECT | OCI_THREADED,
749
                             (dvoid *)0, 0, 0, 0, (size_t)0, (dvoid **)0))
750
#else
751
                OCIEnvCreate(&hand->envhp, OCI_OBJECT, (dvoid *)0, 0, 0, 0,
752
                             (size_t)0, (dvoid **)0))
753
#endif
754
            &&
755
            TRY(hand,
756
                /* allocate errhp */
757
                OCIHandleAlloc((dvoid *)hand->envhp, (dvoid **)&hand->errhp,
758
                               (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0)) &&
759
            TRY(hand,
760
                /* logon */
761
                OCILogon(hand->envhp, hand->errhp, &hand->svchp,
762
                         (text *)username, strlen(username), (text *)password,
763
                         strlen(password), (text *)dblink, strlen(dblink)));
764
765
  if (!success) {
766
    msDebug("Cannot create OCI Handlers. "
767
            "Connection failure."
768
            "Error: %s."
769
            "msOracleSpatialLayerOpen()\n",
770
            hand->last_oci_error);
771
    msSetError(
772
        MS_ORACLESPATIALERR,
773
        "Cannot create OCI Handlers. "
774
        "Connection failure. Check your logs and the connection string. ",
775
        "msOracleSpatialLayerOpen()");
776
777
    msOCICloseHandlers(hand);
778
    return NULL;
779
  }
780
781
  return hand;
782
}
783
784
/* disconnect from database */
785
static void msOCICloseHandlers(msOracleSpatialHandler *hand) {
786
  if (hand->svchp != NULL)
787
    OCILogoff(hand->svchp, hand->errhp);
788
  if (hand->errhp != NULL)
789
    OCIHandleFree((dvoid *)hand->errhp, (ub4)OCI_HTYPE_ERROR);
790
  if (hand->envhp != NULL)
791
    OCIHandleFree((dvoid *)hand->envhp, (ub4)OCI_HTYPE_ENV);
792
  if (hand != NULL)
793
    memset(hand, 0, sizeof(msOracleSpatialHandler));
794
  free(hand);
795
}
796
797
static void msOCICloseDataHandlers(msOracleSpatialDataHandler *dthand) {
798
  if (dthand->dschp != NULL)
799
    OCIHandleFree((dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE);
800
  if (dthand != NULL)
801
    memset(dthand, 0, sizeof(msOracleSpatialDataHandler));
802
  free(dthand);
803
}
804
805
static void msOCIClearLayerInfo(msOracleSpatialLayerInfo *layerinfo) {
806
  if (layerinfo != NULL) {
807
    memset(layerinfo, 0, sizeof(msOracleSpatialLayerInfo));
808
    free(layerinfo);
809
  }
810
}
811
812
/*function that creates the correct sql for geoditical srid for version 9i*/
813
static char *osGeodeticData(int function, char *query_str,
814
                            char *geom_column_name, char *index_column_name) {
815
  char *filter_field =
816
      index_column_name[0] == '\0' ? geom_column_name : index_column_name;
817
  switch (function) {
818
  case FUNCTION_FILTER: {
819
    query_str = msStringConcatenate(query_str, "SDO_FILTER( ");
820
    query_str = msStringConcatenate(query_str, filter_field);
821
    query_str = msStringConcatenate(
822
        query_str, ", SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY("
823
                   "2003, 0, NULL,"
824
                   "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),"
825
                   ":ordinates ), :srid),"
826
                   "'querytype=window') = 'TRUE'");
827
    break;
828
  }
829
  case FUNCTION_RELATE: {
830
    query_str = msStringConcatenate(query_str, "SDO_RELATE( ");
831
    query_str = msStringConcatenate(query_str, filter_field);
832
    query_str = msStringConcatenate(
833
        query_str, ", SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY("
834
                   "2003, 0, NULL,"
835
                   "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),"
836
                   ":ordinates ), :srid),"
837
                   "'mask=anyinteract querytype=window') = 'TRUE'");
838
    break;
839
  }
840
  case FUNCTION_GEOMRELATE: {
841
    char tmpFloat[256];
842
    snprintf(tmpFloat, sizeof(tmpFloat), "%f", TOLERANCE);
843
844
    query_str = msStringConcatenate(query_str, "SDO_GEOM.RELATE( ");
845
    query_str = msStringConcatenate(query_str, filter_field);
846
    query_str = msStringConcatenate(
847
        query_str, ", SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY("
848
                   "2003, 0, NULL,"
849
                   "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),"
850
                   ":ordinates), :srid),");
851
    query_str = msStringConcatenate(query_str, tmpFloat);
852
    query_str = msStringConcatenate(query_str, ") = 'TRUE' AND ");
853
    query_str = msStringConcatenate(query_str, geom_column_name);
854
    query_str = msStringConcatenate(query_str, " IS NOT NULL");
855
    break;
856
  }
857
  case FUNCTION_NONE: {
858
    break;
859
  }
860
  default: {
861
    query_str = msStringConcatenate(query_str, "SDO_FILTER( ");
862
    query_str = msStringConcatenate(query_str, filter_field);
863
    query_str = msStringConcatenate(
864
        query_str, ", SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY("
865
                   "2003, 0, NULL,"
866
                   "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),"
867
                   ":ordinates), :srid),"
868
                   "'querytype=window') = 'TRUE'");
869
  }
870
  }
871
  return query_str;
872
}
873
874
/*function that generate the correct sql for no geoditic srid's*/
875
static char *osNoGeodeticData(int function, int version, char *query_str,
876
                              char *geom_column_name, char *index_column_name) {
877
  char *filter_field =
878
      index_column_name[0] == '\0' ? geom_column_name : index_column_name;
879
  switch (function) {
880
  case FUNCTION_FILTER: {
881
    query_str = msStringConcatenate(query_str, "SDO_FILTER( ");
882
    query_str = msStringConcatenate(query_str, filter_field);
883
    query_str = msStringConcatenate(
884
        query_str, ", MDSYS.SDO_GEOMETRY("
885
                   "2003, :srid, NULL,"
886
                   "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),"
887
                   /*   "MDSYS.SDO_ORDINATE_ARRAY(%.9g,%.9g,%.9g,%.9g)" */
888
                   ":ordinates"
889
                   " ),'querytype=window') = 'TRUE'");
890
    break;
891
  }
892
  case FUNCTION_RELATE: {
893
    if (version == VERSION_10g) {
894
      query_str = msStringConcatenate(query_str, "SDO_ANYINTERACT( ");
895
      query_str = msStringConcatenate(query_str, filter_field);
896
      query_str =
897
          msStringConcatenate(query_str, ", MDSYS.SDO_GEOMETRY("
898
                                         "2003, :srid, NULL,"
899
                                         "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),"
900
                                         ":ordinates)) = 'TRUE'");
901
    } else {
902
903
      query_str = msStringConcatenate(query_str, "SDO_RELATE( ");
904
      query_str = msStringConcatenate(query_str, geom_column_name);
905
      query_str = msStringConcatenate(
906
          query_str, ", MDSYS.SDO_GEOMETRY("
907
                     "2003, :srid, NULL,"
908
                     "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),"
909
                     ":ordinates),"
910
                     "'mask=anyinteract querytype=window') = 'TRUE'");
911
    }
912
    break;
913
  }
914
  case FUNCTION_GEOMRELATE: {
915
    char tmpFloat[256];
916
    snprintf(tmpFloat, sizeof(tmpFloat), "%f", TOLERANCE);
917
918
    query_str = msStringConcatenate(query_str, "SDO_GEOM.RELATE( ");
919
    query_str = msStringConcatenate(query_str, index_column_name);
920
    query_str =
921
        msStringConcatenate(query_str, ", 'anyinteract', MDSYS.SDO_GEOMETRY("
922
                                       "2003, :srid, NULL,"
923
                                       "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),"
924
                                       ":ordinates),");
925
    query_str = msStringConcatenate(query_str, tmpFloat);
926
    query_str = msStringConcatenate(query_str, ") = 'TRUE' AND ");
927
    query_str = msStringConcatenate(query_str, geom_column_name);
928
    query_str = msStringConcatenate(query_str, " IS NOT NULL");
929
    break;
930
  }
931
  case FUNCTION_NONE: {
932
    break;
933
  }
934
  default: {
935
    query_str = msStringConcatenate(query_str, "SDO_FILTER( ");
936
    query_str = msStringConcatenate(query_str, filter_field);
937
    query_str =
938
        msStringConcatenate(query_str, ", MDSYS.SDO_GEOMETRY("
939
                                       "2003, :srid, NULL,"
940
                                       "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),"
941
                                       ":ordinates),"
942
                                       "'querytype=window') = 'TRUE'");
943
  }
944
  }
945
  return query_str;
946
}
947
948
/* get ordinates from SDO buffer */
949
static int msOCIGet2DOrdinates(msOracleSpatialHandler *hand,
950
                               SDOGeometryObj *obj, int s, int e,
951
                               pointObj *pt) {
952
  double x, y;
953
  int i, n, success = 1;
954
  boolean exists;
955
  OCINumber *oci_number;
956
957
  for (i = s, n = 0; i < e && success; i += 2, n++) {
958
    success = TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
959
                                       (OCIColl *)obj->ordinates, (sb4)i,
960
                                       (boolean *)&exists, (dvoid *)&oci_number,
961
                                       (dvoid **)0)) &&
962
              TRY(hand, OCINumberToReal(hand->errhp, oci_number,
963
                                        (uword)sizeof(double), (dvoid *)&x)) &&
964
              TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
965
                                       (OCIColl *)obj->ordinates, (sb4)i + 1,
966
                                       (boolean *)&exists, (dvoid *)&oci_number,
967
                                       (dvoid **)0)) &&
968
              TRY(hand, OCINumberToReal(hand->errhp, oci_number,
969
                                        (uword)sizeof(double), (dvoid *)&y));
970
971
    if (success) {
972
      pt[n].x = x;
973
      pt[n].y = y;
974
    }
975
  }
976
977
  return success ? n : 0;
978
}
979
980
static int msOCIGet3DOrdinates(msOracleSpatialHandler *hand,
981
                               SDOGeometryObj *obj, int s, int e,
982
                               pointObj *pt) {
983
  double x, y;
984
  int i, n, success = 1;
985
  boolean exists;
986
  double z;
987
  boolean numnull;
988
  OCINumber *oci_number;
989
990
  for (i = s, n = 0; i < e && success; i += 3, n++) {
991
    success = TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
992
                                       (OCIColl *)obj->ordinates, (sb4)i,
993
                                       (boolean *)&exists, (dvoid *)&oci_number,
994
                                       (dvoid **)0)) &&
995
              TRY(hand, OCINumberToReal(hand->errhp, oci_number,
996
                                        (uword)sizeof(double), (dvoid *)&x)) &&
997
              TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
998
                                       (OCIColl *)obj->ordinates, (sb4)i + 1,
999
                                       (boolean *)&exists, (dvoid *)&oci_number,
1000
                                       (dvoid **)0)) &&
1001
              TRY(hand, OCINumberToReal(hand->errhp, oci_number,
1002
                                        (uword)sizeof(double), (dvoid *)&y)) &&
1003
              TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
1004
                                       (OCIColl *)obj->ordinates, (sb4)i + 2,
1005
                                       (boolean *)&exists, (dvoid *)&oci_number,
1006
                                       (dvoid **)0));
1007
    if (success) {
1008
      success = TRY(
1009
          hand, OCINumberIsZero(hand->errhp, oci_number, (boolean *)&numnull));
1010
      if (success) {
1011
        success =
1012
            TRY(hand, OCINumberToReal(hand->errhp, oci_number,
1013
                                      (uword)sizeof(double), (dvoid *)&z));
1014
      } else {
1015
        hand->last_oci_status = MS_SUCCESS;
1016
        strlcpy((char *)hand->last_oci_error,
1017
                "Retrieve z value, but NULL value for z. Setting z to 0.",
1018
                sizeof(hand->last_oci_error));
1019
        z = 0;
1020
        success = 1;
1021
      }
1022
    }
1023
    if (success) {
1024
      pt[n].x = x;
1025
      pt[n].y = y;
1026
      pt[n].z = z;
1027
    }
1028
  }
1029
1030
  return success ? n : 0;
1031
}
1032
1033
static int msOCIGet4DOrdinates(msOracleSpatialHandler *hand,
1034
                               SDOGeometryObj *obj, int s, int e,
1035
                               pointObj *pt) {
1036
  double x, y;
1037
  int i, n, success = 1;
1038
  boolean exists;
1039
  double z;
1040
  boolean numnull;
1041
  OCINumber *oci_number;
1042
1043
  for (i = s, n = 0; i < e && success; i += 4, n++) {
1044
    success = TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
1045
                                       (OCIColl *)obj->ordinates, (sb4)i,
1046
                                       (boolean *)&exists, (dvoid *)&oci_number,
1047
                                       (dvoid **)0)) &&
1048
              TRY(hand, OCINumberToReal(hand->errhp, oci_number,
1049
                                        (uword)sizeof(double), (dvoid *)&x)) &&
1050
              TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
1051
                                       (OCIColl *)obj->ordinates, (sb4)i + 1,
1052
                                       (boolean *)&exists, (dvoid *)&oci_number,
1053
                                       (dvoid **)0)) &&
1054
              TRY(hand, OCINumberToReal(hand->errhp, oci_number,
1055
                                        (uword)sizeof(double), (dvoid *)&y)) &&
1056
              TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
1057
                                       (OCIColl *)obj->ordinates, (sb4)i + 2,
1058
                                       (boolean *)&exists, (dvoid *)&oci_number,
1059
                                       (dvoid **)0));
1060
1061
    if (success) {
1062
      success = TRY(
1063
          hand, OCINumberIsZero(hand->errhp, oci_number, (boolean *)&numnull));
1064
      if (success) {
1065
        success =
1066
            TRY(hand, OCINumberToReal(hand->errhp, oci_number,
1067
                                      (uword)sizeof(double), (dvoid *)&z));
1068
      } else {
1069
        hand->last_oci_status = MS_SUCCESS;
1070
        strlcpy((char *)hand->last_oci_error,
1071
                "Retrieve z value, but NULL value for z. Setting z to 0.",
1072
                sizeof(hand->last_oci_error));
1073
        z = 0;
1074
        success = 1;
1075
      }
1076
    }
1077
1078
    if (success) {
1079
      pt[n].x = x;
1080
      pt[n].y = y;
1081
      pt[n].z = z;
1082
    }
1083
  }
1084
  return success ? n : 0;
1085
}
1086
1087
/* convert three-point circle to two-point rectangular bounds */
1088
static int msOCIConvertCircle(pointObj *pt) {
1089
  pointObj ptaux;
1090
  double dXa, dXb;
1091
  double ma, mb;
1092
  double cx, cy, r;
1093
  int success;
1094
1095
  dXa = pt[1].x - pt[0].x;
1096
  success = (fabs(dXa) > 1e-8);
1097
  if (!success) {
1098
    /* switch points 1 & 2 */
1099
    ptaux = pt[1];
1100
    pt[1] = pt[2];
1101
    pt[2] = ptaux;
1102
    dXa = pt[1].x - pt[0].x;
1103
    success = (fabs(dXa) > 1e-8);
1104
  }
1105
  if (success) {
1106
    dXb = pt[2].x - pt[1].x;
1107
    success = (fabs(dXb) > 1e-8);
1108
    if (!success) {
1109
      /* insert point 2 before point 0 */
1110
      ptaux = pt[2];
1111
      pt[2] = pt[1];
1112
      pt[1] = pt[0];
1113
      pt[0] = ptaux;
1114
      dXb = dXa;               /* segment A has become B */
1115
      dXa = pt[1].x - pt[0].x; /* recalculate new segment A */
1116
      success = (fabs(dXa) > 1e-8);
1117
    }
1118
  }
1119
  if (success) {
1120
    ma = (pt[1].y - pt[0].y) / dXa;
1121
    mb = (pt[2].y - pt[1].y) / dXb;
1122
    success = (fabs(mb - ma) > 1e-8);
1123
  }
1124
  if (!success)
1125
    return 0;
1126
1127
  /* calculate center and radius */
1128
  cx = (ma * mb * (pt[0].y - pt[2].y) + mb * (pt[0].x + pt[1].x) -
1129
        ma * (pt[1].x + pt[2].x)) /
1130
       (2 * (mb - ma));
1131
  cy = (fabs(ma) > 1e-8)
1132
           ? ((pt[0].y + pt[1].y) / 2 - (cx - (pt[0].x + pt[1].x) / 2) / ma)
1133
           : ((pt[1].y + pt[2].y) / 2 - (cx - (pt[1].x + pt[2].x) / 2) / mb);
1134
1135
  r = sqrt(pow(pt[0].x - cx, 2) + pow(pt[0].y - cy, 2));
1136
1137
  /* update pt buffer with rectangular bounds */
1138
  pt[0].x = cx - r;
1139
  pt[0].y = cy - r;
1140
  pt[1].x = cx + r;
1141
  pt[1].y = cy + r;
1142
1143
  return 1;
1144
}
1145
1146
/*function that creates the correct sql for filter and filteritem*/
1147
static char *osFilteritem(layerObj *layer, int function, char *query_str,
1148
                          int mode) {
1149
  if (layer->filter.native_string != NULL) {
1150
    if (mode == 1) {
1151
      query_str = msStringConcatenate(query_str, " WHERE ");
1152
    } else {
1153
      query_str = msStringConcatenate(query_str, " AND ");
1154
    }
1155
    size_t tmpBufSize =
1156
        (strlen(layer->filter.native_string) + 3) * sizeof(char);
1157
    char *tmpBuf = (char *)msSmallMalloc(tmpBufSize);
1158
    snprintf(tmpBuf, tmpBufSize, " %s ", layer->filter.native_string);
1159
1160
    query_str = msStringConcatenate(query_str, tmpBuf);
1161
    msFree(tmpBuf);
1162
1163
    if (function != FUNCTION_NONE) {
1164
      query_str = msStringConcatenate(query_str, " AND ");
1165
    }
1166
  } else {
1167
    if (function != FUNCTION_NONE) {
1168
      query_str = msStringConcatenate(query_str, " WHERE ");
1169
    }
1170
  }
1171
1172
  /* Handle a native filter set as a PROCESSING option (#5001). */
1173
  if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) {
1174
    if ((function == FUNCTION_NONE) && (layer->filter.native_string == NULL)) {
1175
      query_str = msStringConcatenate(query_str, " WHERE ");
1176
    }
1177
    if ((function == FUNCTION_NONE) && (layer->filter.native_string != NULL)) {
1178
      query_str = msStringConcatenate(query_str, " AND ");
1179
    }
1180
    size_t tmpSz;
1181
1182
    const char *native_filter = msLayerGetProcessingKey(layer, "NATIVE_FILTER");
1183
    char *tmpBuf = NULL;
1184
1185
    tmpSz = sizeof(char) * (strlen(native_filter) + 2 + 1);
1186
    tmpBuf = msSmallMalloc(tmpSz);
1187
1188
    snprintf(tmpBuf, tmpSz, " %s ", native_filter);
1189
    query_str = msStringConcatenate(query_str, tmpBuf);
1190
    msFree(tmpBuf);
1191
1192
    if (function != FUNCTION_NONE) {
1193
      query_str = msStringConcatenate(query_str, " AND ");
1194
    }
1195
  }
1196
  return query_str;
1197
}
1198
1199
static char *osAggrGetExtent(layerObj *layer, char *query_str,
1200
                             char *geom_column_name, char *table_name) {
1201
  char *query_str2 = NULL;
1202
  int i = 0;
1203
1204
  query_str2 = msStringConcatenate(query_str2, "(SELECT");
1205
1206
  for (i = 0; i < layer->numitems; ++i) {
1207
    size_t tmpSize = sizeof(char) * (strlen(layer->items[i]) + 1 /* '\0' */ +
1208
                                     2 /* " ", "," */);
1209
    char *tmpItem = (char *)msSmallMalloc(tmpSize);
1210
    snprintf(tmpItem, tmpSize, " %s,", layer->items[i]);
1211
1212
    query_str2 = msStringConcatenate(query_str2, tmpItem);
1213
1214
    msFree(tmpItem);
1215
  }
1216
1217
  size_t tmpFromSize =
1218
      sizeof(char) * (7 + strlen(geom_column_name) + strlen(table_name) + 1);
1219
  char *tmpFrom = msSmallMalloc(tmpFromSize);
1220
  snprintf(tmpFrom, tmpFromSize, " %s FROM %s", geom_column_name, table_name);
1221
1222
  query_str2 = msStringConcatenate(query_str2, tmpFrom);
1223
1224
  msFree(tmpFrom);
1225
1226
  query_str2 = osFilteritem(layer, FUNCTION_NONE, query_str2, 1);
1227
1228
  query_str = msStringConcatenate(query_str, "SELECT SDO_AGGR_MBR(");
1229
  query_str = msStringConcatenate(query_str, geom_column_name);
1230
  query_str = msStringConcatenate(query_str, ") AS GEOM from ");
1231
  query_str = msStringConcatenate(query_str, query_str2);
1232
  query_str = msStringConcatenate(query_str, ")");
1233
1234
  msFree(query_str2);
1235
1236
  if (layer->debug)
1237
    msDebug("osAggrGetExtent was called: %s.\n", query_str);
1238
1239
  return query_str;
1240
}
1241
1242
static double osCalculateArcRadius(pointObj *pnt) {
1243
  double rc;
1244
  double r1, r2, r3;
1245
1246
  r1 = sqrt(pow(pnt[0].x - pnt[1].x, 2) + pow(pnt[0].y - pnt[1].y, 2));
1247
  r2 = sqrt(pow(pnt[1].x - pnt[2].x, 2) + pow(pnt[1].y - pnt[2].y, 2));
1248
  r3 = sqrt(pow(pnt[2].x - pnt[0].x, 2) + pow(pnt[2].y - pnt[0].y, 2));
1249
  rc = (r1 + r2 + r3) / 2;
1250
1251
  return ((r1 * r2 * r3) / (4 * sqrt(rc * (rc - r1) * (rc - r2) * (rc - r3))));
1252
}
1253
1254
static void osCalculateArc(pointObj *pnt, int data3d, int data4d, double radius,
1255
                           double npoints, int side, lineObj arcline,
1256
                           shapeObj *shape) {
1257
  double length, ctrl, angle;
1258
  double divbas, plusbas, cosbas, sinbas = 0;
1259
  double zrange = 0;
1260
  int i = 0;
1261
1262
  if (npoints > 0) {
1263
    length = sqrt(((pnt[1].x - pnt[0].x) * (pnt[1].x - pnt[0].x)) +
1264
                  ((pnt[1].y - pnt[0].y) * (pnt[1].y - pnt[0].y)));
1265
    ctrl = length / (2 * radius);
1266
1267
    if (data3d || data4d) {
1268
      /* is this cast (long) legit... ? */
1269
      zrange = labs((long)(pnt[0].z - pnt[1].z)) / npoints;
1270
      if ((pnt[0].z > pnt[1].z) && side == 1)
1271
        zrange *= -1;
1272
      else if ((pnt[0].z < pnt[1].z) && side == 1)
1273
        zrange = zrange;
1274
      else if ((pnt[0].z > pnt[1].z) && side != 1)
1275
        zrange *= -1;
1276
      else if ((pnt[0].z < pnt[1].z) && side != 1)
1277
        zrange = zrange;
1278
    }
1279
1280
    if (ctrl <= 1) {
1281
      divbas = 2 * asin(ctrl);
1282
      plusbas = divbas / (npoints);
1283
      cosbas = (pnt[0].x - pnt[3].x) / radius;
1284
      sinbas = (pnt[0].y - pnt[3].y) / radius;
1285
      angle = plusbas;
1286
1287
      arcline.point = (pointObj *)malloc(sizeof(pointObj) * (npoints + 1));
1288
      arcline.point[0].x = pnt[0].x;
1289
      arcline.point[0].y = pnt[0].y;
1290
      if (data3d || data4d)
1291
        arcline.point[0].z = pnt[0].z;
1292
1293
      for (i = 1; i <= npoints; i++) {
1294
        if (side == 1) {
1295
          arcline.point[i].x = pnt[3].x + radius * ((cosbas * cos(angle)) -
1296
                                                    (sinbas * sin(angle)));
1297
          arcline.point[i].y = pnt[3].y + radius * ((sinbas * cos(angle)) +
1298
                                                    (cosbas * sin(angle)));
1299
          if (data3d || data4d)
1300
            arcline.point[i].z = pnt[0].z + (zrange * i);
1301
        } else {
1302
          if (side == -1) {
1303
            arcline.point[i].x = pnt[3].x + radius * ((cosbas * cos(angle)) +
1304
                                                      (sinbas * sin(angle)));
1305
            arcline.point[i].y = pnt[3].y + radius * ((sinbas * cos(angle)) -
1306
                                                      (cosbas * sin(angle)));
1307
            if (data3d || data4d)
1308
              arcline.point[i].z = pnt[0].z + (zrange * i);
1309
          } else {
1310
            arcline.point[i].x = pnt[0].x;
1311
            arcline.point[i].y = pnt[0].y;
1312
            if (data3d || data4d)
1313
              arcline.point[i].z = pnt[0].z;
1314
          }
1315
        }
1316
        angle += plusbas;
1317
      }
1318
1319
      arcline.numpoints = npoints + 1;
1320
      msAddLine(shape, &arcline);
1321
      free(arcline.point);
1322
    }
1323
  } else {
1324
    arcline.point = (pointObj *)malloc(sizeof(pointObj) * (2));
1325
    arcline.point[0].x = pnt[0].x;
1326
    arcline.point[0].y = pnt[0].y;
1327
    arcline.point[1].x = pnt[1].x;
1328
    arcline.point[1].y = pnt[1].y;
1329
1330
    if (data3d || data4d) {
1331
      arcline.point[0].z = pnt[0].z;
1332
      arcline.point[1].z = pnt[1].z;
1333
    }
1334
1335
    arcline.numpoints = 2;
1336
1337
    msAddLine(shape, &arcline);
1338
    free(arcline.point);
1339
  }
1340
}
1341
1342
/* Part of this function was based on Terralib function TeGenerateArc
1343
 * found in TeGeometryAlgorithm.cpp (www.terralib.org).
1344
 * Part of this function was based on Dr. Ialo (Univali/Cttmar) functions. */
1345
static void osGenerateArc(shapeObj *shape, lineObj arcline, lineObj points,
1346
                          int i, int data3d, int data4d) {
1347
  double mult, plus1, plus2, plus3, bpoint;
1348
  double cx, cy;
1349
  double radius, side, area, npoints;
1350
  double dist1 = 0;
1351
  double dist2 = 0;
1352
  pointObj point5[4];
1353
1354
  mult = (points.point[i + 1].x - points.point[i].x) *
1355
             (points.point[i + 2].y - points.point[i].y) -
1356
         (points.point[i + 1].y - points.point[i].y) *
1357
             (points.point[i + 2].x - points.point[i].x);
1358
1359
  if (mult) {
1360
    /*point5 = (pointObj *)malloc(sizeof(pointObj)*(4));*/
1361
1362
    plus1 = points.point[i].x * points.point[i].x +
1363
            points.point[i].y * points.point[i].y;
1364
    plus2 = points.point[i + 1].x * points.point[i + 1].x +
1365
            points.point[i + 1].y * points.point[i + 1].y;
1366
    plus3 = points.point[i + 2].x * points.point[i + 2].x +
1367
            points.point[i + 2].y * points.point[i + 2].y;
1368
1369
    bpoint = plus1 * (points.point[i + 1].y - points.point[i + 2].y) +
1370
             plus2 * (points.point[i + 2].y - points.point[i].y) +
1371
             plus3 * (points.point[i].y - points.point[i + 1].y);
1372
1373
    cx = bpoint / (2.0 * mult);
1374
1375
    bpoint = plus1 * (points.point[i + 2].x - points.point[i + 1].x) +
1376
             plus2 * (points.point[i].x - points.point[i + 2].x) +
1377
             plus3 * (points.point[i + 1].x - points.point[i].x);
1378
1379
    cy = bpoint / (2.0 * mult);
1380
1381
    dist1 =
1382
        (points.point[i + 1].x - points.point[i].x) * (cy - points.point[i].y);
1383
    dist2 =
1384
        (points.point[i + 1].y - points.point[i].y) * (cx - points.point[i].x);
1385
    side = 0;
1386
1387
    if ((dist1 - dist2) > 0)
1388
      side = 1;
1389
    else {
1390
      if ((dist1 - dist2) < 0)
1391
        side = -1;
1392
    }
1393
1394
    point5[0] = points.point[i];
1395
    point5[1] = points.point[i + 1];
1396
    point5[2] = points.point[i + 2];
1397
    point5[3].x = cx;
1398
    point5[3].y = cy;
1399
1400
    radius = osCalculateArcRadius(point5);
1401
1402
    area = ((points.point[i].x + points.point[i + 1].x) *
1403
            (points.point[i + 1].y - points.point[i].y)) +
1404
           ((points.point[i + 1].x + points.point[i + 2].x) *
1405
            (points.point[i + 2].y - points.point[i + 1].y));
1406
1407
    npoints = labs((long)(area / radius));
1408
1409
    point5[0] = points.point[i];
1410
    point5[1] = points.point[i + 1];
1411
    osCalculateArc(point5, data3d, data4d, radius,
1412
                   (npoints > 1000) ? 1000 : npoints, side, arcline, shape);
1413
1414
    point5[0] = points.point[i + 1];
1415
    point5[1] = points.point[i + 2];
1416
    osCalculateArc(point5, data3d, data4d, radius,
1417
                   (npoints > 1000) ? 1000 : npoints, side, arcline, shape);
1418
1419
  } else {
1420
    arcline.point = (pointObj *)malloc(sizeof(pointObj) * (2));
1421
    arcline.point[0].x = points.point[i].x;
1422
    arcline.point[0].y = points.point[i].y;
1423
    arcline.point[1].x = points.point[i + 2].x;
1424
    arcline.point[1].y = points.point[i + 2].y;
1425
1426
    if (data3d || data4d) {
1427
      arcline.point[0].z = points.point[i].z;
1428
      arcline.point[1].z = points.point[i + 2].z;
1429
    }
1430
1431
    arcline.numpoints = 2;
1432
1433
    msAddLine(shape, &arcline);
1434
    free(arcline.point);
1435
  }
1436
}
1437
1438
static void osShapeBounds(shapeObj *shp) {
1439
  int i, f;
1440
1441
  if ((shp->numlines > 0) && (shp->line[0].numpoints > 0)) {
1442
    shp->bounds.minx = shp->line[0].point[0].x;
1443
    shp->bounds.maxx = shp->line[0].point[0].x;
1444
    shp->bounds.miny = shp->line[0].point[0].y;
1445
    shp->bounds.maxy = shp->line[0].point[0].y;
1446
  }
1447
1448
  for (i = 0; i < shp->numlines; i++) {
1449
    for (f = 0; f < shp->line[i].numpoints; f++) {
1450
      if (shp->line[i].point[f].x < shp->bounds.minx)
1451
        shp->bounds.minx = shp->line[i].point[f].x;
1452
      if (shp->line[i].point[f].x > shp->bounds.maxx)
1453
        shp->bounds.maxx = shp->line[i].point[f].x;
1454
      if (shp->line[i].point[f].y < shp->bounds.miny)
1455
        shp->bounds.miny = shp->line[i].point[f].y;
1456
      if (shp->line[i].point[f].y > shp->bounds.maxy)
1457
        shp->bounds.maxy = shp->line[i].point[f].y;
1458
    }
1459
  }
1460
}
1461
1462
static void osCloneShape(shapeObj *shape, shapeObj *newshape, int data3d,
1463
                         int data4d) {
1464
  int max_points = 0;
1465
  int i, f, g;
1466
  lineObj shapeline = {0, NULL};
1467
1468
  for (i = 0; i < shape->numlines; i++)
1469
    max_points += shape->line[i].numpoints;
1470
1471
  if (max_points > 0)
1472
    shapeline.point = (pointObj *)malloc(sizeof(pointObj) * max_points);
1473
1474
  g = 0;
1475
  for (i = 0; i < shape->numlines; i++) {
1476
    for (f = 0; f < shape->line[i].numpoints && g <= max_points; f++, g++) {
1477
      shapeline.point[g].x = shape->line[i].point[f].x;
1478
      shapeline.point[g].y = shape->line[i].point[f].y;
1479
      if (data3d || data4d)
1480
        shapeline.point[g].z = shape->line[i].point[f].z;
1481
    }
1482
  }
1483
1484
  if (g) {
1485
    shapeline.numpoints = g;
1486
    newshape->type = shape->type; /* jimk: 2009/09/23 Fixes compound linestrings
1487
                                     being converted to polygons */
1488
    msAddLine(newshape, &shapeline);
1489
  }
1490
}
1491
1492
static void osPointCluster(msOracleSpatialHandler *hand, shapeObj *shape,
1493
                           SDOGeometryObj *obj, int start, int end,
1494
                           lineObj points, int interpretation, int data3d,
1495
                           int data4d) {
1496
  int n;
1497
1498
  n = (end - start) / 2;
1499
  /* n = interpretation; */
1500
1501
  /* if (n == interpretation) { */
1502
  points.point = (pointObj *)malloc(sizeof(pointObj) * n);
1503
1504
  if (data3d)
1505
    n = msOCIGet3DOrdinates(hand, obj, start, end, points.point);
1506
  else if (data4d)
1507
    n = msOCIGet4DOrdinates(hand, obj, start, end, points.point);
1508
  else
1509
    n = msOCIGet2DOrdinates(hand, obj, start, end, points.point);
1510
1511
  if (n == interpretation && n > 0) {
1512
    shape->type = MS_SHAPE_POINT;
1513
    points.numpoints = n;
1514
    msAddLine(shape, &points);
1515
  }
1516
  free(points.point);
1517
  /* } */
1518
}
1519
1520
static void osPoint(msOracleSpatialHandler *hand, shapeObj *shape,
1521
                    SDOGeometryObj *obj, int start, int end, lineObj points,
1522
                    pointObj *pnt, int data3d, int data4d) {
1523
  int n;
1524
1525
  if (data3d)
1526
    n = msOCIGet3DOrdinates(hand, obj, start, end, pnt);
1527
  else if (data4d)
1528
    n = msOCIGet4DOrdinates(hand, obj, start, end, pnt);
1529
  else
1530
    n = msOCIGet2DOrdinates(hand, obj, start, end, pnt); /* n must be < 5 */
1531
1532
  if (n == 1) {
1533
    shape->type = MS_SHAPE_POINT;
1534
    points.numpoints = 1;
1535
    points.point = pnt;
1536
    msAddLine(shape, &points);
1537
  }
1538
}
1539
1540
static void osClosedPolygon(msOracleSpatialHandler *hand, shapeObj *shape,
1541
                            SDOGeometryObj *obj, int start, int end,
1542
                            lineObj points, int elem_type, int data3d,
1543
                            int data4d) {
1544
  int n;
1545
1546
  n = (end - start) / 2;
1547
  points.point = (pointObj *)malloc(sizeof(pointObj) * n);
1548
1549
  if (data3d)
1550
    n = msOCIGet3DOrdinates(hand, obj, start, end, points.point);
1551
  else if (data4d)
1552
    n = msOCIGet4DOrdinates(hand, obj, start, end, points.point);
1553
  else
1554
    n = msOCIGet2DOrdinates(hand, obj, start, end, points.point);
1555
1556
  if (n > 0) {
1557
    shape->type = (elem_type == 21) ? MS_SHAPE_LINE : MS_SHAPE_POLYGON;
1558
    points.numpoints = n;
1559
    msAddLine(shape, &points);
1560
  }
1561
  free(points.point);
1562
}
1563
1564
static void osRectangle(msOracleSpatialHandler *hand, shapeObj *shape,
1565
                        SDOGeometryObj *obj, int start, int end, lineObj points,
1566
                        pointObj *pnt, int data3d, int data4d) {
1567
  int n;
1568
1569
  if (data3d)
1570
    n = msOCIGet3DOrdinates(hand, obj, start, end, pnt); /* n must be < 5 */
1571
  else if (data4d)
1572
    n = msOCIGet4DOrdinates(hand, obj, start, end, pnt); /* n must be < 5 */
1573
  else
1574
    n = msOCIGet2DOrdinates(hand, obj, start, end, pnt); /* n must be < 5 */
1575
1576
  if (n == 2) {
1577
    shape->type = MS_SHAPE_POLYGON;
1578
    points.numpoints = 5;
1579
    points.point = pnt;
1580
1581
    /* point5 [0] & [1] contains the lower-left and upper-right points of the
1582
     * rectangle */
1583
    pnt[2] = pnt[1];
1584
    pnt[1].x = pnt[0].x;
1585
    pnt[3].x = pnt[2].x;
1586
    pnt[3].y = pnt[0].y;
1587
    pnt[4] = pnt[0];
1588
    if (data3d || data4d) {
1589
      pnt[1].z = pnt[0].z;
1590
      pnt[3].z = pnt[2].z;
1591
    }
1592
1593
    msAddLine(shape, &points);
1594
  }
1595
}
1596
1597
static void osCircle(msOracleSpatialHandler *hand, shapeObj *shape,
1598
                     SDOGeometryObj *obj, int start, int end, lineObj points,
1599
                     pointObj *pnt, int data3d, int data4d) {
1600
  int n;
1601
1602
  if (data3d)
1603
    n = msOCIGet3DOrdinates(hand, obj, start, end, pnt); /* n must be < 5 */
1604
  else if (data4d)
1605
    n = msOCIGet4DOrdinates(hand, obj, start, end, pnt); /* n must be < 5 */
1606
  else
1607
    n = msOCIGet2DOrdinates(hand, obj, start, end, pnt); /* n must be < 5 */
1608
1609
  if (n == 3) {
1610
    if (msOCIConvertCircle(pnt)) {
1611
      shape->type = MS_SHAPE_POINT;
1612
      points.numpoints = 2;
1613
      points.point = pnt;
1614
      msAddLine(shape, &points);
1615
    } else {
1616
      strlcpy((char *)hand->last_oci_error,
1617
              "Points in circle object are colinear",
1618
              sizeof(hand->last_oci_error));
1619
      hand->last_oci_status = MS_FAILURE;
1620
    }
1621
  }
1622
}
1623
1624
static void osArcPolygon(msOracleSpatialHandler *hand, shapeObj *shape,
1625
                         SDOGeometryObj *obj, int start, int end,
1626
                         lineObj arcpoints, int elem_type, int data3d,
1627
                         int data4d) {
1628
  int n, i;
1629
  lineObj points = {0, NULL};
1630
1631
  n = (end - start) / 2;
1632
  points.point = (pointObj *)malloc(sizeof(pointObj) * n);
1633
1634
  if (data3d)
1635
    n = msOCIGet3DOrdinates(hand, obj, start, end, points.point);
1636
  else if (data4d)
1637
    n = msOCIGet4DOrdinates(hand, obj, start, end, points.point);
1638
  else
1639
    n = msOCIGet2DOrdinates(hand, obj, start, end, points.point);
1640
1641
  if (n > 2) {
1642
    shape->type = (elem_type == 32) ? MS_SHAPE_POLYGON : MS_SHAPE_LINE;
1643
    points.numpoints = n;
1644
1645
    for (i = 0; i < n - 2; i = i + 2)
1646
      osGenerateArc(shape, arcpoints, points, i, data3d, data4d);
1647
  }
1648
  free(points.point);
1649
}
1650
1651
static int osCheck2DGtype(int pIntGtype) {
1652
  if (pIntGtype > 2000 && pIntGtype < 2008) {
1653
    if (pIntGtype != 2004)
1654
      return MS_TRUE;
1655
  }
1656
1657
  return MS_FALSE;
1658
}
1659
1660
static int osCheck3DGtype(int pIntGtype) {
1661
  if (pIntGtype > 3000 && pIntGtype < 3308) {
1662
    if (pIntGtype > 3007)
1663
      pIntGtype -= 300;
1664
1665
    if (pIntGtype <= 3007 && pIntGtype != 3004)
1666
      return MS_TRUE;
1667
  }
1668
  /*
1669
   * Future version, untested
1670
   * return (pIntGtype & 2208 && (pIntGtype & 3000 || pIntGtype & 3296) &&
1671
   * pIntGtype & 3);
1672
   */
1673
  return MS_FALSE;
1674
}
1675
1676
static int osCheck4DGtype(int pIntGtype) {
1677
1678
  if (pIntGtype > 4000 && pIntGtype < 4408) {
1679
    if (pIntGtype > 4007)
1680
      pIntGtype -= 400;
1681
1682
    if (pIntGtype <= 4007 && pIntGtype != 4004)
1683
      return MS_TRUE;
1684
  }
1685
1686
  return MS_FALSE;
1687
}
1688
1689
static int osGetOrdinates(msOracleSpatialDataHandler *dthand,
1690
                          msOracleSpatialHandler *hand, shapeObj *shape,
1691
                          SDOGeometryObj *obj, SDOGeometryInd *ind) {
1692
  int gtype, elem_type, compound_type;
1693
  float compound_lenght, compound_count;
1694
  ub4 etype;
1695
  ub4 interpretation;
1696
  int nelems, nords, data3d, data4d;
1697
  int elem, ord_start, ord_end;
1698
  boolean exists;
1699
  OCINumber *oci_number;
1700
  double x, y;
1701
  double z;
1702
  int success;
1703
  lineObj points = {0, NULL};
1704
  pointObj point5[5]; /* for quick access */
1705
  shapeObj newshape;  /* for compound polygons */
1706
1707
  /*stat the variables for compound polygons*/
1708
  compound_lenght = 0;
1709
  compound_type = 0;
1710
  compound_count = -1;
1711
  data3d = 0;
1712
  data4d = 0;
1713
1714
  if (ind->_atomic != OCI_IND_NULL) { /* not a null object */
1715
    nelems = nords = 0;
1716
    success =
1717
        TRY(hand, OCICollSize(hand->envhp, hand->errhp,
1718
                              (OCIColl *)obj->elem_info, &nelems)) &&
1719
        TRY(hand, OCICollSize(hand->envhp, hand->errhp,
1720
                              (OCIColl *)obj->ordinates, &nords)) &&
1721
        TRY(hand, OCINumberToInt(hand->errhp, &(obj->gtype), (uword)sizeof(int),
1722
                                 OCI_NUMBER_SIGNED, (dvoid *)&gtype));
1723
    /*&& (nords%2==0 && nelems%3==0);*/ /* check %2==0 for 2D geometries; and
1724
                                           %3==0 for element info triplets */
1725
1726
    if (success && osCheck2DGtype(gtype)) {
1727
      success = (nords % 2 == 0 && nelems % 3 == 0)
1728
                    ? 1
1729
                    : 0; /* check %2==0 for 2D geometries; and %3==0 for element
1730
                            info triplets */
1731
    } else if (success && osCheck3DGtype(gtype)) {
1732
      success = (nords % 3 == 0 && nelems % 3 == 0)
1733
                    ? 1
1734
                    : 0; /* check %2==0 for 2D geometries; and %3==0 for element
1735
                            info triplets */
1736
      data3d = 1;
1737
1738
    } else if (success && osCheck4DGtype(gtype)) {
1739
      success = (nords % 4 == 0 && nelems % 3 == 0)
1740
                    ? 1
1741
                    : 0; /* check %2==0 for 2D geometries; and %3==0 for element
1742
                            info triplets */
1743
      data4d = 1;
1744
    }
1745
1746
    if (success) {
1747
      /* reading SDO_POINT from SDO_GEOMETRY for a 2D/3D point geometry */
1748
      if ((gtype == 2001 || gtype == 3001 || gtype == 4001) &&
1749
          ind->point._atomic == OCI_IND_NOTNULL &&
1750
          ind->point.x == OCI_IND_NOTNULL && ind->point.y == OCI_IND_NOTNULL) {
1751
1752
        success =
1753
            TRY(hand, OCINumberToReal(hand->errhp, &(obj->point.x),
1754
                                      (uword)sizeof(double), (dvoid *)&x)) &&
1755
            TRY(hand, OCINumberToReal(hand->errhp, &(obj->point.y),
1756
                                      (uword)sizeof(double), (dvoid *)&y));
1757
1758
        if (ERROR("osGetOrdinates()", hand, dthand))
1759
          return MS_FAILURE;
1760
1761
        shape->type = MS_SHAPE_POINT;
1762
1763
        points.numpoints = 1;
1764
        points.point = point5;
1765
        point5[0].x = x;
1766
        point5[0].y = y;
1767
        if (data3d || data4d) {
1768
          if (ind->point.z == OCI_IND_NOTNULL) {
1769
            success =
1770
                TRY(hand, OCINumberToReal(hand->errhp, &(obj->point.z),
1771
                                          (uword)sizeof(double), (dvoid *)&z));
1772
            if (ERROR("osGetOrdinates()", hand, dthand))
1773
              return MS_FAILURE;
1774
            else
1775
              point5[0].z = z;
1776
          } else
1777
            point5[0].z = z;
1778
        }
1779
        msAddLine(shape, &points);
1780
        return MS_SUCCESS;
1781
      }
1782
      /* if SDO_POINT not fetched, proceed reading elements (element
1783
       * info/ordinates) */
1784
      success =
1785
          TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
1786
                                   (OCIColl *)obj->elem_info, (sb4)0,
1787
                                   (boolean *)&exists, (dvoid *)&oci_number,
1788
                                   (dvoid **)0)) &&
1789
          TRY(hand, OCINumberToInt(hand->errhp, oci_number, (uword)sizeof(ub4),
1790
                                   OCI_NUMBER_SIGNED, (dvoid *)&ord_end));
1791
1792
      elem = 0;
1793
      ord_end--; /* shifts offset from 1..n to 0..n-1 */
1794
1795
      do {
1796
        ord_start = ord_end;
1797
        if (elem + 3 >= nelems) { /* processing last element */
1798
          ord_end = nords;
1799
          success = 1;
1800
        } else { /* get start ordinate position for next element which is
1801
                    ord_end for this element */
1802
          success =
1803
              TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
1804
                                       (OCIColl *)obj->elem_info, (sb4)elem + 3,
1805
                                       (boolean *)&exists, (dvoid *)&oci_number,
1806
                                       (dvoid **)0)) &&
1807
              TRY(hand,
1808
                  OCINumberToInt(hand->errhp, oci_number, (uword)sizeof(ub4),
1809
                                 OCI_NUMBER_SIGNED, (dvoid *)&ord_end));
1810
1811
          ord_end--; /* shifts offset from 1..n to 0..n-1 */
1812
        }
1813
        success =
1814
            (success &&
1815
             TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
1816
                                      (OCIColl *)obj->elem_info, (sb4)elem + 1,
1817
                                      (boolean *)&exists, (dvoid *)&oci_number,
1818
                                      (dvoid **)0)) &&
1819
             TRY(hand,
1820
                 OCINumberToInt(hand->errhp, oci_number, (uword)sizeof(ub4),
1821
                                OCI_NUMBER_UNSIGNED, (dvoid *)&etype)) &&
1822
             TRY(hand, OCICollGetElem(hand->envhp, hand->errhp,
1823
                                      (OCIColl *)obj->elem_info, (sb4)elem + 2,
1824
                                      (boolean *)&exists, (dvoid *)&oci_number,
1825
                                      (dvoid **)0)) &&
1826
             TRY(hand, OCINumberToInt(hand->errhp, oci_number,
1827
                                      (uword)sizeof(ub4), OCI_NUMBER_UNSIGNED,
1828
                                      (dvoid *)&interpretation)));
1829
1830
        if (ERROR("osGetOrdinates()", hand, dthand))
1831
          return MS_FAILURE;
1832
1833
        if (etype == 1005 || etype == 2005 || etype == 4) {
1834
          compound_type = 1;
1835
          compound_lenght = interpretation;
1836
          compound_count = 0;
1837
          msInitShape(&newshape);
1838
        }
1839
1840
        elem_type = (etype == 1 && interpretation > 1)
1841
                        ? 10
1842
                        : ((etype % 10) * 10 + interpretation);
1843
1844
        /* msDebug("osGetOrdinates shape->index = %ld\telem_type =
1845
         * %d\n",shape->index, elem_type); */
1846
1847
        switch (elem_type) {
1848
        case 10: /* point cluster with 'interpretation'-points */
1849
          osPointCluster(hand, shape, obj, ord_start, ord_end, points,
1850
                         interpretation, data3d, data4d);
1851
          break;
1852
        case 11: /* point type */
1853
          osPoint(hand, shape, obj, ord_start, ord_end, points, point5, data3d,
1854
                  data4d);
1855
          break;
1856
        case 21: /* line string whose vertices are connected by straight line
1857
                    segments */
1858
          if (compound_type)
1859
            osClosedPolygon(hand, &newshape, obj, ord_start,
1860
                            (compound_count < compound_lenght) ? ord_end + 2
1861
                                                               : ord_end,
1862
                            points, elem_type, data3d, data4d);
1863
          else
1864
            osClosedPolygon(hand, shape, obj, ord_start, ord_end, points,
1865
                            elem_type, data3d, data4d);
1866
          break;
1867
        case 22: /* compound type */
1868
          if (compound_type)
1869
            osArcPolygon(hand, &newshape, obj, ord_start,
1870
                         (compound_count < compound_lenght) ? ord_end + 2
1871
                                                            : ord_end,
1872
                         points, elem_type, data3d, data4d);
1873
          else
1874
            osArcPolygon(hand, shape, obj, ord_start, ord_end, points,
1875
                         elem_type, data3d, data4d);
1876
          break;
1877
        case 31: /* simple polygon with n points, last point equals the first
1878
                    one */
1879
          osClosedPolygon(hand, shape, obj, ord_start, ord_end, points,
1880
                          elem_type, data3d, data4d);
1881
          break;
1882
        case 32: /* Polygon with arcs */
1883
          osArcPolygon(hand, shape, obj, ord_start, ord_end, points, elem_type,
1884
                       data3d, data4d);
1885
          break;
1886
        case 33: /* rectangle defined by 2 points */
1887
          osRectangle(hand, shape, obj, ord_start, ord_end, points, point5,
1888
                      data3d, data4d);
1889
          break;
1890
        case 34: /* circle defined by 3 points */
1891
          osCircle(hand, shape, obj, ord_start, ord_end, points, point5, data3d,
1892
                   data4d);
1893
          break;
1894
        }
1895
1896
        if (compound_count >= compound_lenght) {
1897
          osCloneShape(&newshape, shape, data3d, data4d);
1898
          msFreeShape(&newshape);
1899
        }
1900
1901
        if (ERROR("osGetOrdinates()", hand, dthand))
1902
          return MS_FAILURE;
1903
1904
        /* prepare for next cycle */
1905
        ord_start = ord_end;
1906
        elem += 3;
1907
1908
        if (compound_type)
1909
          compound_count++;
1910
1911
      } while (elem < nelems); /* end of element loop */
1912
    }                          /* end of gtype big-if */
1913
  }                            /* end of not-null-object if */
1914
1915
  if (compound_type) {
1916
    if (gtype == 2003 || gtype == 2007)
1917
      shape->type = MS_SHAPE_POLYGON;
1918
    msFreeShape(&newshape);
1919
  }
1920
1921
  return MS_SUCCESS;
1922
}
1923
1924
static void msOCICloseConnection(void *hand) {
1925
  msOCICloseHandlers((msOracleSpatialHandler *)hand);
1926
}
1927
1928
/* opens a layer by connecting to db with username/password@database stored in
1929
 * layer->connection */
1930
int msOracleSpatialLayerOpen(layerObj *layer) {
1931
  char *username = NULL, *password = NULL, *dblink = NULL;
1932
1933
  msOracleSpatialLayerInfo *layerinfo = NULL;
1934
  msOracleSpatialDataHandler *dthand = NULL;
1935
  msOracleSpatialStatement *sthand = NULL, *sthand2 = NULL;
1936
  msOracleSpatialHandler *hand = NULL;
1937
1938
  if (layer->debug >= 2)
1939
    msDebug("msOracleSpatialLayerOpen called with: %s (Layer pointer %p)\n",
1940
            layer->data, layer);
1941
1942
  if (layer->layerinfo != NULL) /* Skip if layer is already open */
1943
    return MS_SUCCESS;
1944
1945
  if (layer->data == NULL) {
1946
    msDebug("Error parsing OracleSpatial DATA variable. Must be:"
1947
            "'geometry_column FROM table_name [USING UNIQUE <column> SRID "
1948
            "srid# FUNCTION]' or "
1949
            "'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> SRID "
1950
            "srid# FUNCTION]'."
1951
            "If want to set the FUNCTION statement you can use: FILTER, "
1952
            "RELATE, GEOMRELATE or NONE.\n");
1953
    msSetError(
1954
        MS_ORACLESPATIALERR,
1955
        "Error parsing OracleSpatial DATA variable. More info in server logs",
1956
        "msOracleSpatialLayerOpen()");
1957
1958
    return MS_FAILURE;
1959
  }
1960
1961
  layerinfo =
1962
      (msOracleSpatialLayerInfo *)malloc(sizeof(msOracleSpatialLayerInfo));
1963
  dthand =
1964
      (msOracleSpatialDataHandler *)malloc(sizeof(msOracleSpatialDataHandler));
1965
  sthand = (msOracleSpatialStatement *)malloc(sizeof(msOracleSpatialStatement));
1966
  sthand2 =
1967
      (msOracleSpatialStatement *)malloc(sizeof(msOracleSpatialStatement));
1968
1969
  if ((dthand == NULL) || (layerinfo == NULL)) {
1970
    msSetError(MS_MEMERR, NULL, "msOracleSpatialLayerOpen()");
1971
    return MS_FAILURE;
1972
  }
1973
1974
  memset(dthand, 0, sizeof(msOracleSpatialDataHandler));
1975
  memset(sthand, 0, sizeof(msOracleSpatialStatement));
1976
  memset(sthand2, 0, sizeof(msOracleSpatialStatement));
1977
  memset(layerinfo, 0, sizeof(msOracleSpatialLayerInfo));
1978
  layerinfo->paging = MS_TRUE;
1979
1980
  msSplitLogin(layer->connection, layer->map, &username, &password, &dblink);
1981
1982
  hand = (msOracleSpatialHandler *)msConnPoolRequest(layer);
1983
1984
  if (hand == NULL) {
1985
1986
    hand = msOCISetHandlers(username, password, dblink);
1987
1988
    if (hand == NULL) {
1989
      msOCICloseDataHandlers(dthand);
1990
      msOCIFinishStatement(sthand);
1991
      msOCIFinishStatement(sthand2);
1992
      msOCIClearLayerInfo(layerinfo);
1993
1994
      if (username)
1995
        free(username);
1996
      if (password)
1997
        free(password);
1998
      if (dblink)
1999
        free(dblink);
2000
2001
      return MS_FAILURE;
2002
    }
2003
2004
    if (layer->debug >= 2)
2005
      msDebug("msOracleSpatialLayerOpen. Shared connection not available. "
2006
              "Creating one.\n");
2007
2008
    msConnPoolRegister(layer, hand, msOCICloseConnection);
2009
  } else {
2010
    hand->ref_count++;
2011
    hand->last_oci_status = MS_SUCCESS;
2012
    hand->last_oci_error[0] = (text)'\0';
2013
  }
2014
2015
  if (!(msOCISetDataHandlers(hand, dthand) & msOCIOpenStatement(hand, sthand) &
2016
        msOCIOpenStatement(hand, sthand2))) {
2017
    msSetError(MS_ORACLESPATIALERR,
2018
               "Cannot create OCI LayerInfo. "
2019
               "Connection failure.",
2020
               "msOracleSpatialLayerOpen()");
2021
2022
    if (layer->debug >= 2)
2023
      msDebug("msOracleSpatialLayerOpen. Cannot create OCI LayerInfo. "
2024
              "Connection failure.\n");
2025
2026
    msOCICloseDataHandlers(dthand);
2027
    msOCICloseHandlers(hand);
2028
    msOCIClearLayerInfo(layerinfo);
2029
  }
2030
  layerinfo->orahandlers = hand;
2031
  layerinfo->oradatahandlers = dthand;
2032
  layerinfo->orastmt = sthand;
2033
  layerinfo->orastmt2 = sthand2;
2034
  layer->layerinfo = layerinfo;
2035
2036
  if (username)
2037
    free(username);
2038
  if (password)
2039
    free(password);
2040
  if (dblink)
2041
    free(dblink);
2042
2043
  return layer->layerinfo != NULL ? MS_SUCCESS : MS_FAILURE;
2044
}
2045
2046
/* return MS_TRUE if layer is open, MS_FALSE otherwise.*/
2047
int msOracleSpatialLayerIsOpen(layerObj *layer) {
2048
  if (layer->layerinfo != NULL)
2049
    return MS_TRUE;
2050
2051
  return MS_FALSE;
2052
}
2053
2054
/* closes the layer, disconnecting from db if connected. layer->layerinfo is
2055
 * freed */
2056
int msOracleSpatialLayerClose(layerObj *layer) {
2057
  msOracleSpatialLayerInfo *layerinfo =
2058
      (msOracleSpatialLayerInfo *)layer->layerinfo;
2059
  /*int lIntSuccessFree = 0;*/
2060
2061
  if (layer->debug >= 2)
2062
    msDebug("msOracleSpatialLayerClose was called. Layer: %p, Layer name: %s\n",
2063
            layer, layer->name);
2064
2065
  if (layerinfo != NULL) {
2066
2067
    /*
2068
     * Some errors with the OCIObjectFree with query function
2069
     * If uncomment draw mode will work but no query modes
2070
     * Need to investigate the error cause
2071
     */
2072
    /*lIntSuccessFree = TRY (layerinfo->orahandlers,
2073
     *OCIObjectFree(layerinfo->orahandlers->envhp,
2074
     *layerinfo->orahandlers->errhp, (dvoid *)layerinfo->obj,
2075
     *(ub2)OCI_OBJECTFREE_FORCE)); if (!lIntSuccessFree) msDebug("Error: %s\n",
2076
     *layerinfo->orahandlers->last_oci_error);
2077
     */
2078
    /* Release Statement Handles */
2079
    if (layerinfo->orastmt != NULL) {
2080
      msOCIFinishStatement(layerinfo->orastmt);
2081
      layerinfo->orastmt = NULL;
2082
    }
2083
    if (layerinfo->orastmt2 != NULL) {
2084
      msOCIFinishStatement(layerinfo->orastmt2);
2085
      layerinfo->orastmt2 = NULL;
2086
    }
2087
2088
    /* Release Datahandlers */
2089
    if (layer->debug >= 4)
2090
      msDebug("msOracleSpatialLayerClose. Cleaning layerinfo handlers.\n");
2091
    msOCICloseDataHandlers(layerinfo->oradatahandlers);
2092
    layerinfo->oradatahandlers = NULL;
2093
2094
    /* Free the OCI cache only if there is no more layer that could use it */
2095
    layerinfo->orahandlers->ref_count--;
2096
    if (layerinfo->orahandlers->ref_count == 0)
2097
      OCICacheFree(layerinfo->orahandlers->envhp, layerinfo->orahandlers->errhp,
2098
                   layerinfo->orahandlers->svchp);
2099
2100
    /* Release Mapserver Pool */
2101
    if (layer->debug >= 4)
2102
      msDebug("msOracleSpatialLayerClose. Release the Oracle Pool.\n");
2103
    msConnPoolRelease(layer, layerinfo->orahandlers);
2104
2105
    /* Release Layerinfo */
2106
    layerinfo->orahandlers = NULL;
2107
2108
    msOCIClearLayerInfo(layerinfo);
2109
    layer->layerinfo = NULL;
2110
  }
2111
2112
  return MS_SUCCESS;
2113
}
2114
2115
/* create SQL statement for retrieving shapes */
2116
/* Sets up cursor for use in *NextShape and *GetShape */
2117
int msOracleSpatialLayerWhichShapes(layerObj *layer, rectObj rect,
2118
                                    int isQuery) {
2119
  int success, i;
2120
  int function = 0;
2121
  int version = 0;
2122
  char *query_str = NULL;
2123
  char query_str2[256];
2124
  char *tmp_str = NULL, *tmp1_str = NULL;
2125
  char *table_name;
2126
  char *geom_column_name = NULL, *unique = NULL, *srid = NULL,
2127
       *indexfield = NULL;
2128
  OCIDefine *adtp = NULL;
2129
  OCIDefine **items = NULL;
2130
  OCINumber oci_number;
2131
  OCIBind *bnd1p = NULL, *bnd2p = NULL;
2132
2133
  int existunique = MS_FALSE;
2134
  int rownumisuniquekey = MS_FALSE;
2135
  int numitemsinselect = 0;
2136
2137
  /* get layerinfo */
2138
  msOracleSpatialLayerInfo *layerinfo =
2139
      (msOracleSpatialLayerInfo *)layer->layerinfo;
2140
  msOracleSpatialDataHandler *dthand = NULL;
2141
  msOracleSpatialHandler *hand = NULL;
2142
  msOracleSpatialStatement *sthand = NULL;
2143
2144
  if (layer->debug >= 3)
2145
    msDebug("msOracleSpatialLayerWhichShapes was called.\n");
2146
2147
  if (layerinfo == NULL) {
2148
    msSetError(MS_ORACLESPATIALERR,
2149
               "msOracleSpatialLayerWhichShapes called on unopened layer",
2150
               "msOracleSpatialLayerWhichShapes()");
2151
2152
    return MS_FAILURE;
2153
  } else {
2154
    dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers;
2155
    hand = (msOracleSpatialHandler *)layerinfo->orahandlers;
2156
    sthand = (msOracleSpatialStatement *)layerinfo->orastmt2;
2157
  }
2158
2159
  /*init uniqueindex field*/
2160
  sthand->uniqueidindex = 0;
2161
2162
  table_name = (char *)malloc(sizeof(char) * TABLE_NAME_SIZE);
2163
  /* parse geom_column_name and table_name */
2164
  if (!msSplitData(layer->data, &geom_column_name, &table_name, &unique, &srid,
2165
                   &indexfield, &function, &version)) {
2166
    msDebug("Error parsing OracleSpatial DATA variable. Must be:"
2167
            "'geometry_column FROM table_name [USING UNIQUE <column> SRID "
2168
            "srid# FUNCTION]' or "
2169
            "'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> SRID "
2170
            "srid# FUNCTION]'."
2171
            "If want to set the FUNCTION statement you can use: FILTER, "
2172
            "RELATE, GEOMRELATE or NONE."
2173
            "Your data statement: (%s)"
2174
            "in msOracleSpatialLayerWhichShapes()\n",
2175
            layer->data);
2176
    msSetError(
2177
        MS_ORACLESPATIALERR,
2178
        "Error parsing OracleSpatial DATA variable. More info in server logs",
2179
        "msOracleSpatialLayerWhichShapes()");
2180
2181
    if (geom_column_name)
2182
      free(geom_column_name);
2183
    if (srid)
2184
      free(srid);
2185
    if (unique)
2186
      free(unique);
2187
    if (indexfield)
2188
      free(indexfield);
2189
    free(table_name);
2190
    return MS_FAILURE;
2191
  }
2192
2193
  /*rownum will be the first in the select if no UNIQUE key is defined or
2194
    will be added at the end of the select*/
2195
  rownumisuniquekey = MS_TRUE;
2196
  /*Define the unique*/
2197
  if (unique[0] == '\0')
2198
    strcpy(unique, "rownum");
2199
  else
2200
    rownumisuniquekey = MS_FALSE;
2201
2202
  /* Check if the unique field is already in the items list */
2203
  existunique = MS_FALSE;
2204
  if (unique) {
2205
    for (i = 0; i < layer->numitems; ++i) {
2206
      if (strcasecmp(unique, layer->items[i]) == 0) {
2207
        sthand->uniqueidindex = i;
2208
        existunique = MS_TRUE;
2209
        break;
2210
      }
2211
    }
2212
  }
2213
2214
  /* If no SRID is provided, set it to -1 (NULL) for binding */
2215
  if (strcmp(srid, "NULL") == 0)
2216
    strcpy(srid, "-1");
2217
2218
  query_str = msStringConcatenate(query_str, "SELECT ");
2219
  numitemsinselect = layer->numitems;
2220
  /* allocate enough space for items */
2221
  if (layer->numitems >= 0) {
2222
    /*we will always add a rownumber in the selection*/
2223
    numitemsinselect++;
2224
2225
    /*if unique key in the data is specified and is not part of the current item
2226
      lists, we should add it to the select*/
2227
    if (existunique == MS_FALSE && rownumisuniquekey == MS_FALSE)
2228
      numitemsinselect++;
2229
2230
    /*the usinque index is there was no uniqueid given or the uniqueid given was
2231
     * not part of the items lists*/
2232
    if (existunique == MS_FALSE)
2233
      sthand->uniqueidindex = layer->numitems;
2234
2235
    sthand->items =
2236
        (item_text_array *)malloc(sizeof(item_text_array) * (numitemsinselect));
2237
    if (sthand->items == NULL) {
2238
      msSetError(MS_ORACLESPATIALERR, "Cannot allocate layerinfo->items buffer",
2239
                 "msOracleSpatialLayerWhichShapes()");
2240
      if (geom_column_name)
2241
        free(geom_column_name);
2242
      if (srid)
2243
        free(srid);
2244
      if (unique)
2245
        free(unique);
2246
      if (indexfield)
2247
        free(indexfield);
2248
      if (query_str)
2249
        free(query_str);
2250
      free(table_name);
2251
      return MS_FAILURE;
2252
    }
2253
2254
    items = (OCIDefine **)malloc(sizeof(OCIDefine *) * (numitemsinselect));
2255
    if (items == NULL) {
2256
      msSetError(MS_ORACLESPATIALERR, "Cannot allocate items buffer",
2257
                 "msOracleSpatialLayerWhichShapes()");
2258
      if (geom_column_name)
2259
        free(geom_column_name);
2260
      if (srid)
2261
        free(srid);
2262
      if (unique)
2263
        free(unique);
2264
      if (indexfield)
2265
        free(indexfield);
2266
      free(table_name);
2267
      if (query_str)
2268
        free(query_str);
2269
      return MS_FAILURE;
2270
    }
2271
    memset(items, 0, sizeof(OCIDefine *) * (numitemsinselect));
2272
  }
2273
2274
  /* define SQL query */
2275
  for (i = 0; i < layer->numitems; ++i) {
2276
    query_str = msStringConcatenate(query_str, "\"");
2277
    query_str = msStringConcatenate(query_str, layer->items[i]);
2278
    query_str = msStringConcatenate(query_str, "\", ");
2279
  }
2280
2281
  /*we add the uniqueid if it was not part of the current item list*/
2282
  if (existunique == MS_FALSE && rownumisuniquekey == MS_FALSE) {
2283
    query_str = msStringConcatenate(query_str, unique);
2284
    query_str = msStringConcatenate(query_str, ",");
2285
  }
2286
2287
  /*we always want to add rownum in the selection to allow paging to work*/
2288
  query_str = msStringConcatenate(query_str, "rownum, ");
2289
2290
  query_str = msStringConcatenate(query_str, geom_column_name);
2291
  query_str = msStringConcatenate(query_str, " FROM ");
2292
  query_str = msStringConcatenate(query_str, table_name);
2293
2294
  query_str = osFilteritem(layer, function, query_str, 1);
2295
2296
  if (layerinfo->paging && layer->maxfeatures > 0 && layer->startindex < 0) {
2297
    if (function == FUNCTION_NONE && layer->filter.native_string == NULL) {
2298
      query_str = msStringConcatenate(query_str, " WHERE ");
2299
    } else if (function == FUNCTION_NONE &&
2300
               layer->filter.native_string != NULL) {
2301
      query_str = msStringConcatenate(query_str, " AND ");
2302
    }
2303
    // avoiding an allocation on the heap here sounds acceptable
2304
    char tmpBuf[256];
2305
    snprintf(tmpBuf, sizeof(tmpBuf), " ROWNUM<=%d ", layer->maxfeatures);
2306
    query_str = msStringConcatenate(query_str, tmpBuf);
2307
2308
    if (function != FUNCTION_NONE) {
2309
      query_str = msStringConcatenate(query_str, " AND ");
2310
    }
2311
  }
2312
2313
  if ((((atol(srid) >= 8192) && (atol(srid) <= 8330)) || (atol(srid) == 2) ||
2314
       (atol(srid) == 5242888) || (atol(srid) == 2000001)) &&
2315
      (version == VERSION_9i)) {
2316
    query_str =
2317
        osGeodeticData(function, query_str, geom_column_name, indexfield);
2318
  } else {
2319
    query_str = osNoGeodeticData(function, version, query_str, geom_column_name,
2320
                                 indexfield);
2321
  }
2322
2323
  if (layer->sortBy.nProperties > 0) {
2324
    msDebug("Layer sorting is requested\n");
2325
    tmp1_str = msLayerBuildSQLOrderBy(layer);
2326
    query_str = msStringConcatenate(query_str, " ORDER BY ");
2327
    query_str = msStringConcatenate(query_str, tmp1_str);
2328
    query_str = msStringConcatenate(query_str, "  ");
2329
    msFree(tmp1_str);
2330
  }
2331
2332
  /*assuming startindex starts at 1*/
2333
  if (layerinfo->paging && layer->startindex > 0) {
2334
    tmp1_str = msStrdup("SELECT * from (SELECT atmp.*, ROWNUM rnum from (");
2335
    tmp_str = msStringConcatenate(tmp_str, tmp1_str);
2336
    msFree(tmp1_str);
2337
    tmp_str = msStringConcatenate(tmp_str, query_str);
2338
    /*order by rowid does not seem to work with function using the spatial
2339
      filter, at least on layers loaded using ogr in a 11g database*/
2340
    if (function == FUNCTION_NONE || function == FUNCTION_RELATE ||
2341
        function == FUNCTION_GEOMRELATE)
2342
      tmp1_str = msStrdup("order by rowid");
2343
    /* Populate strOrderBy, if necessary */
2344
    else
2345
      tmp1_str = msStrdup("");
2346
2347
    if (layer->maxfeatures > 0) {
2348
      snprintf(query_str2, sizeof(query_str2),
2349
               " %s) atmp where ROWNUM<=%d) where rnum >=%d", tmp1_str,
2350
               layer->maxfeatures + layer->startindex - 1, layer->startindex);
2351
    } else {
2352
      snprintf(query_str2, sizeof(query_str2), " %s) atmp) where rnum >=%d",
2353
               tmp1_str, layer->startindex);
2354
    }
2355
    msFree(tmp1_str);
2356
2357
    tmp_str = msStringConcatenate(tmp_str, query_str2);
2358
    memset(query_str, 0, strlen(query_str));
2359
    query_str = msStringConcatenate(query_str, tmp_str);
2360
    msFree(tmp_str);
2361
  }
2362
2363
  if (layer->debug)
2364
    msDebug("msOracleSpatialLayerWhichShapes. Using this Sql to retrieve the "
2365
            "data: %s\n",
2366
            query_str);
2367
2368
  if (layer->debug)
2369
    msDebug("msOracleSpatialLayerWhichShapes. Bind values: srid:%s   minx:%f   "
2370
            "miny:%f  maxx:%f   maxy:%f \n",
2371
            srid, rect.minx, rect.miny, rect.maxx, rect.maxy);
2372
2373
  /* prepare */
2374
  success = TRY(hand, OCIStmtPrepare(sthand->stmthp, hand->errhp,
2375
                                     (text *)query_str, (ub4)strlen(query_str),
2376
                                     (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT));
2377
2378
  if (layer->debug >= 4)
2379
    msDebug("msOracleSpatialLayerWhichShapes getting ordinate definition.\n");
2380
2381
  /* get the object definition of the ordinate array */
2382
  ordinates_tdo = get_tdo(SDO_ORDINATE_ARRAY, hand, dthand);
2383
2384
  if (layer->debug >= 4)
2385
    msDebug("msOracleSpatialLayerWhichShapes converting to OCIColl.\n");
2386
2387
  /* initialized the collection array */
2388
  success = TRY(hand, OCIObjectNew(hand->envhp, hand->errhp, hand->svchp,
2389
                                   OCI_TYPECODE_VARRAY, ordinates_tdo,
2390
                                   (dvoid *)NULL, OCI_DURATION_SESSION, FALSE,
2391
                                   (dvoid **)&ordinates));
2392
2393
  /* convert it to a OCI number and then append minx...maxy to the collection */
2394
  success =
2395
      TRY(hand,
2396
          OCINumberFromReal(hand->errhp, (dvoid *)&(rect.minx),
2397
                            (uword)sizeof(double), (dvoid *)&oci_number)) &&
2398
      TRY(hand, OCICollAppend(hand->envhp, hand->errhp, (dvoid *)&oci_number,
2399
                              (dvoid *)0, (OCIColl *)ordinates)) &&
2400
      TRY(hand,
2401
          OCINumberFromReal(hand->errhp, (dvoid *)&(rect.miny),
2402
                            (uword)sizeof(double), (dvoid *)&oci_number)) &&
2403
      TRY(hand, OCICollAppend(hand->envhp, hand->errhp, (dvoid *)&oci_number,
2404
                              (dvoid *)0, (OCIColl *)ordinates)) &&
2405
      TRY(hand,
2406
          OCINumberFromReal(hand->errhp, (dvoid *)&(rect.maxx),
2407
                            (uword)sizeof(double), (dvoid *)&oci_number)) &&
2408
      TRY(hand, OCICollAppend(hand->envhp, hand->errhp, (dvoid *)&oci_number,
2409
                              (dvoid *)0, (OCIColl *)ordinates)) &&
2410
      TRY(hand,
2411
          OCINumberFromReal(hand->errhp, (dvoid *)&(rect.maxy),
2412
                            (uword)sizeof(double), (dvoid *)&oci_number)) &&
2413
      TRY(hand, OCICollAppend(hand->envhp, hand->errhp, (dvoid *)&oci_number,
2414
                              (dvoid *)0, (OCIColl *)ordinates));
2415
2416
  if (layer->debug >= 3)
2417
    msDebug("msOracleSpatialLayerWhichShapes bind by name and object.\n");
2418
2419
  /* do the actual binding */
2420
2421
  if (success && function != FUNCTION_NONE) {
2422
    success =
2423
        TRY(hand,
2424
            /* bind in srid */
2425
            OCIBindByName(sthand->stmthp, &bnd2p, hand->errhp, (text *)":srid",
2426
                          strlen(":srid"), (ub1 *)srid, strlen(srid) + 1,
2427
                          SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2)0, (ub4)0,
2428
                          (ub4 *)0, OCI_DEFAULT)) &&
2429
        TRY(hand,
2430
            /* bind in rect by name */
2431
            OCIBindByName(sthand->stmthp, &bnd1p, hand->errhp,
2432
                          (text *)":ordinates", -1, (dvoid *)0, (sb4)0,
2433
                          SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)0,
2434
                          (ub4 *)0, (ub4)OCI_DEFAULT)) &&
2435
        TRY(hand,
2436
            /* bind in rect object */
2437
            OCIBindObject(bnd1p, hand->errhp, ordinates_tdo,
2438
                          (dvoid **)&ordinates, (ub4 *)0, (dvoid **)0,
2439
                          (ub4 *)0));
2440
2441
    /* bind the variables from the bindvals hash */
2442
    const char *bind_key = msFirstKeyFromHashTable(&layer->bindvals);
2443
    while (bind_key != NULL) {
2444
      const char *bind_value = msLookupHashTable(&layer->bindvals, bind_key);
2445
      char *bind_tag = (char *)malloc(sizeof(char) * strlen(bind_key) + 2);
2446
      sprintf(bind_tag, ":%s", bind_key);
2447
2448
      success =
2449
          success &&
2450
          TRY(hand, OCIBindByName(sthand->stmthp, &bnd2p, hand->errhp,
2451
                                  (text *)bind_tag, strlen(bind_tag),
2452
                                  (ub1 *)bind_value, strlen(bind_value) + 1,
2453
                                  SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2)0,
2454
                                  (ub4)0, (ub4 *)0, OCI_DEFAULT));
2455
      bind_key = msNextKeyFromHashTable(&layer->bindvals, bind_key);
2456
    }
2457
  }
2458
2459
  if (layer->debug >= 3)
2460
    msDebug("msOracleSpatialLayerWhichShapes name and object now bound.\n");
2461
2462
  if (success && layer->numitems >= 0) {
2463
    for (i = 0; i < numitemsinselect && success; ++i) {
2464
      if (i < numitemsinselect - 1) {
2465
        // msDebug("Defining by POS, for %s\n", layer->items[i]);
2466
        // msDebug("datatype retrieved is %i\n", layer->iteminfo);
2467
      }
2468
      success = TRY(hand, OCIDefineByPos(sthand->stmthp, &items[i], hand->errhp,
2469
                                         (ub4)i + 1, (dvoid *)sthand->items[i],
2470
                                         (sb4)TEXT_SIZE, SQLT_STR, (dvoid *)0,
2471
                                         (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT));
2472
    }
2473
  }
2474
2475
  if (success) {
2476
    int cursor_type = OCI_DEFAULT;
2477
    if (isQuery)
2478
      cursor_type = OCI_STMT_SCROLLABLE_READONLY;
2479
2480
    success = TRY(hand,
2481
                  /* define spatial position adtp ADT object */
2482
                  OCIDefineByPos(sthand->stmthp, &adtp, hand->errhp,
2483
                                 (ub4)numitemsinselect + 1, (dvoid *)0, (sb4)0,
2484
                                 SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0,
2485
                                 (ub4)OCI_DEFAULT)) &&
2486
              TRY(hand,
2487
                  /* define object tdo from adtp */
2488
                  OCIDefineObject(adtp, hand->errhp, dthand->tdo,
2489
                                  (dvoid **)sthand->obj, (ub4 *)0,
2490
                                  (dvoid **)sthand->ind, (ub4 *)0)) &&
2491
              TRY(hand,
2492
                  /* execute */
2493
                  OCIStmtExecute(hand->svchp, sthand->stmthp, hand->errhp,
2494
                                 (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL,
2495
                                 (OCISnapshot *)NULL, (ub4)cursor_type)) &&
2496
              TRY(hand,
2497
                  /* get rows fetched */
2498
                  OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
2499
                             (dvoid *)&sthand->rows_fetched, (ub4 *)0,
2500
                             (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp)) &&
2501
              TRY(hand,
2502
                  /* get rows count */
2503
                  OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
2504
                             (dvoid *)&sthand->rows_count, (ub4 *)0,
2505
                             (ub4)OCI_ATTR_ROW_COUNT, hand->errhp));
2506
  }
2507
2508
  if (!success) {
2509
    msDebug("Error: %s . "
2510
            "Query statement: %s . "
2511
            "Check your data statement."
2512
            "msOracleSpatialLayerWhichShapes()\n",
2513
            hand->last_oci_error, query_str);
2514
    msSetError(MS_ORACLESPATIALERR, "Check your data statement and server logs",
2515
               "msOracleSpatialLayerWhichShapes()");
2516
2517
    /* clean items */
2518
    free(items);
2519
    if (geom_column_name)
2520
      free(geom_column_name);
2521
    if (srid)
2522
      free(srid);
2523
    if (unique)
2524
      free(unique);
2525
    if (indexfield)
2526
      free(indexfield);
2527
    if (query_str)
2528
      free(query_str);
2529
    free(table_name);
2530
2531
    return MS_FAILURE;
2532
  }
2533
2534
  /* should begin processing first row */
2535
  sthand->row_num = sthand->row = 0;
2536
2537
  /* clean items */
2538
  free(items);
2539
  // TODO why not msFree() instead to avoid if statements ?
2540
  if (geom_column_name)
2541
    free(geom_column_name);
2542
  if (srid)
2543
    free(srid);
2544
  if (unique)
2545
    free(unique);
2546
  if (indexfield)
2547
    free(indexfield);
2548
  if (query_str)
2549
    free(query_str);
2550
  free(table_name);
2551
2552
  return MS_SUCCESS;
2553
}
2554
2555
/* fetch next shape from previous SELECT stmt (see *WhichShape()) */
2556
int msOracleSpatialLayerNextShape(layerObj *layer, shapeObj *shape) {
2557
  SDOGeometryObj *obj;
2558
  SDOGeometryInd *ind;
2559
  int success, /*lIntSuccessFree,*/ i;
2560
2561
  /* get layerinfo */
2562
  msOracleSpatialLayerInfo *layerinfo =
2563
      (msOracleSpatialLayerInfo *)layer->layerinfo;
2564
  msOracleSpatialDataHandler *dthand = NULL;
2565
  msOracleSpatialHandler *hand = NULL;
2566
  msOracleSpatialStatement *sthand = NULL;
2567
2568
  if (layerinfo == NULL) {
2569
    msSetError(MS_ORACLESPATIALERR,
2570
               "msOracleSpatialLayerWhichShapes called on unopened layer",
2571
               "msOracleSpatialLayerNextShape()");
2572
    return MS_FAILURE;
2573
  } else {
2574
    dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers;
2575
    hand = (msOracleSpatialHandler *)layerinfo->orahandlers;
2576
    sthand = (msOracleSpatialStatement *)layerinfo->orastmt2;
2577
  }
2578
2579
  /* no rows fetched */
2580
  if (sthand->rows_fetched == 0)
2581
    return MS_DONE;
2582
2583
  if (layer->debug >= 5)
2584
    msDebug("msOracleSpatialLayerNextShape on layer %p, row_num: %d\n", layer,
2585
            sthand->row_num);
2586
2587
  do {
2588
    /* is buffer empty? */
2589
    if (sthand->row >= sthand->rows_fetched) {
2590
      /* fetch more */
2591
      success =
2592
          TRY(hand,
2593
              OCIStmtFetch2(sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE,
2594
                            (ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT)) &&
2595
          TRY(hand, OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
2596
                               (dvoid *)&sthand->rows_fetched, (ub4 *)0,
2597
                               (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp)) &&
2598
          TRY(hand, OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
2599
                               (dvoid *)&sthand->rows_count, (ub4 *)0,
2600
                               (ub4)OCI_ATTR_ROW_COUNT, hand->errhp));
2601
2602
      if (!success || sthand->rows_fetched == 0 ||
2603
          sthand->row_num >= sthand->rows_count) {
2604
        hand->last_oci_status = MS_SUCCESS;
2605
        return MS_DONE;
2606
      }
2607
      if (layer->debug >= 4)
2608
        msDebug("msOracleSpatialLayerNextShape on layer %p, Fetched %d more "
2609
                "rows (%d total)\n",
2610
                layer, sthand->rows_fetched, sthand->rows_count);
2611
2612
      sthand->row = 0; /* reset buffer row index */
2613
    }
2614
2615
    /* set obj & ind for current row */
2616
    obj = sthand->obj[sthand->row];
2617
    ind = sthand->ind[sthand->row];
2618
2619
    /* get the items for the shape */
2620
    shape->index = atol((char *)(sthand->items[sthand->uniqueidindex]
2621
                                              [sthand->row])); /* Primary Key */
2622
    shape->resultindex = sthand->row_num;
2623
    shape->numvalues = layer->numitems;
2624
2625
    shape->values = (char **)malloc(sizeof(char *) * shape->numvalues);
2626
    if (shape->values == NULL) {
2627
      msSetError(MS_ORACLESPATIALERR,
2628
                 "No memory available to allocate the values",
2629
                 "msOracleSpatialLayerNextShape()");
2630
      return MS_FAILURE;
2631
    }
2632
2633
    for (i = 0; i < shape->numvalues; ++i) {
2634
      shape->values[i] =
2635
          (char *)malloc(strlen((char *)sthand->items[i][sthand->row]) + 1);
2636
      if (shape->values[i] == NULL) {
2637
        msSetError(MS_ORACLESPATIALERR,
2638
                   "No memory available to allocate the items",
2639
                   "msOracleSpatialLayerNextShape()");
2640
        return MS_FAILURE;
2641
      } else {
2642
        strcpy(shape->values[i], (char *)sthand->items[i][sthand->row]);
2643
        shape->values[i][strlen((char *)sthand->items[i][sthand->row])] = '\0';
2644
      }
2645
    }
2646
2647
    /* fetch a layer->type object */
2648
    success = osGetOrdinates(dthand, hand, shape, obj, ind);
2649
2650
    /* increment for next row */
2651
    sthand->row_num++;
2652
    sthand->row++;
2653
2654
    if (success != MS_SUCCESS) {
2655
      return MS_FAILURE;
2656
    }
2657
2658
    osShapeBounds(shape);
2659
  } while (shape->type == MS_SHAPE_NULL);
2660
2661
  return MS_SUCCESS;
2662
}
2663
2664
int msOracleSpatialLayerGetShape(layerObj *layer, shapeObj *shape,
2665
                                 resultObj *record) {
2666
  int success, i;
2667
  SDOGeometryObj *obj;
2668
  SDOGeometryInd *ind;
2669
  msOracleSpatialDataHandler *dthand = NULL;
2670
  msOracleSpatialHandler *hand = NULL;
2671
  msOracleSpatialLayerInfo *layerinfo;
2672
  msOracleSpatialStatement *sthand = NULL;
2673
2674
  long shapeindex = record->shapeindex;
2675
  int resultindex = record->resultindex;
2676
2677
  if (layer == NULL) {
2678
    msSetError(MS_ORACLESPATIALERR,
2679
               "msOracleSpatialLayerGetShape called on unopened layer",
2680
               "msOracleSpatialLayerGetShape()");
2681
    return MS_FAILURE;
2682
  }
2683
2684
  layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo;
2685
2686
  if (layerinfo == NULL) {
2687
    msSetError(
2688
        MS_ORACLESPATIALERR,
2689
        "msOracleSpatialLayerGetShape called on unopened layer (layerinfo)",
2690
        "msOracleSpatialLayerGetShape()");
2691
    return MS_FAILURE;
2692
  }
2693
2694
  /* If resultindex is set, fetch the shape from the resultcache, otherwise
2695
   * fetch it from the DB  */
2696
  if (resultindex >= 0) {
2697
    long buffer_first_row_num, buffer_last_row_num;
2698
2699
    /* get layerinfo */
2700
    dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers;
2701
    hand = (msOracleSpatialHandler *)layerinfo->orahandlers;
2702
    sthand = (msOracleSpatialStatement *)layerinfo->orastmt2;
2703
2704
    if (layer->resultcache == NULL) {
2705
      msSetError(MS_ORACLESPATIALERR,
2706
                 "msOracleSpatialLayerGetShape called before "
2707
                 "msOracleSpatialLayerWhichShapes()",
2708
                 "msOracleSpatialLayerGetShape()");
2709
      return MS_FAILURE;
2710
    }
2711
2712
    if ((unsigned)resultindex >= sthand->rows_count) {
2713
      if (layer->debug >= 5)
2714
        msDebug("msOracleSpatialLayerGetShape problem with cursor. Trying to "
2715
                "fetch record = %d of %d, falling back to GetShape\n",
2716
                resultindex, sthand->rows_count);
2717
2718
      msSetError(MS_ORACLESPATIALERR,
2719
                 "msOracleSpatialLayerGetShape record out of range",
2720
                 "msOracleSpatialLayerGetShape()");
2721
      return MS_FAILURE;
2722
    }
2723
2724
    if (layer->debug >= 5)
2725
      msDebug("msOracleSpatialLayerGetShape was called. Using the record = %d "
2726
              "of %d. (shape: %ld should equal pkey: %ld)\n",
2727
              resultindex, layer->resultcache->numresults,
2728
              layer->resultcache->results[resultindex].shapeindex, shapeindex);
2729
2730
    /* NOTE: with the way the resultcache works, we should see items in
2731
     * increasing order, but some may have been filtered out. */
2732
    /* Best case: item in buffer */
2733
    /* Next best case: item is in next fetch block */
2734
    /* Worst case: item is random access */
2735
    buffer_first_row_num =
2736
        sthand->row_num - sthand->row; /* cursor id of first item in buffer */
2737
    buffer_last_row_num = buffer_first_row_num + sthand->rows_fetched -
2738
                          1; /* cursor id of last item in buffer */
2739
    if (resultindex >= buffer_first_row_num &&
2740
        resultindex <= buffer_last_row_num) { /* Item is in buffer. Calculate
2741
                                                 position in buffer */
2742
      sthand->row +=
2743
          resultindex - sthand->row_num; /* move sthand row an row_num by offset
2744
                                            from last call */
2745
      sthand->row_num += resultindex - sthand->row_num;
2746
    } else { /* Item is not in buffer. Fetch item from Oracle */
2747
      if (layer->debug >= 4)
2748
        msDebug("msOracleSpatialLayerGetShape: Fetching result from DB start: "
2749
                "%ld end:%ld record: %d\n",
2750
                buffer_first_row_num, buffer_last_row_num, resultindex);
2751
2752
      success =
2753
          TRY(hand, OCIStmtFetch2(sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE,
2754
                                  (ub2)OCI_FETCH_ABSOLUTE, (sb4)resultindex + 1,
2755
                                  (ub4)OCI_DEFAULT)) &&
2756
          TRY(hand, OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
2757
                               (dvoid *)&sthand->rows_fetched, (ub4 *)0,
2758
                               (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp));
2759
2760
      sthand->row_num = resultindex;
2761
      sthand->row = 0; /* reset row index */
2762
2763
      if (ERROR("msOracleSpatialLayerGetShape", hand, dthand))
2764
        return MS_FAILURE;
2765
2766
      if (!success || sthand->rows_fetched == 0) {
2767
        msSetError(
2768
            MS_ORACLESPATIALERR,
2769
            "msOracleSpatialLayerGetShape could not fetch specified record.",
2770
            "msOracleSpatialLayerGetShape()");
2771
        return MS_FAILURE;
2772
      }
2773
    }
2774
2775
    /* set obj & ind for current row */
2776
    obj = sthand->obj[sthand->row];
2777
    ind = sthand->ind[sthand->row];
2778
2779
    /* get the items for the shape */
2780
    shape->index = shapeindex; /* By definition this is what we asked for */
2781
    shape->numvalues = layer->numitems;
2782
2783
    shape->values = (char **)malloc(sizeof(char *) * shape->numvalues);
2784
    if (shape->values == NULL) {
2785
      msSetError(MS_ORACLESPATIALERR,
2786
                 "No memory available to allocate the values",
2787
                 "msOracleSpatialLayerNextShape()");
2788
      return MS_FAILURE;
2789
    }
2790
2791
    for (i = 0; i < shape->numvalues; ++i) {
2792
      shape->values[i] =
2793
          (char *)malloc(strlen((char *)sthand->items[i][sthand->row]) + 1);
2794
      if (shape->values[i] == NULL) {
2795
        msSetError(MS_ORACLESPATIALERR,
2796
                   "No memory available to allocate the items",
2797
                   "msOracleSpatialLayerNextShape()");
2798
        return MS_FAILURE;
2799
      } else {
2800
        strcpy(shape->values[i], (char *)sthand->items[i][sthand->row]);
2801
        shape->values[i][strlen((char *)sthand->items[i][sthand->row])] = '\0';
2802
      }
2803
    }
2804
2805
    /* fetch a layer->type object */
2806
    success = osGetOrdinates(dthand, hand, shape, obj, ind);
2807
2808
    if (success != MS_SUCCESS) {
2809
      msSetError(MS_ORACLESPATIALERR, "Call to osGetOrdinates failed.",
2810
                 "msOracleSpatialLayerGetShape()");
2811
      return MS_FAILURE;
2812
    }
2813
2814
    osShapeBounds(shape);
2815
    if (shape->type == MS_SHAPE_NULL) {
2816
      msSetError(MS_ORACLESPATIALERR,
2817
                 "Shape type is null... this probably means a record number "
2818
                 "was requested that could not have beeen in a result set (as "
2819
                 "returned by NextShape).",
2820
                 "msOracleSpatialLayerGetShape()");
2821
      return MS_FAILURE;
2822
    }
2823
2824
    return (MS_SUCCESS);
2825
  } else { /* no resultindex, fetch the shape from the DB */
2826
    char *table_name;
2827
    char *query_str = NULL, *geom_column_name = NULL, *unique = NULL,
2828
         *srid = NULL, *indexfield = NULL;
2829
    int function = 0;
2830
    int version = 0;
2831
    sb2 *nullind = NULL;
2832
    /*OCIDefine *adtp = NULL, *items[QUERY_SIZE] = { NULL };*/
2833
    OCIDefine *adtp = NULL;
2834
    OCIDefine **items = NULL;
2835
2836
    if (layer->debug >= 4)
2837
      msDebug(
2838
          "msOracleSpatialLayerGetShape was called. Using the record = %ld.\n",
2839
          shapeindex);
2840
2841
    dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers;
2842
    hand = (msOracleSpatialHandler *)layerinfo->orahandlers;
2843
    sthand = (msOracleSpatialStatement *)layerinfo->orastmt;
2844
2845
    /* allocate enough space for items */
2846
    if (layer->numitems > 0) {
2847
      if (sthand->items_query == NULL)
2848
        sthand->items_query = (item_text_array_query *)malloc(
2849
            sizeof(item_text_array_query) * (layer->numitems));
2850
2851
      if (sthand->items_query == NULL) {
2852
        msSetError(MS_ORACLESPATIALERR,
2853
                   "Cannot allocate layerinfo->items_query buffer",
2854
                   "msOracleSpatialLayerGetShape()");
2855
        return MS_FAILURE;
2856
      }
2857
2858
      nullind = (sb2 *)malloc(sizeof(sb2) * (layer->numitems));
2859
      if (nullind == NULL) {
2860
        msSetError(MS_ORACLESPATIALERR, "Cannot allocate nullind buffer",
2861
                   "msOracleSpatialLayerGetShape()");
2862
        return MS_FAILURE;
2863
      }
2864
      memset(nullind, 0, sizeof(sb2) * (layer->numitems));
2865
2866
      items = (OCIDefine **)malloc(sizeof(OCIDefine *) * layer->numitems);
2867
      if (items == NULL) {
2868
        msSetError(MS_ORACLESPATIALERR, "Cannot allocate items buffer",
2869
                   "msOracleSpatialLayerWhichShapes()");
2870
2871
        /* clean nullind  */
2872
        free(nullind);
2873
2874
        return MS_FAILURE;
2875
      }
2876
      memset(items, 0, sizeof(OCIDefine *) * layer->numitems);
2877
    }
2878
2879
    table_name = (char *)malloc(sizeof(char) * TABLE_NAME_SIZE);
2880
    if (!msSplitData(layer->data, &geom_column_name, &table_name, &unique,
2881
                     &srid, &indexfield, &function, &version)) {
2882
      msDebug("Error parsing OracleSpatial DATA variable. Must be: "
2883
              "'geometry_column FROM table_name [USING UNIQUE <column> SRID "
2884
              "srid# FUNCTION]' or "
2885
              "'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> SRID "
2886
              "srid# FUNCTION]'. "
2887
              "If want to set the FUNCTION statement you can use: FILTER, "
2888
              "RELATE, GEOMRELATE or NONE. "
2889
              "Your data statement: (%s) msOracleSpatialLayerGetShape()\n",
2890
              layer->data);
2891
      msSetError(
2892
          MS_ORACLESPATIALERR,
2893
          "Error parsing OracleSpatial DATA variable. Check server logs. ",
2894
          "msOracleSpatialLayerGetShape()");
2895
2896
      /* clean nullind  */
2897
      free(nullind);
2898
2899
      /* clean items */
2900
      free(items);
2901
2902
      if (geom_column_name)
2903
        free(geom_column_name);
2904
      if (srid)
2905
        free(srid);
2906
      if (unique)
2907
        free(unique);
2908
      if (indexfield)
2909
        free(indexfield);
2910
      free(table_name);
2911
2912
      return MS_FAILURE;
2913
    }
2914
2915
    /*Define the first query to retrieve items*/
2916
    if (unique[0] == '\0') {
2917
      msSetError(
2918
          MS_ORACLESPATIALERR,
2919
          "Error parsing OracleSpatial DATA variable for query. To execute "
2920
          "query functions you need to define one "
2921
          "unique column [USING UNIQUE <#column>]",
2922
          "msOracleSpatialLayerGetShape()");
2923
2924
      /* clean nullind  */
2925
      free(nullind);
2926
2927
      /* clean items */
2928
      free(items);
2929
2930
      if (geom_column_name)
2931
        free(geom_column_name);
2932
      if (srid)
2933
        free(srid);
2934
      if (unique)
2935
        free(unique);
2936
      if (indexfield)
2937
        free(indexfield);
2938
      free(table_name);
2939
2940
      return MS_FAILURE;
2941
    } else {
2942
      query_str = msStringConcatenate(query_str, "SELECT");
2943
    }
2944
    /*Define the query*/
2945
    for (i = 0; i < layer->numitems; ++i) {
2946
      msStringConcatenate(query_str, " ");
2947
      msStringConcatenate(query_str, layer->items[i]);
2948
      msStringConcatenate(query_str, ",");
2949
    }
2950
    char tmpBuf[256];
2951
    snprintf(tmpBuf, sizeof(tmpBuf), "%ld", shapeindex);
2952
    query_str = msStringConcatenate(query_str, " ");
2953
    query_str = msStringConcatenate(query_str, geom_column_name);
2954
    query_str = msStringConcatenate(query_str, " FROM ");
2955
    query_str = msStringConcatenate(query_str, table_name);
2956
    query_str = msStringConcatenate(query_str, " WHERE ");
2957
    query_str = msStringConcatenate(query_str, unique);
2958
    query_str = msStringConcatenate(query_str, " = ");
2959
    query_str = msStringConcatenate(query_str, tmpBuf);
2960
2961
    /*if (layer->filter.native_string != NULL)
2962
      sprintf( query_str + strlen(query_str), " AND %s",
2963
      (layer->filter.string));*/
2964
    query_str = osFilteritem(layer, FUNCTION_NONE, query_str, 2);
2965
2966
    if (layer->debug)
2967
      msDebug("msOracleSpatialLayerGetShape. Sql: %s\n", query_str);
2968
2969
    /*Prepare the handlers to the query*/
2970
    success =
2971
        TRY(hand, OCIStmtPrepare(sthand->stmthp, hand->errhp, (text *)query_str,
2972
                                 (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX,
2973
                                 (ub4)OCI_DEFAULT));
2974
2975
    if (success && layer->numitems > 0) {
2976
      for (i = 0; i < layer->numitems && success; i++)
2977
        success = TRY(
2978
            hand, OCIDefineByPos(sthand->stmthp, &items[i], hand->errhp,
2979
                                 (ub4)i + 1, (dvoid *)sthand->items_query[i],
2980
                                 (sb4)TEXT_SIZE, SQLT_STR, (sb2 *)&nullind[i],
2981
                                 (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT));
2982
    }
2983
2984
    if (!success) {
2985
      msSetError(MS_ORACLESPATIALERR,
2986
                 "Error: %s . "
2987
                 "Query statement: %s . "
2988
                 "Check your data statement.",
2989
                 "msOracleSpatialLayerGetShape()\n", hand->last_oci_error,
2990
                 query_str);
2991
2992
      /* clean nullind  */
2993
      free(nullind);
2994
2995
      /* clean items */
2996
      free(items);
2997
2998
      if (geom_column_name)
2999
        free(geom_column_name);
3000
      if (srid)
3001
        free(srid);
3002
      if (unique)
3003
        free(unique);
3004
      if (indexfield)
3005
        free(indexfield);
3006
      if (query_str)
3007
        free(query_str);
3008
      free(table_name);
3009
3010
      return MS_FAILURE;
3011
    }
3012
3013
    if (success) {
3014
      success =
3015
          TRY(hand, OCIDefineByPos(sthand->stmthp, &adtp, hand->errhp,
3016
                                   (ub4)layer->numitems + 1, (dvoid *)0, (sb4)0,
3017
                                   SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0,
3018
                                   (ub4)OCI_DEFAULT)) &&
3019
          TRY(hand, OCIDefineObject(adtp, hand->errhp, dthand->tdo,
3020
                                    (dvoid **)sthand->obj, (ub4 *)0,
3021
                                    (dvoid **)sthand->ind, (ub4 *)0)) &&
3022
          TRY(hand, OCIStmtExecute(hand->svchp, sthand->stmthp, hand->errhp,
3023
                                   (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL,
3024
                                   (OCISnapshot *)NULL, (ub4)OCI_DEFAULT)) &&
3025
          TRY(hand, OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
3026
                               (dvoid *)&sthand->rows_fetched, (ub4 *)0,
3027
                               (ub4)OCI_ATTR_ROW_COUNT, hand->errhp));
3028
    }
3029
3030
    if (!success) {
3031
      msDebug("Error: %s . "
3032
              "Query statement: %s ."
3033
              "Check your data statement."
3034
              "in msOracleSpatialLayerGetShape()\n",
3035
              hand->last_oci_error, query_str);
3036
      msSetError(MS_ORACLESPATIALERR,
3037
                 "Error in Query statement. Check your server logs",
3038
                 "msOracleSpatialLayerGetShape()");
3039
3040
      /* clean nullind  */
3041
      free(nullind);
3042
3043
      /* clean items */
3044
      free(items);
3045
3046
      if (geom_column_name)
3047
        free(geom_column_name);
3048
      if (srid)
3049
        free(srid);
3050
      if (unique)
3051
        free(unique);
3052
      if (indexfield)
3053
        free(indexfield);
3054
      if (query_str)
3055
        free(query_str);
3056
      free(table_name);
3057
3058
      return MS_FAILURE;
3059
    }
3060
3061
    shape->type = MS_SHAPE_NULL;
3062
3063
    /* no rows fetched */
3064
    if (sthand->rows_fetched == 0) {
3065
      /* clean nullind  */
3066
      free(nullind);
3067
3068
      /* clean items */
3069
      free(items);
3070
3071
      if (geom_column_name)
3072
        free(geom_column_name);
3073
      if (srid)
3074
        free(srid);
3075
      if (unique)
3076
        free(unique);
3077
      if (indexfield)
3078
        free(indexfield);
3079
      if (query_str)
3080
        free(query_str);
3081
      free(table_name);
3082
3083
      return (MS_DONE);
3084
    }
3085
3086
    obj = sthand->obj[sthand->row];
3087
    ind = sthand->ind[sthand->row];
3088
3089
    /* get the items for the shape */
3090
    shape->numvalues = layer->numitems;
3091
    shape->values = (char **)malloc(sizeof(char *) * layer->numitems);
3092
    if (shape->values == NULL) {
3093
      msSetError(MS_ORACLESPATIALERR,
3094
                 "No memory available to allocate the values.",
3095
                 "msOracleSpatialLayerGetShape()");
3096
3097
      /* clean nullind  */
3098
      free(nullind);
3099
3100
      /* clean items */
3101
      free(items);
3102
3103
      if (geom_column_name)
3104
        free(geom_column_name);
3105
      if (srid)
3106
        free(srid);
3107
      if (unique)
3108
        free(unique);
3109
      if (indexfield)
3110
        free(indexfield);
3111
      if (query_str)
3112
        free(query_str);
3113
      free(table_name);
3114
3115
      return MS_FAILURE;
3116
    }
3117
3118
    shape->index = shapeindex;
3119
3120
    for (i = 0; i < layer->numitems; ++i) {
3121
      shape->values[i] = (char *)malloc(
3122
          strlen((char *)sthand->items_query[sthand->row][i]) + 1);
3123
3124
      if (shape->values[i] == NULL) {
3125
        msSetError(MS_ORACLESPATIALERR,
3126
                   "No memory available to allocate the items buffer.",
3127
                   "msOracleSpatialLayerGetShape()");
3128
3129
        /* clean nullind  */
3130
        free(nullind);
3131
3132
        /* clean items */
3133
        free(items);
3134
3135
        if (geom_column_name)
3136
          free(geom_column_name);
3137
        if (srid)
3138
          free(srid);
3139
        if (unique)
3140
          free(unique);
3141
        if (indexfield)
3142
          free(indexfield);
3143
        if (query_str)
3144
          free(query_str);
3145
        free(table_name);
3146
3147
        return MS_FAILURE;
3148
      } else {
3149
        if (nullind[i] != OCI_IND_NULL) {
3150
          strcpy(shape->values[i], (char *)sthand->items_query[sthand->row][i]);
3151
          shape
3152
              ->values[i][strlen((char *)sthand->items_query[sthand->row][i])] =
3153
              '\0';
3154
        } else {
3155
          shape->values[i][0] = '\0';
3156
        }
3157
      }
3158
    }
3159
3160
    /* increment for next row */
3161
    sthand->row_num++;
3162
    sthand->row++;
3163
3164
    /* fetch a layer->type object */
3165
    success = osGetOrdinates(dthand, hand, shape, obj, ind);
3166
    if (success != MS_SUCCESS) {
3167
      msSetError(MS_ORACLESPATIALERR, "Cannot execute query",
3168
                 "msOracleSpatialLayerGetShape()");
3169
3170
      /* clean nullind  */
3171
      free(nullind);
3172
3173
      /* clean items */
3174
      free(items);
3175
3176
      if (geom_column_name)
3177
        free(geom_column_name);
3178
      if (srid)
3179
        free(srid);
3180
      if (unique)
3181
        free(unique);
3182
      if (indexfield)
3183
        free(indexfield);
3184
      if (query_str)
3185
        free(query_str);
3186
      free(table_name);
3187
3188
      return MS_FAILURE;
3189
    }
3190
    osShapeBounds(shape);
3191
    sthand->row = sthand->row_num = 0;
3192
3193
    /* clean nullind  */
3194
    free(nullind);
3195
3196
    /* clean items */
3197
    free(items);
3198
3199
    if (geom_column_name)
3200
      free(geom_column_name);
3201
    if (srid)
3202
      free(srid);
3203
    if (unique)
3204
      free(unique);
3205
    if (indexfield)
3206
      free(indexfield);
3207
    if (query_str)
3208
      free(query_str);
3209
    free(table_name);
3210
3211
    return (MS_SUCCESS);
3212
  }
3213
}
3214
3215
int msOracleSpatialLayerInitItemInfo(layerObj *layer) {
3216
  int i;
3217
  int *itemindexes;
3218
3219
  if (layer->debug >= 3)
3220
    msDebug("msOracleSpatialLayerInitItemInfo was called.\n");
3221
3222
  if (layer->numitems == 0)
3223
    return MS_SUCCESS;
3224
3225
  if (layer->iteminfo)
3226
    free(layer->iteminfo);
3227
3228
  if ((layer->iteminfo = (long *)malloc(sizeof(int) * layer->numitems)) ==
3229
      NULL) {
3230
    msSetError(MS_MEMERR, NULL, "msOracleSpatialLayerInitItemInfo()");
3231
    return MS_FAILURE;
3232
  }
3233
3234
  itemindexes = (int *)layer->iteminfo;
3235
3236
  for (i = 0; i < layer->numitems; i++) {
3237
    itemindexes[i] =
3238
        i; /*last one is always the geometry one - the rest are non-geom*/
3239
  }
3240
3241
  return MS_SUCCESS;
3242
}
3243
3244
/* AutoProjection Support for RFC 37 #3333
3245
 * TODO: Needs testing
3246
 */
3247
int msOracleSpatialLayerGetAutoProjection(layerObj *layer,
3248
                                          projectionObj *projection) {
3249
  char *table_name;
3250
  char *query_str, *geom_column_name = NULL, *unique = NULL, *srid = NULL,
3251
                   *indexfield = NULL;
3252
  int success;
3253
  int function = 0;
3254
  int version = 0;
3255
  char wktext[4000];
3256
3257
  OCIDefine *def1p = NULL;
3258
  OCIBind *bnd1p = NULL, *bnd2p = NULL;
3259
3260
  msOracleSpatialLayerInfo *layerinfo =
3261
      (msOracleSpatialLayerInfo *)layer->layerinfo;
3262
  msOracleSpatialHandler *hand = NULL;
3263
  msOracleSpatialStatement *sthand = NULL;
3264
3265
  if (layer->debug >= 3)
3266
    msDebug("msOracleSpatialLayerGetAutoProjection was called.\n");
3267
3268
  if (layerinfo == NULL) {
3269
    msSetError(MS_ORACLESPATIALERR,
3270
               "msOracleSpatialLayerGetAutoProjection called on unopened layer",
3271
               "msOracleSpatialLayerGetAutoProjection()");
3272
    return MS_FAILURE;
3273
  } else {
3274
    hand = (msOracleSpatialHandler *)layerinfo->orahandlers;
3275
    sthand = (msOracleSpatialStatement *)layerinfo->orastmt;
3276
  }
3277
3278
  table_name = (char *)malloc(sizeof(char) * TABLE_NAME_SIZE);
3279
  if (!msSplitData(layer->data, &geom_column_name, &table_name, &unique, &srid,
3280
                   &indexfield, &function, &version)) {
3281
    msDebug("Error parsing OracleSpatial DATA variable. Must be: "
3282
            "'geometry_column FROM table_name [USING UNIQUE <column> SRID "
3283
            "srid# FUNCTION]' or "
3284
            "'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> SRID "
3285
            "srid# FUNCTION]'. "
3286
            "If want to set the FUNCTION statement you can use: FILTER, "
3287
            "RELATE, GEOMRELATE or NONE. "
3288
            "Your data statement: (%s) "
3289
            "in msOracleSpatialLayerGetAutoProjection()\n",
3290
            layer->data);
3291
3292
    msSetError(MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable",
3293
               "msOracleSpatialLayerGetAutoProjection()");
3294
3295
    if (geom_column_name)
3296
      free(geom_column_name);
3297
    if (srid)
3298
      free(srid);
3299
    if (unique)
3300
      free(unique);
3301
    if (indexfield)
3302
      free(indexfield);
3303
    free(table_name);
3304
3305
    return MS_FAILURE;
3306
  }
3307
3308
  query_str = "SELECT wktext FROM mdsys.all_sdo_geom_metadata m, mdsys.cs_srs "
3309
              "c WHERE c.srid = m.srid and m.owner||'.'||m.table_name = "
3310
              ":table_name and m.column_name = :geo_col_name "
3311
              "UNION SELECT wktext from mdsys.user_sdo_geom_metadata m, "
3312
              "mdsys.cs_srs c WHERE c.srid = m.srid and m.table_name = "
3313
              ":table_name and m.column_name = :geo_col_name";
3314
3315
  if (layer->debug >= 2)
3316
    msDebug("msOracleSpatialLayerGetAutoProjection. Using this Sql to retrieve "
3317
            "the projection: %s.\n",
3318
            query_str);
3319
3320
  /*Prepare the handlers to the query*/
3321
  success =
3322
      TRY(hand, OCIStmtPrepare(sthand->stmthp, hand->errhp, (text *)query_str,
3323
                               (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX,
3324
                               (ub4)OCI_DEFAULT)) &&
3325
      TRY(hand, OCIBindByName(sthand->stmthp, &bnd2p, hand->errhp,
3326
                              (text *)":table_name", strlen(":table_name"),
3327
                              (ub1 *)table_name, strlen(table_name) + 1,
3328
                              SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2)0, (ub4)0,
3329
                              (ub4 *)0, OCI_DEFAULT)) &&
3330
      TRY(hand,
3331
          OCIBindByName(sthand->stmthp, &bnd1p, hand->errhp,
3332
                        (text *)":geo_col_name", strlen(":geo_col_name"),
3333
                        (ub1 *)geom_column_name, strlen(geom_column_name) + 1,
3334
                        SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2)0, (ub4)0,
3335
                        (ub4 *)0, OCI_DEFAULT)) &&
3336
      TRY(hand, OCIDefineByPos(sthand->stmthp, &def1p, hand->errhp, (ub4)1,
3337
                               (dvoid *)wktext, (sb4)4000, SQLT_STR, (dvoid *)0,
3338
                               (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT)) &&
3339
      TRY(hand, OCIStmtExecute(hand->svchp, sthand->stmthp, hand->errhp, (ub4)0,
3340
                               (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL,
3341
                               (ub4)OCI_DEFAULT)) &&
3342
      TRY(hand, OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
3343
                           (dvoid *)&sthand->rows_fetched, (ub4 *)0,
3344
                           (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp));
3345
3346
  if (!success) {
3347
    msDebug("Error: %s . "
3348
            "Query statement: %s . "
3349
            "Check your data statement."
3350
            "in msOracleSpatialLayerGetAutoProjection()\n",
3351
            hand->last_oci_error, query_str);
3352
    msSetError(MS_ORACLESPATIALERR,
3353
               "Error "
3354
               "Check your data statement and server logs",
3355
               "msOracleSpatialLayerGetAutoProjection()");
3356
3357
    if (geom_column_name)
3358
      free(geom_column_name);
3359
    if (srid)
3360
      free(srid);
3361
    if (unique)
3362
      free(unique);
3363
    if (indexfield)
3364
      free(indexfield);
3365
    free(table_name);
3366
    return MS_FAILURE;
3367
  }
3368
  do {
3369
    success = TRY(hand, OCIStmtFetch(sthand->stmthp, hand->errhp, (ub4)1,
3370
                                     (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT)) &&
3371
              TRY(hand, OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
3372
                                   (dvoid *)&sthand->rows_fetched, (ub4 *)0,
3373
                                   (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp));
3374
    if (success && sthand->rows_fetched > 0) {
3375
3376
      if (layer->debug)
3377
        msDebug("Found WKT projection for table %s: %s\n", table_name, wktext);
3378
3379
      if (wktext != NULL && projection != NULL)
3380
        if (msOGCWKT2ProjectionObj(wktext, projection, layer->debug) ==
3381
            MS_FAILURE)
3382
          return (MS_FAILURE);
3383
    }
3384
  } while (sthand->rows_fetched > 0);
3385
3386
  if (geom_column_name)
3387
    free(geom_column_name);
3388
  if (srid)
3389
    free(srid);
3390
  if (unique)
3391
    free(unique);
3392
  if (indexfield)
3393
    free(indexfield);
3394
  free(table_name);
3395
  return MS_SUCCESS;
3396
}
3397
3398
/**********************************************************************
3399
 *             msOracleSpatialGetFieldDefn()
3400
 *
3401
 * Pass the field definitions through to the layer metadata in the
3402
 * "gml_[item]_{type,width,precision}" set of metadata items for
3403
 * defining fields.
3404
 **********************************************************************/
3405
static void
3406
msOracleSpatialGetFieldDefn(layerObj *layer, msOracleSpatialHandler *hand,
3407
                            const char *item, OCIParam *paramDescriptor)
3408
3409
{
3410
  const char *gml_type = "Character";
3411
  char gml_width[32], gml_precision[32];
3412
  int success;
3413
  ub2 rzttype, nOCILen;
3414
3415
  gml_width[0] = '\0';
3416
  gml_precision[0] = '\0';
3417
3418
  /* -------------------------------------------------------------------- */
3419
  /*      Get basic parameter details.                                    */
3420
  /* -------------------------------------------------------------------- */
3421
  success = TRY(hand, OCIAttrGet((dvoid *)paramDescriptor, (ub4)OCI_DTYPE_PARAM,
3422
                                 (dvoid *)&rzttype, (ub4 *)0,
3423
                                 (ub4)OCI_ATTR_DATA_TYPE, hand->errhp)) &&
3424
            TRY(hand, OCIAttrGet((dvoid *)paramDescriptor, (ub4)OCI_DTYPE_PARAM,
3425
                                 (dvoid *)&nOCILen, (ub4 *)0,
3426
                                 (ub4)OCI_ATTR_DATA_SIZE, hand->errhp));
3427
3428
  if (!success)
3429
    return;
3430
3431
  switch (rzttype) {
3432
  case SQLT_CHR:
3433
  case SQLT_AFC:
3434
    gml_type = "Character";
3435
    if (nOCILen <= 4000)
3436
      sprintf(gml_width, "%d", nOCILen);
3437
    break;
3438
3439
  case SQLT_NUM: {
3440
    /* NOTE: OCI docs say this should be ub1 type, but we have
3441
       determined that oracle is actually returning a short so we
3442
       use that type and try to compensate for possible problems by
3443
       initializing, and dividing by 256 if it is large. */
3444
    unsigned short byPrecision = 0;
3445
    sb1 nScale = 0;
3446
3447
    if (!TRY(hand, OCIAttrGet((dvoid *)paramDescriptor, (ub4)OCI_DTYPE_PARAM,
3448
                              (dvoid *)&byPrecision, (ub4 *)0,
3449
                              (ub4)OCI_ATTR_PRECISION, hand->errhp)) ||
3450
        !TRY(hand, OCIAttrGet((dvoid *)paramDescriptor, (ub4)OCI_DTYPE_PARAM,
3451
                              (dvoid *)&nScale, (ub4 *)0, (ub4)OCI_ATTR_SCALE,
3452
                              hand->errhp)))
3453
      return;
3454
    if (byPrecision > 255)
3455
      byPrecision = byPrecision / 256;
3456
3457
    if (nScale > 0) {
3458
      gml_type = "Real";
3459
      sprintf(gml_width, "%d", byPrecision);
3460
      sprintf(gml_precision, "%d", nScale);
3461
    } else if (nScale < 0)
3462
      gml_type = "Real";
3463
    else {
3464
      gml_type = "Integer";
3465
      if (byPrecision < 38)
3466
        sprintf(gml_width, "%d", byPrecision);
3467
    }
3468
  } break;
3469
3470
  case SQLT_DAT:
3471
  case SQLT_DATE:
3472
    gml_type = "Date";
3473
    break;
3474
  case SQLT_TIMESTAMP:
3475
  case SQLT_TIMESTAMP_TZ:
3476
  case SQLT_TIMESTAMP_LTZ:
3477
    gml_type = "DateTime";
3478
    break;
3479
  case SQLT_TIME:
3480
  case SQLT_TIME_TZ:
3481
    gml_type = "Time";
3482
    break;
3483
3484
  default:
3485
    gml_type = "Character";
3486
  }
3487
3488
  msUpdateGMLFieldMetadata(layer, item, gml_type, gml_width, gml_precision, 0);
3489
}
3490
3491
int msOracleSpatialLayerGetItems(layerObj *layer) {
3492
  char *rzt = "";
3493
  ub2 rzttype = 0;
3494
  char *flk = "";
3495
  int function = 0;
3496
  int version = 0;
3497
  int existgeom;
3498
  int count_item, flk_len, success, i;
3499
  char *table_name;
3500
  char *query_str = NULL, *geom_column_name = NULL, *unique = NULL,
3501
       *srid = NULL, *indexfield = NULL;
3502
  OCIParam *paramDescriptor = (OCIParam *)0;
3503
3504
  msOracleSpatialLayerInfo *layerinfo =
3505
      (msOracleSpatialLayerInfo *)layer->layerinfo;
3506
  msOracleSpatialHandler *hand = NULL;
3507
  msOracleSpatialStatement *sthand = NULL;
3508
  int get_field_details = 0;
3509
  const char *value;
3510
3511
  if (layer->debug >= 3)
3512
    msDebug("msOracleSpatialLayerGetItems was called.\n");
3513
3514
  if (layerinfo == NULL) {
3515
    msSetError(MS_ORACLESPATIALERR,
3516
               "msOracleSpatialLayerGetItems called on unopened layer",
3517
               "msOracleSpatialLayerGetItems()");
3518
    return MS_FAILURE;
3519
  } else {
3520
    hand = (msOracleSpatialHandler *)layerinfo->orahandlers;
3521
    sthand = (msOracleSpatialStatement *)layerinfo->orastmt;
3522
  }
3523
3524
  /* Will we want to capture the field details? */
3525
  if ((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL &&
3526
      strcasecmp(value, "auto") == 0)
3527
    get_field_details = 1;
3528
3529
  table_name = (char *)malloc(sizeof(char) * TABLE_NAME_SIZE);
3530
  if (!msSplitData(layer->data, &geom_column_name, &table_name, &unique, &srid,
3531
                   &indexfield, &function, &version)) {
3532
    msDebug("Error parsing OracleSpatial DATA variable. Must be: "
3533
            "'geometry_column FROM table_name [USING UNIQUE <column> SRID "
3534
            "srid# FUNCTION]' or "
3535
            "'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> SRID "
3536
            "srid# FUNCTION]'. "
3537
            "If want to set the FUNCTION statement you can use: FILTER, "
3538
            "RELATE, GEOMRELATE or NONE. "
3539
            "Your data statement: (%s)"
3540
            "in msOracleSpatialLayerGetItems()\n",
3541
            layer->data);
3542
    msSetError(MS_ORACLESPATIALERR,
3543
               "Error parsing OracleSpatial DATA variable. Check server logs. ",
3544
               "msOracleSpatialLayerGetItems()");
3545
3546
    if (geom_column_name)
3547
      free(geom_column_name);
3548
    if (srid)
3549
      free(srid);
3550
    if (unique)
3551
      free(unique);
3552
    if (indexfield)
3553
      free(indexfield);
3554
    free(table_name);
3555
    return MS_FAILURE;
3556
  }
3557
  query_str = msStringConcatenate(query_str, "SELECT * FROM ");
3558
  query_str = msStringConcatenate(query_str, table_name);
3559
3560
  success =
3561
      TRY(hand, OCIStmtPrepare(sthand->stmthp, hand->errhp, (text *)query_str,
3562
                               (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX,
3563
                               (ub4)OCI_DESCRIBE_ONLY)) &&
3564
      TRY(hand, OCIStmtExecute(hand->svchp, sthand->stmthp, hand->errhp,
3565
                               (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL,
3566
                               (OCISnapshot *)NULL, (ub4)OCI_DESCRIBE_ONLY)) &&
3567
      TRY(hand, OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
3568
                           (dvoid *)&layer->numitems, (ub4 *)0,
3569
                           OCI_ATTR_PARAM_COUNT, hand->errhp));
3570
3571
  if (!success) {
3572
    msSetError(MS_QUERYERR, "Cannot retrieve column list",
3573
               "msOracleSpatialLayerGetItems()");
3574
    if (geom_column_name)
3575
      free(geom_column_name);
3576
    if (srid)
3577
      free(srid);
3578
    if (unique)
3579
      free(unique);
3580
    if (indexfield)
3581
      free(indexfield);
3582
    if (query_str)
3583
      free(query_str);
3584
    free(table_name);
3585
    return MS_FAILURE;
3586
  }
3587
3588
  sthand->row_num = sthand->row = 0;
3589
  layer->numitems = layer->numitems - 1;
3590
3591
  layer->items = malloc(sizeof(char *) * (layer->numitems));
3592
  if (layer->items == NULL) {
3593
    msSetError(MS_ORACLESPATIALERR, "Cannot allocate items",
3594
               "msOracleSpatialLayerGetItems()");
3595
    if (geom_column_name)
3596
      free(geom_column_name);
3597
    if (srid)
3598
      free(srid);
3599
    if (unique)
3600
      free(unique);
3601
    if (indexfield)
3602
      free(indexfield);
3603
    if (query_str)
3604
      free(query_str);
3605
    free(table_name);
3606
    return MS_FAILURE;
3607
  }
3608
3609
  if (layer->numitems > 0) {
3610
    if (sthand->items_query == NULL)
3611
      sthand->items_query = (item_text_array_query *)malloc(
3612
          sizeof(item_text_array_query) * (layer->numitems));
3613
3614
    if (sthand->items_query == NULL) {
3615
      msSetError(MS_ORACLESPATIALERR, "Cannot allocate items buffer",
3616
                 "msOracleSpatialLayerGetItems()");
3617
      if (geom_column_name)
3618
        free(geom_column_name);
3619
      if (srid)
3620
        free(srid);
3621
      if (unique)
3622
        free(unique);
3623
      if (indexfield)
3624
        free(indexfield);
3625
      if (query_str)
3626
        free(query_str);
3627
      free(table_name);
3628
      return MS_FAILURE;
3629
    }
3630
  }
3631
3632
  count_item = 0;
3633
  existgeom = 0;
3634
3635
  /*Upcase conversion for the geom_column_name*/
3636
  for (i = 0; geom_column_name[i] != '\0'; i++)
3637
    geom_column_name[i] = toupper(geom_column_name[i]);
3638
3639
  /*Retrieve columns name from the user table*/
3640
  for (i = 0; i <= layer->numitems; i++) {
3641
3642
    success =
3643
        TRY(hand,
3644
            OCIParamGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
3645
                        hand->errhp, (dvoid *)&paramDescriptor, (ub4)i + 1)) &&
3646
        TRY(hand, OCIAttrGet((dvoid *)paramDescriptor, (ub4)OCI_DTYPE_PARAM,
3647
                             (dvoid *)&rzttype, (ub4 *)0,
3648
                             (ub4)OCI_ATTR_DATA_TYPE, hand->errhp)) &&
3649
        TRY(hand,
3650
            OCIParamGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
3651
                        hand->errhp, (dvoid *)&paramDescriptor, (ub4)i + 1)) &&
3652
        TRY(hand, OCIAttrGet((dvoid *)paramDescriptor, (ub4)OCI_DTYPE_PARAM,
3653
                             (dvoid *)&rzt, (ub4 *)&flk_len, (ub4)OCI_ATTR_NAME,
3654
                             hand->errhp));
3655
3656
    /*  if (layer->debug)
3657
           msDebug("msOracleSpatialLayerGetItems checking type. Column = %s Type
3658
       = %d\n", rzt, rzttype);  */
3659
    flk = (char *)malloc(sizeof(char *) * flk_len + 1);
3660
    if (flk == NULL) {
3661
      msSetError(MS_ORACLESPATIALERR,
3662
                 "No memory available to allocate the items",
3663
                 "msOracleSpatialLayerGetItems()");
3664
      if (geom_column_name)
3665
        free(geom_column_name);
3666
      if (srid)
3667
        free(srid);
3668
      if (unique)
3669
        free(unique);
3670
      if (query_str)
3671
        free(query_str);
3672
      free(table_name);
3673
      return MS_FAILURE;
3674
    } else {
3675
      // layer->iteminfo->dtype[i]= 1;
3676
      strlcpy(flk, rzt, flk_len + 1);
3677
    }
3678
3679
    /*Compare the column name (flk) with geom_column_name and ignore with true*/
3680
    if (strcmp(flk, geom_column_name) != 0) {
3681
      if (rzttype != OCI_TYPECODE_BLOB) {
3682
        layer->items[count_item] = (char *)malloc(sizeof(char) * flk_len + 1);
3683
        if (layer->items[count_item] == NULL) {
3684
          msSetError(MS_ORACLESPATIALERR,
3685
                     "No memory available to allocate the items buffer",
3686
                     "msOracleSpatialLayerGetItems()");
3687
          if (geom_column_name)
3688
            free(geom_column_name);
3689
          if (srid)
3690
            free(srid);
3691
          if (unique)
3692
            free(unique);
3693
          if (query_str)
3694
            free(query_str);
3695
          free(table_name);
3696
          return MS_FAILURE;
3697
        }
3698
3699
        strcpy(layer->items[count_item], flk);
3700
        count_item++;
3701
3702
        if (get_field_details)
3703
          msOracleSpatialGetFieldDefn(layer, hand, layer->items[count_item - 1],
3704
                                      paramDescriptor);
3705
      }
3706
    } else
3707
      existgeom = 1;
3708
3709
    strcpy(rzt, "");
3710
    free(flk); /* Better?!*/
3711
    flk_len = 0;
3712
  }
3713
3714
  layer->numitems = count_item;
3715
3716
  if (!(existgeom)) {
3717
    msSetError(MS_ORACLESPATIALERR, "No geometry column, check stmt",
3718
               "msOracleSpatialLayerGetItems()");
3719
    if (geom_column_name)
3720
      free(geom_column_name);
3721
    if (srid)
3722
      free(srid);
3723
    if (unique)
3724
      free(unique);
3725
    if (indexfield)
3726
      free(indexfield);
3727
    if (query_str)
3728
      free(query_str);
3729
    free(table_name);
3730
    return MS_FAILURE;
3731
  }
3732
3733
  if (geom_column_name)
3734
    free(geom_column_name);
3735
  if (srid)
3736
    free(srid);
3737
  if (unique)
3738
    free(unique);
3739
  if (indexfield)
3740
    free(indexfield);
3741
  if (query_str)
3742
    free(query_str);
3743
  free(table_name);
3744
  return msOracleSpatialLayerInitItemInfo(layer);
3745
}
3746
3747
int msOracleSpatialLayerGetExtent(layerObj *layer, rectObj *extent) {
3748
  char *table_name;
3749
  char *query_str = NULL, *geom_column_name = NULL, *unique = NULL,
3750
       *srid = NULL, *indexfield = NULL;
3751
  int success, i;
3752
  int function = 0;
3753
  int version = 0;
3754
  SDOGeometryObj *obj = NULL;
3755
  SDOGeometryInd *ind = NULL;
3756
  shapeObj shape;
3757
  rectObj bounds;
3758
  /*OCIDefine *adtp = NULL, *items[QUERY_SIZE] = { NULL };*/
3759
  OCIDefine *adtp = NULL;
3760
  OCIDefine **items = NULL;
3761
3762
  msOracleSpatialLayerInfo *layerinfo =
3763
      (msOracleSpatialLayerInfo *)layer->layerinfo;
3764
  msOracleSpatialDataHandler *dthand = NULL;
3765
  msOracleSpatialHandler *hand = NULL;
3766
  msOracleSpatialStatement *sthand = NULL;
3767
3768
  if (layer->debug >= 3)
3769
    msDebug("msOracleSpatialLayerGetExtent was called.\n");
3770
3771
  if (layerinfo == NULL) {
3772
    msSetError(MS_ORACLESPATIALERR,
3773
               "msOracleSpatialLayerGetExtent called on unopened layer",
3774
               "msOracleSpatialLayerGetExtent()");
3775
    return MS_FAILURE;
3776
  } else {
3777
    dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers;
3778
    hand = (msOracleSpatialHandler *)layerinfo->orahandlers;
3779
    sthand = (msOracleSpatialStatement *)layerinfo->orastmt;
3780
  }
3781
3782
  /* allocate enough space for items */
3783
  if (layer->numitems > 0) {
3784
    sthand->items_query = (item_text_array_query *)malloc(
3785
        sizeof(item_text_array_query) * (layer->numitems));
3786
    if (sthand->items_query == NULL) {
3787
      msSetError(MS_ORACLESPATIALERR, "Cannot allocate layerinfo->items buffer",
3788
                 "msOracleSpatialLayerGetExtent()");
3789
      return MS_FAILURE;
3790
    }
3791
    items = (OCIDefine **)malloc(sizeof(OCIDefine *) * layer->numitems);
3792
    if (items == NULL) {
3793
      msSetError(MS_ORACLESPATIALERR, "Cannot allocate items buffer",
3794
                 "msOracleSpatialLayerWhichShapes()");
3795
      return MS_FAILURE;
3796
    }
3797
    memset(items, 0, sizeof(OCIDefine *) * layer->numitems);
3798
  }
3799
3800
  table_name = (char *)malloc(sizeof(char) * TABLE_NAME_SIZE);
3801
  if (!msSplitData(layer->data, &geom_column_name, &table_name, &unique, &srid,
3802
                   &indexfield, &function, &version)) {
3803
    msDebug("Error parsing OracleSpatial DATA variable. Must be: "
3804
            "'geometry_column FROM table_name [USING UNIQUE <column> SRID "
3805
            "srid# FUNCTION]' or "
3806
            "'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> SRID "
3807
            "srid# FUNCTION]'. "
3808
            "If want to set the FUNCTION statement you can use: FILTER, "
3809
            "RELATE, GEOMRELATE or NONE. "
3810
            "Your data statement: (%s) "
3811
            "in msOracleSpatialLayerGetExtent()\n",
3812
            layer->data);
3813
    msSetError(MS_ORACLESPATIALERR,
3814
               "Error parsing OracleSpatial DATA variable. Check server logs. ",
3815
               "msOracleSpatialLayerGetExtent()");
3816
    /* clean items */
3817
    free(items);
3818
3819
    if (geom_column_name)
3820
      free(geom_column_name);
3821
    if (srid)
3822
      free(srid);
3823
    if (unique)
3824
      free(unique);
3825
    if (indexfield)
3826
      free(indexfield);
3827
    free(table_name);
3828
3829
    return MS_FAILURE;
3830
  }
3831
3832
  query_str = osAggrGetExtent(layer, query_str, geom_column_name, table_name);
3833
3834
  if (layer->debug >= 3)
3835
    msDebug("msOracleSpatialLayerGetExtent. Using this Sql to retrieve the "
3836
            "extent: %s.\n",
3837
            query_str);
3838
3839
  /*Prepare the handlers to the query*/
3840
  success = TRY(hand, OCIStmtPrepare(sthand->stmthp, hand->errhp,
3841
                                     (text *)query_str, (ub4)strlen(query_str),
3842
                                     (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT));
3843
3844
  if (success && layer->numitems > 0) {
3845
    for (i = 0; i < layer->numitems && success; ++i)
3846
      success =
3847
          TRY(hand, OCIDefineByPos(sthand->stmthp, &items[i], hand->errhp,
3848
                                   (ub4)i + 1, (dvoid *)sthand->items_query[i],
3849
                                   (sb4)TEXT_SIZE, SQLT_STR, (dvoid *)0,
3850
                                   (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT));
3851
  }
3852
3853
  if (!success) {
3854
    msDebug("Error: %s . "
3855
            "Query statement: %s . "
3856
            "Check your data statement."
3857
            "in msOracleSpatialLayerGetExtent()\n",
3858
            hand->last_oci_error, query_str);
3859
3860
    msSetError(MS_ORACLESPATIALERR, "Check your data statement and server logs",
3861
               "msOracleSpatialLayerGetExtent()");
3862
3863
    /* clean items */
3864
    free(items);
3865
3866
    if (query_str)
3867
      free(query_str);
3868
3869
    if (geom_column_name)
3870
      free(geom_column_name);
3871
    if (srid)
3872
      free(srid);
3873
    if (unique)
3874
      free(unique);
3875
    if (indexfield)
3876
      free(indexfield);
3877
    free(table_name);
3878
3879
    return MS_FAILURE;
3880
  }
3881
3882
  if (success) {
3883
    success =
3884
        TRY(hand, OCIDefineByPos(sthand->stmthp, &adtp, hand->errhp,
3885
                                 (ub4)layer->numitems + 1, (dvoid *)0, (sb4)0,
3886
                                 SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0,
3887
                                 (ub4)OCI_DEFAULT)) &&
3888
        TRY(hand, OCIDefineObject(adtp, hand->errhp, dthand->tdo,
3889
                                  (dvoid **)sthand->obj, (ub4 *)0,
3890
                                  (dvoid **)sthand->ind, (ub4 *)0)) &&
3891
        TRY(hand, OCIStmtExecute(hand->svchp, sthand->stmthp, hand->errhp,
3892
                                 (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL,
3893
                                 (OCISnapshot *)NULL, (ub4)OCI_DEFAULT)) &&
3894
        TRY(hand, OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
3895
                             (dvoid *)&sthand->rows_fetched, (ub4 *)0,
3896
                             (ub4)OCI_ATTR_ROW_COUNT, hand->errhp));
3897
  }
3898
3899
  if (!success) {
3900
    msDebug("Error: %s . "
3901
            "Query statement: %s ."
3902
            "Check your data statement."
3903
            "in msOracleSpatialLayerGetExtent()\n",
3904
            hand->last_oci_error, query_str);
3905
    msSetError(MS_ORACLESPATIALERR, "Check your data statement and server logs",
3906
               "msOracleSpatialLayerGetExtent()");
3907
3908
    /* clean items */
3909
    free(items);
3910
    if (query_str)
3911
      free(query_str);
3912
    if (geom_column_name)
3913
      free(geom_column_name);
3914
    if (srid)
3915
      free(srid);
3916
    if (unique)
3917
      free(unique);
3918
    if (indexfield)
3919
      free(indexfield);
3920
    free(table_name);
3921
3922
    return MS_FAILURE;
3923
  }
3924
3925
  /* should begin processing first row */
3926
  sthand->row_num = sthand->row = 0;
3927
  msInitShape(&shape);
3928
  do {
3929
    /* is buffer empty? */
3930
    if (sthand->row_num >= sthand->rows_fetched) {
3931
      /* fetch more */
3932
      success =
3933
          TRY(hand, OCIStmtFetch(sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE,
3934
                                 (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT)) &&
3935
          TRY(hand, OCIAttrGet((dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT,
3936
                               (dvoid *)&sthand->rows_fetched, (ub4 *)0,
3937
                               (ub4)OCI_ATTR_ROW_COUNT, hand->errhp));
3938
3939
      if (!success || sthand->rows_fetched == 0 ||
3940
          sthand->row_num >= sthand->rows_fetched) {
3941
        hand->last_oci_status = MS_SUCCESS;
3942
        break;
3943
      }
3944
3945
      sthand->row = 0; /* reset row index */
3946
    }
3947
3948
    /* no rows fetched */
3949
    if (sthand->rows_fetched == 0)
3950
      break;
3951
3952
    obj = sthand->obj[sthand->row];
3953
    ind = sthand->ind[sthand->row];
3954
3955
    /* get the items for the shape */
3956
    shape.numvalues = layer->numitems;
3957
    shape.values = (char **)malloc(sizeof(char *) * layer->numitems);
3958
    if (shape.values == NULL) {
3959
      msSetError(MS_ORACLESPATIALERR,
3960
                 "No memory available to allocate the values.",
3961
                 "msOracleSpatialLayerGetExtent()");
3962
      if (geom_column_name)
3963
        free(geom_column_name);
3964
      if (srid)
3965
        free(srid);
3966
      if (unique)
3967
        free(unique);
3968
      if (indexfield)
3969
        free(indexfield);
3970
      if (query_str)
3971
        free(query_str);
3972
      free(table_name);
3973
      return MS_FAILURE;
3974
    }
3975
3976
    shape.index = sthand->row_num;
3977
3978
    for (i = 0; i < layer->numitems; ++i) {
3979
      shape.values[i] = (char *)malloc(
3980
          strlen((char *)sthand->items_query[sthand->row][i]) + 1);
3981
3982
      if (shape.values[i] == NULL) {
3983
        msSetError(MS_ORACLESPATIALERR,
3984
                   "No memory available to allocate the items buffer.",
3985
                   "msOracleSpatialLayerGetExtent()");
3986
3987
        /* clean items */
3988
        free(items);
3989
3990
        if (geom_column_name)
3991
          free(geom_column_name);
3992
        if (srid)
3993
          free(srid);
3994
        if (unique)
3995
          free(unique);
3996
        if (indexfield)
3997
          free(indexfield);
3998
        if (query_str)
3999
          free(query_str);
4000
        free(table_name);
4001
4002
        return MS_FAILURE;
4003
      } else {
4004
        strcpy(shape.values[i], (char *)sthand->items_query[sthand->row][i]);
4005
        shape.values[i][strlen((char *)sthand->items_query[sthand->row][i])] =
4006
            '\0';
4007
      }
4008
    }
4009
4010
    /* increment for next row */
4011
    sthand->row_num++;
4012
    sthand->row++;
4013
4014
    /* fetch a layer->type object */
4015
    success = osGetOrdinates(dthand, hand, &shape, obj, ind);
4016
    if (success != MS_SUCCESS) {
4017
      msSetError(MS_ORACLESPATIALERR, "Cannot execute query",
4018
                 "msOracleSpatialLayerGetExtent()");
4019
4020
      /* clean items */
4021
      free(items);
4022
4023
      if (geom_column_name)
4024
        free(geom_column_name);
4025
      if (srid)
4026
        free(srid);
4027
      if (unique)
4028
        free(unique);
4029
      if (indexfield)
4030
        free(indexfield);
4031
      if (query_str)
4032
        free(query_str);
4033
      free(table_name);
4034
4035
      return MS_FAILURE;
4036
    }
4037
4038
  } while (sthand->row <= sthand->rows_fetched);
4039
4040
  sthand->row = sthand->row_num = 0;
4041
4042
  osShapeBounds(&shape);
4043
  bounds = shape.bounds;
4044
4045
  extent->minx = bounds.minx;
4046
  extent->miny = bounds.miny;
4047
  extent->maxx = bounds.maxx;
4048
  extent->maxy = bounds.maxy;
4049
4050
  msFreeShape(&shape);
4051
4052
  /* clean items */
4053
  free(items);
4054
4055
  if (geom_column_name)
4056
    free(geom_column_name);
4057
  if (srid)
4058
    free(srid);
4059
  if (unique)
4060
    free(unique);
4061
  if (indexfield)
4062
    free(indexfield);
4063
  if (query_str)
4064
    free(query_str);
4065
  free(table_name);
4066
4067
  return (MS_SUCCESS);
4068
}
4069
4070
void msOracleSpatialLayerFreeItemInfo(layerObj *layer) {
4071
  if (layer->debug >= 3)
4072
    msDebug("msOracleSpatialLayerFreeItemInfo was called.\n");
4073
4074
  if (layer->iteminfo)
4075
    free(layer->iteminfo);
4076
4077
  layer->iteminfo = NULL;
4078
  /* nothing to do */
4079
}
4080
4081
int msOracleSpatialLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c,
4082
                                     shapeObj *shape) {
4083
  (void)map;
4084
  (void)layer;
4085
  (void)c;
4086
  (void)shape;
4087
  msSetError(MS_ORACLESPATIALERR, "Function not implemented yet",
4088
             "msLayerGetAutoStyle()");
4089
  return MS_FAILURE;
4090
}
4091
4092
/************************************************************************/
4093
/*                       msOracleSpatialEscapePropertyName              */
4094
/*                                                                      */
4095
/*      Return the property name in a properly escaped and quoted form. */
4096
/************************************************************************/
4097
char *msOracleSpatialEscapePropertyName(layerObj *layer,
4098
                                        const char *pszString) {
4099
  char *pszEscapedStr = NULL;
4100
  int i, j = 0;
4101
4102
  if (layer && pszString && strlen(pszString) > 0) {
4103
    int nLength = strlen(pszString);
4104
4105
    pszEscapedStr = (char *)msSmallMalloc(1 + 2 * nLength + 1 + 1);
4106
    // pszEscapedStr[j++] = '';
4107
4108
    for (i = 0; i < nLength; i++) {
4109
      char c = pszString[i];
4110
      if (c == '"') {
4111
        pszEscapedStr[j++] = '"';
4112
        pszEscapedStr[j++] = '"';
4113
      } else if (c == '\\') {
4114
        pszEscapedStr[j++] = '\\';
4115
        pszEscapedStr[j++] = '\\';
4116
      } else
4117
        pszEscapedStr[j++] = c;
4118
    }
4119
    // pszEscapedStr[j++] = '';
4120
    pszEscapedStr[j++] = 0;
4121
  }
4122
  return pszEscapedStr;
4123
}
4124
4125
int msOracleSpatialGetPaging(layerObj *layer) {
4126
  msOracleSpatialLayerInfo *layerinfo = NULL;
4127
4128
  // if (layer->debug)
4129
  //   msDebug("msOracleSpatialLayerGetPaging was called.\n");
4130
4131
  if (!msOracleSpatialLayerIsOpen(layer))
4132
    return MS_TRUE;
4133
4134
  assert(layer->layerinfo != NULL);
4135
  layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo;
4136
4137
  return layerinfo->paging;
4138
}
4139
4140
void msOracleSpatialEnablePaging(layerObj *layer, int value) {
4141
  msOracleSpatialLayerInfo *layerinfo = NULL;
4142
4143
  if (layer->debug >= 3)
4144
    msDebug("msOracleSpatialLayerEnablePaging was called.\n");
4145
4146
  if (!msOracleSpatialLayerIsOpen(layer)) {
4147
    if (msOracleSpatialLayerOpen(layer) != MS_SUCCESS) {
4148
      return;
4149
    }
4150
  }
4151
4152
  assert(layer->layerinfo != NULL);
4153
  layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo;
4154
4155
  layerinfo->paging = value;
4156
4157
  return;
4158
}
4159
4160
int msOracleSpatialLayerTranslateFilter(layerObj *layer, expressionObj *filter,
4161
                                        char *filteritem) {
4162
  char *native_string = NULL;
4163
4164
  int nodeCount = 0;
4165
4166
  int function = 0, version = 0, dwithin = 0, regexp_like = 0, case_ins = 0,
4167
      ieq = 0;
4168
  char *table_name = NULL;
4169
  char *geom_column_name = NULL, *unique = NULL, *srid = NULL,
4170
       *indexfield = NULL;
4171
  char *snippet = NULL;
4172
  char *strtmpl = NULL;
4173
  double dfDistance = -1;
4174
4175
  table_name = (char *)malloc(sizeof(char) * TABLE_NAME_SIZE);
4176
  if (!msSplitData(layer->data, &geom_column_name, &table_name, &unique, &srid,
4177
                   &indexfield, &function, &version)) {
4178
    msDebug("Error parsing OracleSpatial DATA variable. Must be: "
4179
            "'geometry_column FROM table_name [USING UNIQUE <column> SRID "
4180
            "srid# FUNCTION]' or "
4181
            "'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> SRID "
4182
            "srid# FUNCTION]'. "
4183
            "If want to set the FUNCTION statement you can use: FILTER, "
4184
            "RELATE, GEOMRELATE or NONE. "
4185
            "Your data statement: (%s)"
4186
            "in msOracleSpatialLayerGetExtent()\n",
4187
            layer->data);
4188
    msSetError(MS_ORACLESPATIALERR,
4189
               "Error parsing OracleSpatial DATA variable. Check server logs. ",
4190
               "msOracleSpatialLayerGetExtent()");
4191
    /* clean items */
4192
4193
    if (geom_column_name)
4194
      free(geom_column_name);
4195
    if (srid)
4196
      free(srid);
4197
    if (unique)
4198
      free(unique);
4199
    if (indexfield)
4200
      free(indexfield);
4201
    if (table_name)
4202
      free(table_name);
4203
4204
    return MS_FAILURE;
4205
  }
4206
4207
  // msDebug("filter.string was set: %s\n",filter->string);
4208
  if (!filter->string) {
4209
    if (geom_column_name)
4210
      free(geom_column_name);
4211
    if (srid)
4212
      free(srid);
4213
    if (unique)
4214
      free(unique);
4215
    if (indexfield)
4216
      free(indexfield);
4217
    if (table_name)
4218
      free(table_name);
4219
4220
    return MS_SUCCESS;
4221
  }
4222
  /* for backwards compatibility we continue to allow SQL snippets as a string
4223
   */
4224
4225
  if (filter->type == MS_STRING && filter->string &&
4226
      filteritem) { /* item/value pair */
4227
    if (filter->flags & MS_EXP_INSENSITIVE) {
4228
      native_string = msStringConcatenate(native_string, "upper(");
4229
      native_string = msStringConcatenate(native_string, filteritem);
4230
      native_string = msStringConcatenate(native_string, ") = upper(");
4231
    } else {
4232
      native_string = msStringConcatenate(native_string, filteritem);
4233
      native_string = msStringConcatenate(native_string, " = ");
4234
    }
4235
4236
    strtmpl = "'%s'"; /* don't have a type for the righthand literal so assume
4237
                         it's a string and we quote */
4238
    snippet = (char *)msSmallMalloc(strlen(strtmpl) + strlen(filter->string));
4239
    sprintf(snippet, strtmpl, filter->string); // TODO: escape filter->string
4240
                                               // (msPostGISEscapeSQLParam)
4241
    native_string = msStringConcatenate(native_string, snippet);
4242
    free(snippet);
4243
4244
    if (filter->flags & MS_EXP_INSENSITIVE)
4245
      native_string = msStringConcatenate(native_string, ")");
4246
4247
    if (layer->debug >= 2)
4248
      msDebug("msOracleSpatialLayerTranslateFilter: **item/value combo: %s\n",
4249
              native_string);
4250
  } else if (filter->type == MS_REGEX && filter->string &&
4251
             filteritem) { /* item/regex pair */
4252
    native_string = msStringConcatenate(native_string, "REGEXP_LIKE (");
4253
    native_string = msStrdup(filteritem);
4254
    native_string = msStringConcatenate(native_string, ", ");
4255
    strtmpl = "'%s'";
4256
    snippet = (char *)msSmallMalloc(strlen(strtmpl) + strlen(filter->string));
4257
    sprintf(snippet, strtmpl, filter->string); // TODO: escape filter->string
4258
                                               // (msPostGISEscapeSQLParam)
4259
    native_string = msStringConcatenate(native_string, snippet);
4260
4261
    if (filter->flags & MS_EXP_INSENSITIVE) {
4262
      native_string = msStringConcatenate(native_string, ",i ");
4263
    }
4264
    native_string = msStringConcatenate(native_string, " )");
4265
    free(snippet);
4266
  } else if (filter->type == MS_EXPRESSION) {
4267
4268
    tokenListNodeObjPtr node = NULL;
4269
    // tokenListNodeObjPtr nextNode = NULL;
4270
4271
    if (layer->debug > 2)
4272
      msDebug("msOracleSpatialLayerTranslateFilter. String: %s \n",
4273
              filter->string);
4274
    if (layer->debug > 2 && !filter->tokens)
4275
      msDebug("msOracleSpatialLayerTranslateFilter. No tokens to process\n");
4276
4277
    if (!filter->tokens)
4278
      return MS_SUCCESS; /* nothing to work from */
4279
4280
    if (layer->debug > 2)
4281
      msDebug("msOracleSpatialLayerTranslateFilter. There are tokens to "
4282
              "process \n");
4283
4284
    /* try to convert tokens */
4285
    node = filter->tokens;
4286
    while (node != NULL) {
4287
      // msDebug("token count :%i, token is %i\n", nodeCount, node->token);
4288
      switch (node->token) {
4289
      case '(':
4290
        // if (buffer == MS_FALSE)
4291
        native_string = msStringConcatenate(native_string, "( ");
4292
        break;
4293
      case ')':
4294
        if (regexp_like == MS_TRUE) {
4295
          if (case_ins == MS_TRUE) {
4296
            native_string = msStringConcatenate(native_string, ",'i' ");
4297
            case_ins = MS_FALSE;
4298
          }
4299
          regexp_like = MS_FALSE;
4300
          native_string = msStringConcatenate(native_string, " )");
4301
          msDebug("closing RE comparison\n");
4302
        }
4303
        native_string = msStringConcatenate(native_string, " )");
4304
        break;
4305
      case MS_TOKEN_LITERAL_NUMBER: {
4306
        char buffer[32];
4307
        if (dwithin == MS_TRUE) {
4308
          dfDistance = node->tokenval.dblval;
4309
          if (layer->units == MS_DD) {
4310
            dfDistance *=
4311
                msInchesPerUnit(MS_DD, 0) / msInchesPerUnit(MS_METERS, 0);
4312
            // msDebug("Converted Distance value is %lf\n", dfDistance);
4313
          }
4314
          snprintf(buffer, sizeof(buffer), "%.18g", dfDistance);
4315
          native_string = msStringConcatenate(native_string, "'distance=");
4316
          native_string = msStringConcatenate(native_string, buffer);
4317
          native_string = msStringConcatenate(native_string, "'");
4318
        } else {
4319
          snprintf(buffer, sizeof(buffer), "%.18g", node->tokenval.dblval);
4320
          native_string = msStringConcatenate(native_string, buffer);
4321
        }
4322
        break;
4323
      }
4324
      case MS_TOKEN_LITERAL_STRING:
4325
        strtmpl = "%s";
4326
        snippet = (char *)msSmallMalloc(strlen(strtmpl) +
4327
                                        strlen(node->tokenval.strval));
4328
        sprintf(snippet, strtmpl, node->tokenval.strval); // TODO: escape strval
4329
        snippet = msReplaceSubstring(snippet, "'", "''");
4330
        native_string = msStringConcatenate(native_string, "'");
4331
        if (ieq == MS_TRUE) {
4332
          native_string = msStringConcatenate(native_string, "^");
4333
        }
4334
        native_string = msStringConcatenate(native_string, snippet);
4335
        if (ieq == MS_TRUE) {
4336
          native_string = msStringConcatenate(native_string, "$");
4337
        }
4338
        native_string = msStringConcatenate(native_string, "'");
4339
        if (ieq == MS_TRUE) {
4340
          native_string = msStringConcatenate(native_string, ")");
4341
          ieq = MS_FALSE;
4342
        }
4343
        msFree(snippet);
4344
        break;
4345
      case MS_TOKEN_LITERAL_BOOLEAN:
4346
        if (node->tokenval.dblval == MS_TRUE)
4347
          native_string = msStringConcatenate(native_string, "'TRUE'");
4348
        else
4349
          native_string = msStringConcatenate(native_string, "'FALSE'");
4350
        break;
4351
      case MS_TOKEN_LITERAL_TIME: {
4352
        int resolution = msTimeGetResolution(node->tokensrc);
4353
        snippet = (char *)msSmallMalloc(128);
4354
        switch (resolution) {
4355
        case TIME_RESOLUTION_YEAR:
4356
          strtmpl = "to_date('%d-01','YYYY-MM')";
4357
          sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year + 1900));
4358
          break;
4359
        case TIME_RESOLUTION_MONTH:
4360
          strtmpl = "to_date('%d-%02d','YYYY-MM')";
4361
          sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year + 1900),
4362
                  (node->tokenval.tmval.tm_mon + 1));
4363
          break;
4364
        case TIME_RESOLUTION_DAY:
4365
          strtmpl = "to_date('%d-%02d-%02d','YYYY-MM-DD') ";
4366
          sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year + 1900),
4367
                  (node->tokenval.tmval.tm_mon + 1),
4368
                  node->tokenval.tmval.tm_mday);
4369
          break;
4370
        case TIME_RESOLUTION_HOUR:
4371
          strtmpl = "to_timestamp('%d-%02d-%02d %02d','YYYY-MM-DD hh24')";
4372
          sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year + 1900),
4373
                  (node->tokenval.tmval.tm_mon + 1),
4374
                  node->tokenval.tmval.tm_mday, node->tokenval.tmval.tm_hour);
4375
          break;
4376
        case TIME_RESOLUTION_MINUTE:
4377
          strtmpl =
4378
              "to_timestamp('%d-%02d-%02d %02d:%02d','YYYY-MM-DD hh24:mi')";
4379
          sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year + 1900),
4380
                  (node->tokenval.tmval.tm_mon + 1),
4381
                  node->tokenval.tmval.tm_mday, node->tokenval.tmval.tm_hour,
4382
                  node->tokenval.tmval.tm_min);
4383
          break;
4384
        case TIME_RESOLUTION_SECOND:
4385
          strtmpl = "to_timestamp('%d-%02d-%02d %02d:%02d:%02d','YYYY-MM-DD "
4386
                    "hh24:mi:ss')";
4387
          sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year + 1900),
4388
                  (node->tokenval.tmval.tm_mon + 1),
4389
                  node->tokenval.tmval.tm_mday, node->tokenval.tmval.tm_hour,
4390
                  node->tokenval.tmval.tm_min, node->tokenval.tmval.tm_sec);
4391
          break;
4392
        }
4393
        native_string = msStringConcatenate(native_string, snippet);
4394
        msFree(snippet);
4395
        break;
4396
      }
4397
      case MS_TOKEN_LITERAL_SHAPE:
4398
        native_string = msStringConcatenate(native_string, " SDO_GEOMETRY('");
4399
        native_string = msStringConcatenate(
4400
            native_string, msShapeToWKT(node->tokenval.shpval));
4401
        native_string = msStringConcatenate(native_string, "'");
4402
        if (srid && strcmp(srid, "") != 0) {
4403
          native_string = msStringConcatenate(native_string, ", ");
4404
          native_string = msStringConcatenate(native_string, srid);
4405
        }
4406
        native_string = msStringConcatenate(native_string, ") ");
4407
        // msDebug("------> srid node value: %s", node->tokenval.shpval);
4408
        break;
4409
      case MS_TOKEN_BINDING_DOUBLE:
4410
        native_string =
4411
            msStringConcatenate(native_string, node->tokenval.bindval.item);
4412
        break;
4413
      case MS_TOKEN_BINDING_INTEGER:
4414
        native_string =
4415
            msStringConcatenate(native_string, node->tokenval.bindval.item);
4416
        break;
4417
      case MS_TOKEN_BINDING_STRING:
4418
        if (node->next->token == MS_TOKEN_COMPARISON_RE ||
4419
            node->next->token == MS_TOKEN_COMPARISON_IRE ||
4420
            node->next->token == MS_TOKEN_COMPARISON_IEQ) {
4421
          native_string = msStringConcatenate(native_string, "REGEXP_LIKE( ");
4422
        }
4423
        strtmpl = "%s";
4424
        snippet = (char *)msSmallMalloc(strlen(strtmpl) +
4425
                                        strlen(node->tokenval.strval));
4426
        sprintf(snippet, strtmpl,
4427
                node->tokenval
4428
                    .strval); // TODO: escape strval (msPostGISEscapeSQLParam)
4429
        native_string = msStringConcatenate(native_string, snippet);
4430
        free(snippet);
4431
        break;
4432
      case MS_TOKEN_BINDING_TIME:
4433
        native_string =
4434
            msStringConcatenate(native_string, node->tokenval.bindval.item);
4435
        break;
4436
      case MS_TOKEN_BINDING_SHAPE:
4437
        native_string = msStringConcatenate(native_string, geom_column_name);
4438
        break;
4439
      case MS_TOKEN_BINDING_MAP_CELLSIZE: {
4440
        char buffer[32];
4441
        snprintf(buffer, sizeof(buffer), "%.18g", layer->map->cellsize);
4442
        native_string = msStringConcatenate(native_string, buffer);
4443
        break;
4444
      }
4445
      case MS_TOKEN_LOGICAL_AND:
4446
        native_string = msStringConcatenate(native_string, " AND ");
4447
        break;
4448
      case MS_TOKEN_LOGICAL_OR:
4449
        native_string = msStringConcatenate(native_string, " OR ");
4450
        break;
4451
      case MS_TOKEN_LOGICAL_NOT:
4452
        native_string = msStringConcatenate(native_string, " NOT ");
4453
        break;
4454
      case MS_TOKEN_COMPARISON_EQ:
4455
        native_string = msStringConcatenate(native_string, " = ");
4456
        break;
4457
      case MS_TOKEN_COMPARISON_NE:
4458
        native_string = msStringConcatenate(native_string, " != ");
4459
        break;
4460
      case MS_TOKEN_COMPARISON_GT:
4461
        native_string = msStringConcatenate(native_string, " > ");
4462
        break;
4463
      case MS_TOKEN_COMPARISON_GE:
4464
        native_string = msStringConcatenate(native_string, " >= ");
4465
        break;
4466
      case MS_TOKEN_COMPARISON_LT:
4467
        native_string = msStringConcatenate(native_string, " < ");
4468
        break;
4469
      case MS_TOKEN_COMPARISON_LE:
4470
        native_string = msStringConcatenate(native_string, " <= ");
4471
        break;
4472
      case MS_TOKEN_COMPARISON_IEQ:
4473
        // this is for  case insensitive equals check
4474
        msDebug("got a IEQ comparison\n");
4475
        regexp_like = MS_TRUE;
4476
        case_ins = MS_TRUE;
4477
        ieq = MS_TRUE;
4478
        native_string = msStringConcatenate(native_string, ", ");
4479
        break;
4480
      case MS_TOKEN_COMPARISON_RE:
4481
        // the regex formats that MS uses as Oracle users are different so just
4482
        // return and eval the regex's in MS
4483
        // return MS_SUCCESS;
4484
        msDebug("got a RE comparison\n");
4485
        regexp_like = MS_TRUE;
4486
        native_string = msStringConcatenate(native_string, ", ");
4487
        break;
4488
      case MS_TOKEN_COMPARISON_IRE:
4489
        // the regex formats that MS uses as Oracle users are different so just
4490
        // return and eval the regex's in MS
4491
        regexp_like = MS_TRUE;
4492
        case_ins = MS_TRUE;
4493
        native_string = msStringConcatenate(native_string, ", ");
4494
        break;
4495
      case MS_TOKEN_COMPARISON_IN:
4496
        native_string = msStringConcatenate(native_string, " IN ");
4497
        break;
4498
      case MS_TOKEN_COMPARISON_INTERSECTS:
4499
        native_string = msStringConcatenate(native_string, " ST_INTERSECTS ");
4500
        break;
4501
      case MS_TOKEN_COMPARISON_DISJOINT:
4502
        native_string =
4503
            msStringConcatenate(native_string, " NOT ST_INTERSECTS ");
4504
        break;
4505
      case MS_TOKEN_COMPARISON_TOUCHES:
4506
        native_string = msStringConcatenate(native_string, " ST_TOUCH ");
4507
        break;
4508
      case MS_TOKEN_COMPARISON_OVERLAPS:
4509
        native_string = msStringConcatenate(native_string, " ST_OVERLAPS ");
4510
        break;
4511
      case MS_TOKEN_COMPARISON_CROSSES:
4512
        native_string =
4513
            msStringConcatenate(native_string, " SDO_OVERLAPBDYDISJOINT ");
4514
        break;
4515
      case MS_TOKEN_COMPARISON_WITHIN:
4516
        native_string = msStringConcatenate(native_string, " ST_INSIDE ");
4517
        break;
4518
      case MS_TOKEN_COMPARISON_CONTAINS:
4519
        native_string = msStringConcatenate(native_string, " SDO_CONTAINS ");
4520
        break;
4521
      case MS_TOKEN_COMPARISON_EQUALS:
4522
        native_string = msStringConcatenate(native_string, " SDO_EQUAL ");
4523
        break;
4524
      case MS_TOKEN_COMPARISON_BEYOND:
4525
        // support for the wfs case
4526
        dwithin = MS_TRUE;
4527
        native_string =
4528
            msStringConcatenate(native_string, "NOT SDO_WITHIN_DISTANCE ");
4529
        break;
4530
      case MS_TOKEN_COMPARISON_DWITHIN:
4531
        dwithin = MS_TRUE;
4532
        native_string =
4533
            msStringConcatenate(native_string, "SDO_WITHIN_DISTANCE ");
4534
        break;
4535
      case MS_TOKEN_FUNCTION_LENGTH:
4536
        break;
4537
      case MS_TOKEN_FUNCTION_TOSTRING:
4538
        break;
4539
      case MS_TOKEN_FUNCTION_COMMIFY:
4540
        break;
4541
      case MS_TOKEN_FUNCTION_AREA:
4542
        native_string =
4543
            msStringConcatenate(native_string, "SDO_GEOM.SDO_AREA ");
4544
        break;
4545
      case MS_TOKEN_FUNCTION_ROUND:
4546
        native_string = msStringConcatenate(native_string, "ROUND ");
4547
        break;
4548
      case MS_TOKEN_FUNCTION_FROMTEXT:
4549
        native_string = msStringConcatenate(native_string, "SDO_GEOMETRY ");
4550
        break;
4551
      case MS_TOKEN_FUNCTION_BUFFER:
4552
        // native_string = msStringConcatenate(native_string, " SDO_BUFFER ");
4553
        // buffer = MS_TRUE;
4554
        break;
4555
      case MS_TOKEN_FUNCTION_DIFFERENCE:
4556
        native_string = msStringConcatenate(native_string, "ST_DIFFERENCE ");
4557
        break;
4558
      case MS_TOKEN_FUNCTION_SIMPLIFY:
4559
        native_string =
4560
            msStringConcatenate(native_string, "SDO_UTIL.SIMPLIFY ");
4561
        break;
4562
      case MS_TOKEN_FUNCTION_SIMPLIFYPT:
4563
        break;
4564
      case MS_TOKEN_FUNCTION_GENERALIZE:
4565
        native_string =
4566
            msStringConcatenate(native_string, "SDO_UTIL.SIMPLIFY ");
4567
        break;
4568
      case ',':
4569
        native_string = msStringConcatenate(native_string, ",");
4570
        break;
4571
      case '~':
4572
        break;
4573
      default:
4574
        fprintf(stderr, "Translation to native SQL failed.\n");
4575
        msFree(native_string);
4576
        if (layer->debug) {
4577
          msDebug("Token not caught, exiting: Token is %i\n", node->token);
4578
        }
4579
4580
        if (geom_column_name)
4581
          free(geom_column_name);
4582
        if (srid)
4583
          free(srid);
4584
        if (unique)
4585
          free(unique);
4586
        if (indexfield)
4587
          free(indexfield);
4588
        if (table_name)
4589
          free(table_name);
4590
4591
        return MS_SUCCESS; /* not an error */
4592
      }
4593
      nodeCount++;
4594
      node = node->next;
4595
4596
      // fprintf(stderr, "native filter: %s\n", native_string);
4597
    }
4598
4599
    filter->native_string = msStrdup(native_string);
4600
    if (layer->debug >= 4)
4601
      msDebug("total filter tokens are %i\n,", nodeCount);
4602
    msFree(native_string);
4603
  }
4604
4605
  if (geom_column_name)
4606
    free(geom_column_name);
4607
  if (srid)
4608
    free(srid);
4609
  if (unique)
4610
    free(unique);
4611
  if (indexfield)
4612
    free(indexfield);
4613
  if (table_name)
4614
    free(table_name);
4615
4616
  return MS_SUCCESS;
4617
}
4618
4619
#else
4620
/* OracleSpatial "not-supported" procedures */
4621
4622
0
int msOracleSpatialLayerOpen(layerObj *layer) {
4623
0
  (void)layer;
4624
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4625
0
             "msOracleSpatialLayerOpen()");
4626
0
  return MS_FAILURE;
4627
0
}
4628
4629
0
int msOracleSpatialLayerIsOpen(layerObj *layer) {
4630
0
  (void)layer;
4631
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4632
0
             "msOracleSpatialLayerIsOpen()");
4633
0
  return MS_FALSE;
4634
0
}
4635
4636
0
int msOracleSpatialLayerClose(layerObj *layer) {
4637
0
  (void)layer;
4638
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4639
0
             "msOracleSpatialLayerClose()");
4640
0
  return MS_FAILURE;
4641
0
}
4642
4643
int msOracleSpatialLayerWhichShapes(layerObj *layer, rectObj rect,
4644
0
                                    int isQuery) {
4645
0
  (void)layer;
4646
0
  (void)rect;
4647
0
  (void)isQuery;
4648
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4649
0
             "msOracleSpatialLayerWhichShapes()");
4650
0
  return MS_FAILURE;
4651
0
}
4652
4653
0
int msOracleSpatialLayerNextShape(layerObj *layer, shapeObj *shape) {
4654
0
  (void)layer;
4655
0
  (void)shape;
4656
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4657
0
             "msOracleSpatialLayerNextShape()");
4658
0
  return MS_FAILURE;
4659
0
}
4660
4661
0
int msOracleSpatialLayerGetItems(layerObj *layer) {
4662
0
  (void)layer;
4663
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4664
0
             "msOracleSpatialLayerGetItems()");
4665
0
  return MS_FAILURE;
4666
0
}
4667
4668
int msOracleSpatialLayerGetShape(layerObj *layer, shapeObj *shape,
4669
0
                                 resultObj *record) {
4670
0
  (void)layer;
4671
0
  (void)shape;
4672
0
  (void)record;
4673
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4674
0
             "msOracleSpatialLayerGetShape()");
4675
0
  return MS_FAILURE;
4676
0
}
4677
4678
0
int msOracleSpatialLayerGetExtent(layerObj *layer, rectObj *extent) {
4679
0
  (void)layer;
4680
0
  (void)extent;
4681
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4682
0
             "msOracleSpatialLayerGetExtent()");
4683
0
  return MS_FAILURE;
4684
0
}
4685
4686
0
int msOracleSpatialLayerInitItemInfo(layerObj *layer) {
4687
0
  (void)layer;
4688
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4689
0
             "msOracleSpatialLayerInitItemInfo()");
4690
0
  return MS_FAILURE;
4691
0
}
4692
4693
0
void msOracleSpatialLayerFreeItemInfo(layerObj *layer) {
4694
0
  (void)layer;
4695
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4696
0
             "msOracleSpatialLayerFreeItemInfo()");
4697
0
}
4698
4699
int msOracleSpatialLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c,
4700
0
                                     shapeObj *shape) {
4701
0
  (void)map;
4702
0
  (void)layer;
4703
0
  (void)c;
4704
0
  (void)shape;
4705
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4706
0
             "msLayerGetAutoStyle()");
4707
0
  return MS_FAILURE;
4708
0
}
4709
4710
0
void msOracleSpatialEnablePaging(layerObj *layer, int value) {
4711
0
  (void)layer;
4712
0
  (void)value;
4713
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4714
0
             "msLayerEnablePaging()");
4715
0
  return;
4716
0
}
4717
4718
0
int msOracleSpatialGetPaging(layerObj *layer) {
4719
0
  (void)layer;
4720
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4721
0
             "msLayerGetPaging()");
4722
0
  return MS_FAILURE;
4723
0
}
4724
4725
int msOracleSpatialLayerTranslateFilter(layerObj *layer, expressionObj *filter,
4726
0
                                        char *filteritem) {
4727
0
  (void)layer;
4728
0
  (void)filter;
4729
0
  (void)filteritem;
4730
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4731
0
             "msLayerTranslateFilter()");
4732
0
  return MS_FAILURE;
4733
0
}
4734
4735
char *msOracleSpatialEscapePropertyName(layerObj *layer,
4736
0
                                        const char *pszString) {
4737
0
  (void)layer;
4738
0
  msSetError(MS_ORACLESPATIALERR, "OracleSpatial is not supported",
4739
0
             "msLayerEscapePropertyName()");
4740
0
  return msStrdup(pszString);
4741
0
}
4742
#endif
4743
4744
#if defined USE_ORACLE_PLUGIN
4745
MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj *vtable,
4746
                                               layerObj *layer) {
4747
  assert(layer != NULL);
4748
  assert(vtable != NULL);
4749
4750
  vtable->LayerTranslateFilter = msOracleSpatialLayerTranslateFilter;
4751
4752
  vtable->LayerInitItemInfo = msOracleSpatialLayerInitItemInfo;
4753
  vtable->LayerFreeItemInfo = msOracleSpatialLayerFreeItemInfo;
4754
  vtable->LayerOpen = msOracleSpatialLayerOpen;
4755
  vtable->LayerIsOpen = msOracleSpatialLayerIsOpen;
4756
  vtable->LayerWhichShapes = msOracleSpatialLayerWhichShapes;
4757
  vtable->LayerNextShape = msOracleSpatialLayerNextShape;
4758
  vtable->LayerGetShape = msOracleSpatialLayerGetShape;
4759
  vtable->LayerClose = msOracleSpatialLayerClose;
4760
  vtable->LayerGetItems = msOracleSpatialLayerGetItems;
4761
  vtable->LayerGetExtent = msOracleSpatialLayerGetExtent;
4762
  /* layer->vtable->LayerGetAutoStyle, use default */
4763
  /* layer->vtable->LayerApplyFilterToLayer, use default */
4764
  vtable->LayerCloseConnection = msOracleSpatialLayerClose;
4765
  vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer;
4766
  vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter;
4767
  // vtable->LayerSetTimeFilter = msOracleSpatialLayerSetTimeFilter;
4768
  // vtable->LayerEscapePropertyName = msOracleSpatialEscapePropertyName;
4769
  /* layer->vtable->LayerGetNumFeatures, use default */
4770
  /* layer->vtable->LayerGetAutoProjection =
4771
   * msOracleSpatialLayerGetAutoProjection; Disabled until tested */
4772
  vtable->LayerEnablePaging = msOracleSpatialEnablePaging;
4773
  vtable->LayerGetPaging = msOracleSpatialGetPaging;
4774
4775
  return MS_SUCCESS;
4776
}
4777
4778
#else /*if ORACLE_PLUGIN is defined, then this file is not used by             \
4779
        libmapserver and therefre there is no need to include this function */
4780
0
int msOracleSpatialLayerInitializeVirtualTable(layerObj *layer) {
4781
0
  assert(layer != NULL);
4782
0
  assert(layer->vtable != NULL);
4783
4784
0
  layer->vtable->LayerTranslateFilter = msOracleSpatialLayerTranslateFilter;
4785
4786
0
  layer->vtable->LayerInitItemInfo = msOracleSpatialLayerInitItemInfo;
4787
0
  layer->vtable->LayerFreeItemInfo = msOracleSpatialLayerFreeItemInfo;
4788
0
  layer->vtable->LayerOpen = msOracleSpatialLayerOpen;
4789
0
  layer->vtable->LayerIsOpen = msOracleSpatialLayerIsOpen;
4790
0
  layer->vtable->LayerWhichShapes = msOracleSpatialLayerWhichShapes;
4791
0
  layer->vtable->LayerNextShape = msOracleSpatialLayerNextShape;
4792
0
  layer->vtable->LayerGetShape = msOracleSpatialLayerGetShape;
4793
  /* layer->vtable->LayerGetShapeCount, use default */
4794
0
  layer->vtable->LayerClose = msOracleSpatialLayerClose;
4795
0
  layer->vtable->LayerGetItems = msOracleSpatialLayerGetItems;
4796
0
  layer->vtable->LayerGetExtent = msOracleSpatialLayerGetExtent;
4797
  /* layer->vtable->LayerGetAutoStyle, use default */
4798
0
  layer->vtable->LayerCloseConnection = msOracleSpatialLayerClose;
4799
0
  layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer;
4800
0
  layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter;
4801
  // layer->vtable->LayerSetTimeFilter = msOracleSpatialLayerSetTimeFilter;
4802
  // layer->vtable->LayerEscapePropertyName = msOracleSpatialEscapePropertyName;
4803
  /* layer->vtable->LayerCreateItems, use default */
4804
  /* layer->vtable->LayerGetNumFeatures, use default */
4805
  /* layer->vtable->LayerGetAutoProjection =
4806
   * msOracleSpatialLayerGetAutoProjection; Disabled until tested */
4807
0
  layer->vtable->LayerEnablePaging = msOracleSpatialEnablePaging;
4808
0
  layer->vtable->LayerGetPaging = msOracleSpatialGetPaging;
4809
4810
0
  return MS_SUCCESS;
4811
0
}
4812
#endif