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