/****************************************************************************** * Project: MapServer * Purpose: Native access to Oracle Spatial (SDO) data. * Author: Fernando Simon (fsimon@univali.br) * Rodrigo Becke Cabral * Adriana Gomes Alves * * Notes: Developed under several funding agreements: * * 1) n.45/00 between CTTMAR/UNIVALI (www.cttmar.univali.br) * and CEPSUL/IBAMA (www.ibama.gov.br) * * 2) CNPq (www.cnpq.br) under process 401263.03-7 * * 3) FUNCITEC (www.funcitec.rct-sc.br) under process FCTP1523-031 * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include MS_CVSID("$Id$") #ifdef USE_ORACLESPATIAL #include #include #define ARRAY_SIZE 1024 #define QUERY_SIZE 1 #define TEXT_SIZE 4000 /* ticket #2260 */ #define TYPE_OWNER "MDSYS" #define SDO_GEOMETRY TYPE_OWNER".SDO_GEOMETRY" #define SDO_ORDINATE_ARRAY TYPE_OWNER".SDO_ORDINATE_ARRAY" #define SDO_GEOMETRY_LEN strlen( SDO_GEOMETRY ) #define FUNCTION_FILTER 1 #define FUNCTION_RELATE 2 #define FUNCTION_GEOMRELATE 3 #define FUNCTION_NONE 4 #define VERSION_8i 1 #define VERSION_9i 2 #define VERSION_10g 3 #define TOLERANCE 0.001 #define NULLERRCODE 1405 #define TABLE_NAME_SIZE 2000 typedef struct { OCINumber x; OCINumber y; OCINumber z; } SDOPointObj; typedef struct { OCINumber gtype; OCINumber srid; SDOPointObj point; OCIArray *elem_info; OCIArray *ordinates; } SDOGeometryObj; typedef struct { OCIInd _atomic; OCIInd x; OCIInd y; OCIInd z; } SDOPointInd; typedef struct { OCIInd _atomic; OCIInd gtype; OCIInd srid; SDOPointInd point; OCIInd elem_info; OCIInd ordinates; } SDOGeometryInd; typedef text item_text[TEXT_SIZE]; typedef item_text item_text_array[ARRAY_SIZE]; typedef item_text item_text_array_query[QUERY_SIZE]; typedef struct { /*Oracle handlers (global to connection)*/ OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; int last_oci_status; text last_oci_error[2048]; /* This references counter is to avoid the cache freed if there are other layers that could use it */ int ref_count; } msOracleSpatialHandler; typedef struct { /* Oracle data handlers (global to connection) */ OCIDescribe *dschp; OCIType *tdo; } msOracleSpatialDataHandler; typedef struct { OCIStmt *stmthp; /* fetch data buffer */ ub4 rows_count; /* total number of rows (so far) within cursor */ ub4 row_num; /* current row index within cursor results */ ub4 rows_fetched; /* total number of rows fetched into our buffer */ ub4 row; /* current row index within our buffer */ item_text_array *items; /* items buffer */ item_text_array_query *items_query; /* items buffer */ SDOGeometryObj *obj[ARRAY_SIZE]; /* spatial object buffer */ SDOGeometryInd *ind[ARRAY_SIZE]; /* object indicator (null) buffer */ int uniqueidindex; /*allows to keep whic attribute id index is used as unique id*/ } msOracleSpatialStatement; typedef struct { /* oracle handlers */ msOracleSpatialHandler *orahandlers; /* oracle data handlers */ msOracleSpatialDataHandler *oradatahandlers; msOracleSpatialStatement *orastmt; /* Following items are setup by WhichShapes * used by NextShape, ResultGetShape * disposed by CloseLayer (if set) */ msOracleSpatialStatement *orastmt2; } msOracleSpatialLayerInfo; static OCIType *ordinates_tdo = NULL; static OCIArray *ordinates; /* local prototypes */ static int TRY( msOracleSpatialHandler *hand, sword status ); static int ERROR( char *routine, msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ); static void msSplitLogin( char *connection, mapObj *map, char **username, char **password, char **dblink ); static int msSplitData( char *data, char **geometry_column_name, char **table_name, char **unique, char **srid, int *function, int * version); static void msOCICloseConnection( void *layerinfo ); static msOracleSpatialHandler *msOCISetHandlers( char *username, char *password, char *dblink ); static int msOCISetDataHandlers( msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ); static void msOCICloseDataHandlers ( msOracleSpatialDataHandler *dthand ); static void msOCICloseHandlers( msOracleSpatialHandler *hand ); static void msOCIClearLayerInfo( msOracleSpatialLayerInfo *layerinfo ); static int msOCIOpenStatement( msOracleSpatialHandler *hand, msOracleSpatialStatement *sthand ); static void msOCIFinishStatement( msOracleSpatialStatement *sthand ); static int msOCIGet2DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ); static int msOCIGet3DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ); static int msOCIGet4DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ); static int msOCIConvertCircle( pointObj *pt ); static void osFilteritem(layerObj *layer, int function, char *query_str, size_t size, int mode); static void osAggrGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name); static void osConvexHullGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name); static void osGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *srid, rectObj rect); static void osNoGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *srid, rectObj rect); static double osCalculateArcRadius(pointObj *pnt); static void osCalculateArc(pointObj *pnt, int data3d, int data4d, double area, double radius, double npoints, int side, lineObj arcline, shapeObj *shape); static void osGenerateArc(shapeObj *shape, lineObj arcline, lineObj points, int i, int n, int data3d, int data4d); static void osShapeBounds ( shapeObj *shp ); static void osCloneShape(shapeObj *shape, shapeObj *newshape, int data3d, int data4d); static void osPointCluster(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int interpretation, int data3d, int data4d); static void osPoint(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d); static void osClosedPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int elem_type, int data3d, int data4d); static void osRectangle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d); static void osCircle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d); static void osArcPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj arcpoints,int elem_type,int data3d, int data4d); static int osGetOrdinates(msOracleSpatialDataHandler *dthand, msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, SDOGeometryInd *ind); static int osCheck2DGtype(int pIntGtype); static int osCheck3DGtype(int pIntGtype); static int osCheck4DGtype(int pIntGtype); /****************************************************************************** * Local Helper Functions * ******************************************************************************/ /* if an error ocurred call msSetError, sets last_oci_status to MS_FAILURE and return 0; * otherwise returns 1 */ static int TRY( msOracleSpatialHandler *hand, sword status ) { sb4 errcode = 0; if (hand->last_oci_status == MS_FAILURE) return 0; /* error from previous call */ switch (status) { case OCI_SUCCESS_WITH_INFO: case OCI_ERROR: OCIErrorGet((dvoid *)hand->errhp, (ub4)1, (text *)NULL, &errcode, hand->last_oci_error, (ub4)sizeof(hand->last_oci_error), OCI_HTYPE_ERROR ); if (errcode == NULLERRCODE) { hand->last_oci_error[0] = (text)'\0'; return 1; } hand->last_oci_error[sizeof(hand->last_oci_error)-1] = 0; /* terminate string!? */ break; case OCI_NEED_DATA: strlcpy( (char *)hand->last_oci_error, "OCI_NEED_DATA", sizeof(hand->last_oci_error)); break; case OCI_INVALID_HANDLE: strlcpy( (char *)hand->last_oci_error, "OCI_INVALID_HANDLE", sizeof(hand->last_oci_error)); break; case OCI_STILL_EXECUTING: ((char*)hand->last_oci_error)[sizeof(hand->last_oci_error)-1] = 0; break; case OCI_CONTINUE: strlcpy( (char *)hand->last_oci_error, "OCI_CONTINUE", sizeof(hand->last_oci_error)); break; default: return 1; /* no error */ } /* if I got here, there was an error */ hand->last_oci_status = MS_FAILURE; return 0; /* error! */ } OCIType *get_tdo(char *typename, msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ) { OCIParam *paramp = NULL; OCIRef *type_ref = NULL; OCIType *tdoe = NULL; int success = 0; 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)) &&TRY( hand, OCIAttrGet((dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE, (dvoid *)¶mp, (ub4 *)0, (ub4)OCI_ATTR_PARAM, hand->errhp)) &&TRY( hand, OCIAttrGet((dvoid *)paramp, (ub4)OCI_DTYPE_PARAM, (dvoid *)&type_ref, (ub4 *)0, (ub4)OCI_ATTR_REF_TDO, hand->errhp)) &&TRY( hand, OCIObjectPin(hand->envhp, hand->errhp, type_ref, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&tdoe)); if (success) return tdoe; /* if failure, return NULL*/ return NULL; } /* check last_oci_status for MS_FAILURE (set by TRY()) if an error ocurred return 1; * otherwise, returns 0 */ static int ERROR( char *routine, msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ) { if (hand->last_oci_status == MS_FAILURE) { /* there was an error */ msSetError( MS_ORACLESPATIALERR, (char *)hand->last_oci_error, routine ); return 1; /* error processed */ } else return 0; /* no error */ } /* break layer->connection (username/password@dblink) into username, password and dblink */ static void msSplitLogin( char *connection, mapObj *map, char **username, char **password, char **dblink ) { char *src, *tgt, *conn_decrypted; size_t buffer_size = 0; /* bad 'connection' */ if (connection == NULL) return; buffer_size = strlen(connection)+1; *username = (char*)malloc(buffer_size); *password = (char*)malloc(buffer_size); *dblink = (char*)malloc(buffer_size); /* clearup */ **username = **password = **dblink = 0; /* Decrypt any encrypted token */ conn_decrypted = msDecryptStringTokens(map, connection); if (conn_decrypted == NULL) return; /* ok, split connection */ for( tgt=*username, src=conn_decrypted; *src; src++, tgt++ ) if (*src=='/' || *src=='@') break; else *tgt = *src; *tgt = 0; if (*src == '/') { for( tgt=*password, ++src; *src; src++, tgt++ ) if (*src == '@') break; else *tgt = *src; *tgt = 0; } if (*src == '@') { strlcpy( *dblink, ++src, buffer_size); } msFree(conn_decrypted); } /* break layer->data into geometry_column_name, table_name and srid */ static int msSplitData( char *data, char **geometry_column_name, char **table_name, char **unique, char **srid, int *function, int *version ) { char *tok_from = "from"; char *tok_using = "using"; char *tok_unique = "unique"; char *tok_srid = "srid"; char *tok_version = "version"; char data_version[4] = ""; char tok_function[11] = ""; int parenthesis, i; char *src = data, *tgt; int table_name_size = TABLE_NAME_SIZE; size_t buffer_size = 0; /* bad 'data' */ if (data == NULL) return 0; buffer_size = strlen(data)+1; *geometry_column_name = (char*)malloc(buffer_size); *unique = (char*)malloc(buffer_size); *srid = (char*)malloc(buffer_size); /* clearup */ **geometry_column_name = **table_name = 0; /* parsing 'geometry_column_name' */ for( ;*src && isspace( *src ); src++ ); /* skip blanks */ for( tgt=*geometry_column_name; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; /* parsing 'from' */ for( ;*src && isspace( *src ); src++ ) ; /* skip blanks */ for( ;*src && *tok_from && tolower(*src)==*tok_from; src++, tok_from++ ); if (*tok_from != '\0') return 0; /* parsing 'table_name' or '(SELECT stmt)' */ i = 0; for( ;*src && isspace( *src ); src++ ); /* skip blanks */ for( tgt=*table_name, parenthesis=0; *src; src++, tgt++, ++i ) { if (*src == '(') parenthesis++; else if (*src == ')') parenthesis--; else if (parenthesis==0 && isspace( *src )) break; /* stop on spaces */ /* double the size of the table_name array if necessary */ if (i == table_name_size) { table_name_size *= 2; *table_name = (char *) realloc(*table_name,sizeof(char *) * table_name_size); } *tgt = *src; } *tgt = 0; strlcpy( *unique, "", buffer_size); strlcpy( *srid, "NULL", buffer_size); *function = -1; *version = -1; /* parsing 'unique' */ for( ;*src && isspace( *src ); src++ ) ; /* skip blanks */ if (*src != '\0') { /* parse 'using' */ for( ;*src && *tok_using && tolower(*src)==*tok_using; src++, tok_using++ ); if (*tok_using != '\0') return 0; /* parsing 'unique' */ for( ;*src && isspace( *src ); src++ ); /* skip blanks */ for( ;*src && *tok_unique && tolower(*src)==*tok_unique; src++, tok_unique++ ); if (*tok_unique == '\0') { for( ;*src && isspace( *src ); src++ ); /* skip blanks */ if (*src == '\0') return 0; for( tgt=*unique; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; if (*tok_unique != '\0') return 0; } /* parsing 'srid' */ for( ;*src && isspace( *src ); src++ ); /* skip blanks */ for( ;*src && *tok_srid && tolower(*src)==*tok_srid; src++, tok_srid++ ); if (*tok_srid == '\0') { for( ;*src && isspace( *src ); src++ ); /* skip blanks */ if (*src == '\0') return 0; for( tgt=*srid; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; if (*tok_srid != '\0') return 0; } /*parsing function/version */ for( ;*src && isspace( *src ); src++ ); if (*src != '\0') { for( tgt=tok_function; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; } /*Upcase conversion for the FUNCTION/VERSION token*/ for (i=0; tok_function[i] != '\0'; i++) tok_function[i] = toupper(tok_function[i]); if (strcmp(tok_function, "VERSION")) { if (!strcmp(tok_function, "FILTER") || !strcmp(tok_function, "")) *function = FUNCTION_FILTER; else if(!strcmp(tok_function, "RELATE")) *function = FUNCTION_RELATE; else if (!strcmp(tok_function,"GEOMRELATE")) *function = FUNCTION_GEOMRELATE; else if (!strcmp(tok_function,"NONE")) *function = FUNCTION_NONE; else { *function = -1; return 0; } /*parsing VERSION token when user defined one function*/ for( ;*src && isspace( *src ); src++ ); for( ;*src && *tok_version && tolower(*src)==*tok_version; src++, tok_version++ ); } else { for(tgt = "VERSION";*tgt && *tok_version && toupper(*tgt)==toupper(*tok_version); tgt++, tok_version++ ); *function = FUNCTION_FILTER; } /*parsing version*/ if (*tok_version == '\0') { for( ;*src && isspace( *src ); src++ ); /* skip blanks */ for( tgt=data_version; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; for (i=0; data_version[i] != '\0'; i++) data_version[i] = tolower(data_version[i]); if (!strcmp(data_version, "8i")) *version = VERSION_8i; else if(!strcmp(data_version, "9i")) *version = VERSION_9i; else if (!strcmp(data_version, "10g")) *version = VERSION_10g; else return 0; } } /* finish parsing */ for( ;*src && isspace( *src ); src++ ); /* skip blanks */ return (*src == '\0'); } /****************************************************************************** * OCI Helper Functions * ******************************************************************************/ /* create statement handle from database connection */ static int msOCIOpenStatement( msOracleSpatialHandler *hand, msOracleSpatialStatement *sthand) { int success = 0; /* allocate stmthp */ success = TRY( hand, OCIHandleAlloc( (dvoid *)hand->envhp, (dvoid **)&sthand->stmthp, (ub4)OCI_HTYPE_STMT, (size_t)0, (dvoid **)0 ) ); sthand->rows_count = 0; sthand->row_num = 0; sthand->rows_fetched = 0; sthand->row = 0; sthand->items = NULL; sthand->items_query = NULL; /* fprintf(stderr, "Creating statement handle at %p\n", sthand->stmthp); */ return success; } /* create statement handle from database connection */ static void msOCIFinishStatement( msOracleSpatialStatement *sthand ) { if(sthand != NULL) { /* fprintf(stderr, "Freeing statement handle at %p\n", sthand->stmthp); */ if (sthand->stmthp != NULL) OCIHandleFree( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT ); if (sthand->items != NULL) free( sthand->items ); if (sthand->items_query != NULL) free( sthand->items_query ); memset(sthand, 0, sizeof( msOracleSpatialStatement ) ); free(sthand); } } static int msOCISetDataHandlers(msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand) { int success = 0; OCIParam *paramp = NULL; OCIRef *type_ref = NULL; success = TRY( hand, /* allocate dschp */ OCIHandleAlloc( hand->envhp, (dvoid **)&dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE, (size_t)0, (dvoid **)0 ) ) && TRY( hand, /* describe SDO_GEOMETRY in svchp (dschp) */ OCIDescribeAny( hand->svchp, hand->errhp, (text *)SDO_GEOMETRY, (ub4)SDO_GEOMETRY_LEN, OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TYPE, dthand->dschp ) ) && TRY( hand, /* get param for SDO_GEOMETRY */ OCIAttrGet( (dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE, (dvoid *)¶mp, (ub4 *)0, (ub4)OCI_ATTR_PARAM, hand->errhp ) ) && TRY( hand, /* get type_ref for SDO_GEOMETRY */ OCIAttrGet( (dvoid *)paramp, (ub4)OCI_DTYPE_PARAM, (dvoid *)&type_ref, (ub4 *)0, (ub4)OCI_ATTR_REF_TDO, hand->errhp ) ) && TRY( hand, /* get TDO for SDO_GEOMETRY */ OCIObjectPin( hand->envhp, hand->errhp, type_ref, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&dthand->tdo ) ); return success; } /* connect to database */ static msOracleSpatialHandler *msOCISetHandlers( char *username, char *password, char *dblink ) { int success; msOracleSpatialHandler *hand = NULL; hand = (msOracleSpatialHandler *) malloc( sizeof(msOracleSpatialHandler)); if (hand == NULL) { msSetError(MS_MEMERR, NULL, "msOCISetHandlers()"); return NULL; } memset( hand, 0, sizeof(msOracleSpatialHandler) ); hand->ref_count = 1; hand->last_oci_status = MS_SUCCESS; hand->last_oci_error[0] = (text)'\0'; success = TRY( hand, /* allocate envhp */ OCIEnvCreate( &hand->envhp, OCI_OBJECT, (dvoid *)0, 0, 0, 0, (size_t) 0, (dvoid **)0 ) ) && TRY( hand, /* allocate errhp */ OCIHandleAlloc( (dvoid *)hand->envhp, (dvoid **)&hand->errhp, (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0 ) ) && TRY( hand, /* logon */ OCILogon( hand->envhp, hand->errhp, &hand->svchp, (text *)username, strlen(username), (text *)password, strlen(password), (text *)dblink, strlen(dblink) ) ); if ( !success ) { msSetError( MS_ORACLESPATIALERR, "Cannot create OCI Handlers. " "Connection failure. Check the connection string. " "Error: %s.", "msOracleSpatialLayerOpen()", hand->last_oci_error); msOCICloseHandlers(hand); return NULL; } return hand; } /* disconnect from database */ static void msOCICloseHandlers( msOracleSpatialHandler *hand ) { if (hand->svchp != NULL) OCILogoff( hand->svchp, hand->errhp ); if (hand->errhp != NULL) OCIHandleFree( (dvoid *)hand->errhp, (ub4)OCI_HTYPE_ERROR ); if (hand->envhp != NULL) OCIHandleFree( (dvoid *)hand->envhp, (ub4)OCI_HTYPE_ENV ); if (hand != NULL) memset( hand, 0, sizeof (msOracleSpatialHandler)); free(hand); } static void msOCICloseDataHandlers( msOracleSpatialDataHandler *dthand ) { if (dthand->dschp != NULL) OCIHandleFree( (dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE ); if (dthand != NULL) memset( dthand, 0, sizeof (msOracleSpatialDataHandler)); free(dthand); } static void msOCIClearLayerInfo( msOracleSpatialLayerInfo *layerinfo ) { if (layerinfo != NULL) { memset( layerinfo, 0, sizeof( msOracleSpatialLayerInfo ) ); free(layerinfo); } } /*function that creates the correct sql for geoditical srid for version 9i*/ static void osGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *srid, rectObj rect) { switch (function) { case FUNCTION_FILTER: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates ), :srid)," "'querytype=window') = 'TRUE'", geom_column_name); break; } case FUNCTION_RELATE: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_RELATE( %s, SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates ), :srid)," "'mask=anyinteract querytype=window') = 'TRUE'", geom_column_name); break; } case FUNCTION_GEOMRELATE: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_GEOM.RELATE( %s, 'anyinteract', SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates), :srid)," "%f) = 'TRUE' AND %s IS NOT NULL", geom_column_name, TOLERANCE, geom_column_name ); break; } case FUNCTION_NONE: { break; } default: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates), :srid)," "'querytype=window') = 'TRUE'", geom_column_name ); } } } /*function that generate the correct sql for no geoditic srid's*/ static void osNoGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *srid, rectObj rect) { switch (function) { case FUNCTION_FILTER: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," /* "MDSYS.SDO_ORDINATE_ARRAY(%.9g,%.9g,%.9g,%.9g)" */ ":ordinates" " ),'querytype=window') = 'TRUE'", geom_column_name); break; } case FUNCTION_RELATE: { if (version == VERSION_10g) { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_ANYINTERACT( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)) = 'TRUE'", geom_column_name); } else { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_RELATE( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)," "'mask=anyinteract querytype=window') = 'TRUE'", geom_column_name); } break; } case FUNCTION_GEOMRELATE: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_GEOM.RELATE( %s, 'anyinteract', MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)," "%f) = 'TRUE' AND %s IS NOT NULL", geom_column_name, TOLERANCE, geom_column_name ); break; } case FUNCTION_NONE: { break; } default: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)," "'querytype=window') = 'TRUE'", geom_column_name); } } } /* get ordinates from SDO buffer */ static int msOCIGet2DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ) { double x, y; int i, n, success = 1; boolean exists; OCINumber *oci_number; for( i=s, n=0; i < e && success; i+=2, n++ ) { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&y ) ); if (success) { pt[n].x = x; pt[n].y = y; } } return success ? n : 0; } static int msOCIGet3DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ) { double x, y; int i, n, success = 1; boolean exists; #ifdef USE_POINT_Z_M double z; boolean numnull; #endif /* USE_POINT_Z_M */ OCINumber *oci_number; for( i=s, n=0; i < e && success; i+=3, n++ ) { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&y ) ) #ifdef USE_POINT_Z_M && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+2, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) #endif /* USE_POINT_Z_M */ ; #ifdef USE_POINT_Z_M if (success) { success = TRY(hand, OCINumberIsZero( hand->errhp, oci_number, (boolean *)&numnull)); if (success) { success = TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&z ) ); } else { hand->last_oci_status = MS_SUCCESS; strlcpy( (char *)hand->last_oci_error, "Retrieve z value, but NULL value for z. Setting z to 0.", sizeof(hand->last_oci_error)); z = 0; success = 1; } } #endif /* USE_POINT_Z_M */ if (success) { pt[n].x = x; pt[n].y = y; #ifdef USE_POINT_Z_M pt[n].z = z; #endif /* USE_POINT_Z_M */ } } return success ? n : 0; } static int msOCIGet4DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ) { double x, y; int i, n, success = 1; boolean exists; #ifdef USE_POINT_Z_M double z; boolean numnull; #endif /* USE_POINT_Z_M */ OCINumber *oci_number; for( i=s, n=0; i < e && success; i+=4, n++ ) { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&y ) ) #ifdef USE_POINT_Z_M && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+2, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) #endif /* USE_POINT_Z_M */ ; #ifdef USE_POINT_Z_M if (success) { success = TRY(hand, OCINumberIsZero( hand->errhp, oci_number, (boolean *)&numnull)); if (success) { success = TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&z ) ); } else { hand->last_oci_status = MS_SUCCESS; strlcpy( (char *)hand->last_oci_error, "Retrieve z value, but NULL value for z. Setting z to 0.", sizeof(hand->last_oci_error)); z = 0; success = 1; } } #endif /* USE_POINT_Z_M */ if (success) { pt[n].x = x; pt[n].y = y; #ifdef USE_POINT_Z_M pt[n].z = z; #endif /* USE_POINT_Z_M */ } } return success ? n : 0; } /* convert three-point circle to two-point rectangular bounds */ static int msOCIConvertCircle( pointObj *pt ) { pointObj ptaux; double dXa, dXb; double ma, mb; double cx, cy, r; int success; dXa = pt[1].x - pt[0].x; success = (fabs( dXa ) > 1e-8); if (!success) { /* switch points 1 & 2 */ ptaux = pt[1]; pt[1] = pt[2]; pt[2] = ptaux; dXa = pt[1].x - pt[0].x; success = (fabs( dXa ) > 1e-8); } if (success) { dXb = pt[2].x - pt[1].x; success = (fabs( dXb ) > 1e-8); if (!success) { /* insert point 2 before point 0 */ ptaux = pt[2]; pt[2] = pt[1]; pt[1] = pt[0]; pt[0] = ptaux; dXb = dXa; /* segment A has become B */ dXa = pt[1].x - pt[0].x; /* recalculate new segment A */ success = (fabs( dXa ) > 1e-8); } } if (success) { ma = (pt[1].y - pt[0].y)/dXa; mb = (pt[2].y - pt[1].y)/dXb; success = (fabs( mb - ma ) > 1e-8); } if (!success) return 0; /* calculate center and radius */ 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)); cy = (fabs( ma ) > 1e-8) ? ((pt[0].y + pt[1].y)/2 - (cx - (pt[0].x + pt[1].x)/2)/ma) : ((pt[1].y + pt[2].y)/2 - (cx - (pt[1].x + pt[2].x)/2)/mb); r = sqrt( pow( pt[0].x - cx, 2 ) + pow( pt[0].y - cy, 2 ) ); /* update pt buffer with rectangular bounds */ pt[0].x = cx - r; pt[0].y = cy - r; pt[1].x = cx + r; pt[1].y = cy + r; return 1; } /*function that creates the correct sql for filter and filteritem*/ static void osFilteritem(layerObj *layer, int function, char *query_str, size_t size, int mode) { if (layer->filter.string != NULL) { if (mode == 1) strlcat( query_str, " WHERE ", size); else strlcat( query_str, " AND ", size); if (layer->filteritem != NULL) { snprintf (query_str + strlen(query_str), size-strlen(query_str), " %s = ", layer->filteritem); /* snprintf (query_str + strlen(query_str), " %s = ", layer->filteritem); */ } snprintf (query_str + strlen(query_str), size-strlen(query_str), " %s ", layer->filter.string); /* snprintf(buffer, n, "gfdg %s %s %s", layer->filter.string, (layer->filteritem != NULL ? layer->filteritem : ""), ); */ if (function != FUNCTION_NONE) snprintf (query_str + strlen(query_str), size-strlen(query_str), " AND "); } else { if (function != FUNCTION_NONE) strlcat( query_str, " WHERE ", size); } } static void osAggrGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name) { char query_str2[6000]; int i = 0; snprintf( query_str2, sizeof(query_str2), "(SELECT"); for( i = 0; i < layer->numitems; ++i ) snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s,", layer->items[i] ); snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s FROM %s", geom_column_name, table_name); osFilteritem(layer, FUNCTION_NONE, query_str2, sizeof(query_str2), 1); snprintf( query_str, size, "SELECT SDO_AGGR_MBR(%s) AS GEOM from %s)", geom_column_name, query_str2); if (layer->debug) msDebug("osAggrGetExtent was called: %s.\n", query_str); } static void osConvexHullGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name) { char query_str2[6000]; int i = 0; snprintf( query_str2, sizeof(query_str2), "(SELECT"); for( i = 0; i < layer->numitems; ++i ) snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s,", layer->items[i] ); snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s FROM %s", geom_column_name, table_name); osFilteritem(layer, FUNCTION_NONE, query_str2, sizeof(query_str2), 1); snprintf( query_str, size, "SELECT SDO_GEOM.SDO_CONVEXHULL(%s, %f) AS GEOM from %s)", geom_column_name, TOLERANCE, query_str2); } static double osCalculateArcRadius(pointObj *pnt) { double rc; double r1, r2, r3; r1 = sqrt( pow(pnt[0].x-pnt[1].x,2) + pow(pnt[0].y-pnt[1].y,2) ); r2 = sqrt( pow(pnt[1].x-pnt[2].x,2) + pow(pnt[1].y-pnt[2].y,2) ); r3 = sqrt( pow(pnt[2].x-pnt[0].x,2) + pow(pnt[2].y-pnt[0].y,2) ); rc = ( r1+r2+r3 )/2; return ( ( r1*r2*r3 )/( 4*sqrt( rc * (rc-r1) * (rc-r2) * (rc-r3) ) ) ); } static void osCalculateArc(pointObj *pnt, int data3d, int data4d, double area, double radius, double npoints, int side, lineObj arcline, shapeObj *shape) { double length, ctrl, angle; double divbas, plusbas, cosbas, sinbas = 0; #ifdef USE_POINT_Z_M double zrange = 0; #endif /* USE_POINT_Z_M */ int i = 0; if ( npoints > 0 ) { 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))); ctrl = length/(2*radius); #ifdef USE_POINT_Z_M if (data3d||data4d) { zrange = labs(pnt[0].z-pnt[1].z)/npoints; if ((pnt[0].z > pnt[1].z) && side == 1) zrange *= -1; else if ((pnt[0].z < pnt[1].z) && side == 1) zrange = zrange; else if ((pnt[0].z > pnt[1].z) && side != 1) zrange *= -1; else if ((pnt[0].z < pnt[1].z) && side != 1) zrange = zrange; } #endif /* USE_POINT_Z_M */ if( ctrl <= 1 ) { divbas = 2 * asin(ctrl); plusbas = divbas/(npoints); cosbas = (pnt[0].x-pnt[3].x)/radius; sinbas = (pnt[0].y-pnt[3].y)/radius; angle = plusbas; arcline.point = (pointObj *)malloc(sizeof(pointObj)*(npoints+1)); arcline.point[0].x = pnt[0].x; arcline.point[0].y = pnt[0].y; #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[0].z = pnt[0].z; #endif /* USE_POINT_Z_M */ for (i = 1; i <= npoints; i++) { if( side == 1) { arcline.point[i].x = pnt[3].x + radius * ((cosbas*cos(angle))-(sinbas*sin(angle))); arcline.point[i].y = pnt[3].y + radius * ((sinbas*cos(angle))+(cosbas*sin(angle))); #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[i].z = pnt[0].z + (zrange*i); #endif /* USE_POINT_Z_M */ } else { if ( side == -1) { arcline.point[i].x = pnt[3].x + radius * ((cosbas*cos(angle))+(sinbas*sin(angle))); arcline.point[i].y = pnt[3].y + radius * ((sinbas*cos(angle))-(cosbas*sin(angle))); #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[i].z = pnt[0].z + (zrange*i); #endif /* USE_POINT_Z_M */ } else { arcline.point[i].x = pnt[0].x; arcline.point[i].y = pnt[0].y; #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[i].z = pnt[0].z; #endif /* USE_POINT_Z_M */ } } angle += plusbas; } arcline.numpoints = npoints+1; msAddLine( shape, &arcline ); free (arcline.point); } } else { arcline.point = (pointObj *)malloc(sizeof(pointObj)*(2)); arcline.point[0].x = pnt[0].x; arcline.point[0].y = pnt[0].y; arcline.point[1].x = pnt[1].x; arcline.point[1].y = pnt[1].y; #ifdef USE_POINT_Z_M if(data3d||data4d) { arcline.point[0].z = pnt[0].z; arcline.point[1].z = pnt[1].z; } #endif /* USE_POINT_Z_M */ arcline.numpoints = 2; msAddLine( shape, &arcline ); free (arcline.point); } } /* Part of this function was based on Terralib function TeGenerateArc * found in TeGeometryAlgorith.cpp (www.terralib.org). * Part of this function was based on Dr. Ialo (Univali/Cttmar) functions. */ static void osGenerateArc(shapeObj *shape, lineObj arcline, lineObj points, int i, int n, int data3d, int data4d) { double mult, plus1, plus2, plus3, bpoint; double cx, cy; double radius, side, area, npoints; double dist1 = 0; double dist2 = 0; pointObj point5[4]; mult = ( points.point[i+1].x - points.point[i].x ) * ( points.point[i+2].y - points.point[i].y ) - ( points.point[i+1].y - points.point[i].y ) * ( points.point[i+2].x - points.point[i].x ); if (mult) { /*point5 = (pointObj *)malloc(sizeof(pointObj)*(4));*/ plus1 = points.point[i].x * points.point[i].x + points.point[i].y * points.point[i].y; plus2 = points.point[i+1].x * points.point[i+1].x + points.point[i+1].y * points.point[i+1].y; plus3 = points.point[i+2].x * points.point[i+2].x + points.point[i+2].y * points.point[i+2].y; bpoint = plus1 * ( points.point[i+1].y - points.point[i+2].y ) + plus2 * ( points.point[i+2].y - points.point[i].y ) + plus3 * ( points.point[i].y - points.point[i+1].y ); cx = bpoint / (2.0 * mult); bpoint = plus1 * ( points.point[i+2].x - points.point[i+1].x ) + plus2 * ( points.point[i].x - points.point[i+2].x ) + plus3 * ( points.point[i+1].x - points.point[i].x ); cy = bpoint / (2.0 * mult); dist1 = (points.point[i+1].x - points.point[i].x) * (cy - points.point[i].y); dist2 = (points.point[i+1].y - points.point[i].y) * (cx - points.point[i].x); side = 0; if((dist1-dist2) > 0) side = 1; else { if((dist1-dist2) < 0) side = -1; } point5[0] = points.point[i]; point5[1] = points.point[i+1]; point5[2] = points.point[i+2]; point5[3].x = cx; point5[3].y = cy; radius = osCalculateArcRadius(point5); area = ((points.point[i].x + points.point[i+1].x) * (points.point[i+1].y - points.point[i].y)) + ((points.point[i+1].x + points.point[i+2].x) * (points.point[i+2].y - points.point[i+1].y)); npoints = labs(area/radius); point5[0] = points.point[i]; point5[1] = points.point[i+1]; osCalculateArc(point5, data3d, data4d, area, radius, (npoints>1000)?1000:npoints, side, arcline, shape); point5[0] = points.point[i+1]; point5[1] = points.point[i+2]; osCalculateArc(point5, data3d, data4d, area, radius, (npoints>1000)?1000:npoints, side, arcline, shape); } else { arcline.point = (pointObj *)malloc(sizeof(pointObj)*(2)); arcline.point[0].x = points.point[i].x; arcline.point[0].y = points.point[i].y; arcline.point[1].x = points.point[i+2].x; arcline.point[1].y = points.point[i+2].y; #ifdef USE_POINT_Z_M if (data3d||data4d) { arcline.point[0].z = points.point[i].z; arcline.point[1].z = points.point[i+2].z; } #endif /* USE_POINT_Z_M */ arcline.numpoints = 2; msAddLine( shape, &arcline ); free (arcline.point); } } static void osShapeBounds ( shapeObj *shp ) { int i, f; if ( (shp->numlines > 0) && (shp->line[0].numpoints > 0) ) { shp->bounds.minx = shp->line[0].point[0].x; shp->bounds.maxx = shp->line[0].point[0].x; shp->bounds.miny = shp->line[0].point[0].y; shp->bounds.maxy = shp->line[0].point[0].y; } for ( i = 0 ; i < shp->numlines; i++) { for( f = 0; f < shp->line[i].numpoints; f++) { if (shp->line[i].point[f].x < shp->bounds.minx) shp->bounds.minx = shp->line[i].point[f].x; if (shp->line[i].point[f].x > shp->bounds.maxx) shp->bounds.maxx = shp->line[i].point[f].x; if (shp->line[i].point[f].y < shp->bounds.miny) shp->bounds.miny = shp->line[i].point[f].y; if (shp->line[i].point[f].y > shp->bounds.maxy) shp->bounds.maxy = shp->line[i].point[f].y; } } } static void osCloneShape(shapeObj *shape, shapeObj *newshape, int data3d, int data4d) { int max_points = 0; int i,f,g; lineObj shapeline = {0, NULL}; for (i = 0; i < shape->numlines; i++) max_points += shape->line[i].numpoints; if (max_points > 0) shapeline.point = (pointObj *)malloc( sizeof(pointObj)*max_points ); g = 0; for ( i = 0 ; i < shape->numlines; i++) { for( f = 0; f < shape->line[i].numpoints && g <= max_points; f++, g++) { shapeline.point[g].x = shape->line[i].point[f].x; shapeline.point[g].y = shape->line[i].point[f].y; #ifdef USE_POINT_Z_M if (data3d||data4d) shapeline.point[g].z = shape->line[i].point[f].z; #endif /* USE_POINT_Z_M */ } } if (g) { shapeline.numpoints = g; newshape->type = shape->type; /* jimk: 2009/09/23 Fixes compound linestrings being converted to polygons */ msAddLine( newshape, &shapeline ); } } static void osPointCluster(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int interpretation, int data3d, int data4d) { int n; n = (end - start)/2; /* n = interpretation; */ /* if (n == interpretation) { */ points.point = (pointObj *)malloc( sizeof(pointObj)*n ); if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, points.point ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, points.point ); else n = msOCIGet2DOrdinates( hand, obj, start, end, points.point ); if (n == interpretation && n>0) { shape->type = MS_SHAPE_POINT; points.numpoints = n; msAddLine( shape, &points ); } free( points.point ); /* } */ } static void osPoint(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d) { int n; if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, pnt ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, pnt ); else n = msOCIGet2DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ if (n == 1) { shape->type = MS_SHAPE_POINT; points.numpoints = 1; points.point = pnt; msAddLine( shape, &points ); } } static void osClosedPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int elem_type, int data3d, int data4d) { int n; n = (end - start)/2; points.point = (pointObj *)malloc( sizeof(pointObj)*n ); if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, points.point ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, points.point ); else n = msOCIGet2DOrdinates( hand, obj, start, end, points.point ); if (n > 0) { shape->type = (elem_type==21) ? MS_SHAPE_LINE : MS_SHAPE_POLYGON; points.numpoints = n; msAddLine( shape, &points ); } free( points.point ); } static void osRectangle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d) { int n; if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else n = msOCIGet2DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ if (n == 2) { shape->type = MS_SHAPE_POLYGON; points.numpoints = 5; points.point = pnt; /* point5 [0] & [1] contains the lower-left and upper-right points of the rectangle */ pnt[2] = pnt[1]; pnt[1].x = pnt[0].x; pnt[3].x = pnt[2].x; pnt[3].y = pnt[0].y; pnt[4] = pnt[0]; #ifdef USE_POINT_Z_M if (data3d||data4d) { pnt[1].z = pnt[0].z; pnt[3].z = pnt[2].z; } #endif /* USE_POINT_Z_M */ msAddLine( shape, &points ); } } static void osCircle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d) { int n; if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else n = msOCIGet2DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ if (n == 3) { if (msOCIConvertCircle( pnt )) { shape->type = MS_SHAPE_POINT; points.numpoints = 2; points.point = pnt; msAddLine( shape, &points ); } else { strlcpy( (char *)hand->last_oci_error, "Points in circle object are colinear", sizeof(hand->last_oci_error)); hand->last_oci_status = MS_FAILURE; } } } static void osArcPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj arcpoints, int elem_type, int data3d, int data4d) { int n, i; lineObj points = {0, NULL}; n = (end - start)/2; points.point = (pointObj *)malloc( sizeof(pointObj)*n ); if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, points.point ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, points.point ); else n = msOCIGet2DOrdinates( hand, obj, start, end, points.point ); if (n > 2) { shape->type = (elem_type==32) ? MS_SHAPE_POLYGON : MS_SHAPE_LINE; points.numpoints = n; for (i = 0; i < n-2; i = i+2) osGenerateArc(shape, arcpoints, points, i, n, data3d, data4d); } free (points.point); } static int osCheck2DGtype(int pIntGtype) { if (pIntGtype > 2000 && pIntGtype < 2008) { if (pIntGtype != 2004) return MS_TRUE; } return MS_FALSE; } static int osCheck3DGtype(int pIntGtype) { if (pIntGtype > 3000 && pIntGtype < 3308) { if (pIntGtype > 3007) pIntGtype-= 300; if (pIntGtype <= 3007 && pIntGtype != 3004) return MS_TRUE; } /* * Future version, untested * return (pIntGtype & 2208 && (pIntGtype & 3000 || pIntGtype & 3296) && pIntGtype & 3); */ return MS_FALSE; } static int osCheck4DGtype(int pIntGtype) { if (pIntGtype > 4000 && pIntGtype < 4408) { if (pIntGtype > 4007) pIntGtype-= 400; if (pIntGtype <= 4007 && pIntGtype != 4004) return MS_TRUE; } return MS_FALSE; } static int osGetOrdinates(msOracleSpatialDataHandler *dthand, msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, SDOGeometryInd *ind) { int gtype, elem_type, compound_type; float compound_lenght, compound_count; ub4 etype; ub4 interpretation; int nelems, nords, data3d, data4d; int elem, ord_start, ord_end; boolean exists; OCINumber *oci_number; double x, y; #ifdef USE_POINT_Z_M double z; #endif /* USE_POINT_Z_M */ int success; lineObj points = {0, NULL}; pointObj point5[5]; /* for quick access */ shapeObj newshape; /* for compound polygons */ /*stat the variables for compound polygons*/ compound_lenght = 0; compound_type = 0; compound_count = -1; data3d = 0; data4d = 0; if (ind->_atomic != OCI_IND_NULL) /* not a null object */ { nelems = nords = 0; success = TRY( hand, OCICollSize( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, &nelems ) ) && TRY( hand, OCICollSize( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, &nords ) ) && TRY( hand, OCINumberToInt( hand->errhp, &(obj->gtype), (uword)sizeof(int), OCI_NUMBER_SIGNED, (dvoid *)>ype ) ); /*&& (nords%2==0 && nelems%3==0);*/ /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ if (success && osCheck2DGtype(gtype)) { success = (nords%2==0 && nelems%3==0)?1:0; /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ } else if (success && osCheck3DGtype(gtype)) { success = (nords%3==0 && nelems%3==0)?1:0; /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ data3d = 1; } else if (success && osCheck4DGtype(gtype)) { success = (nords%4==0 && nelems%3==0)?1:0; /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ data4d = 1; } if (success) { /* reading SDO_POINT from SDO_GEOMETRY for a 2D/3D point geometry */ 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) { success = TRY( hand, OCINumberToReal( hand->errhp, &(obj->point.x), (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCINumberToReal( hand->errhp, &(obj->point.y), (uword)sizeof(double), (dvoid *)&y ) ); if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; shape->type = MS_SHAPE_POINT; points.numpoints = 1; points.point = point5; point5[0].x = x; point5[0].y = y; #ifdef USE_POINT_Z_M if (data3d || data4d) { if (ind->point.z == OCI_IND_NOTNULL) { success = TRY( hand, OCINumberToReal( hand->errhp, &(obj->point.z), (uword)sizeof(double), (dvoid *)&z )); if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; else point5[0].z = z; } else point5[0].z = z; } #endif /* USE_POINT_Z_M */ msAddLine( shape, &points ); return MS_SUCCESS; } /* if SDO_POINT not fetched, proceed reading elements (element info/ordinates) */ success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info,(sb4)0, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_SIGNED, (dvoid *)&ord_end ) ); elem = 0; ord_end--; /* shifts offset from 1..n to 0..n-1 */ do{ ord_start = ord_end; if (elem+3 >= nelems) /* processing last element */ { ord_end = nords; success = 1; } else /* get start ordinate position for next element which is ord_end for this element */ { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, (sb4)elem+3, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_SIGNED, (dvoid *)&ord_end ) ); ord_end--; /* shifts offset from 1..n to 0..n-1 */ } success = (success && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, (sb4)elem+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_UNSIGNED, (dvoid *)&etype ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, (sb4)elem+2, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_UNSIGNED, (dvoid *)&interpretation ) )); if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; if ( etype == 1005 || etype == 2005 || etype == 4 ) { compound_type = 1; compound_lenght = interpretation; compound_count = 0; msInitShape(&newshape); } elem_type = (etype == 1 && interpretation > 1) ? 10 : ((etype%10)*10 + interpretation); /* msDebug("osGetOrdinates shape->index = %ld\telem_type = %d\n",shape->index, elem_type); */ switch (elem_type) { case 10: /* point cluster with 'interpretation'-points */ osPointCluster (hand, shape, obj, ord_start, ord_end, points, interpretation, data3d, data4d); break; case 11: /* point type */ osPoint(hand, shape, obj, ord_start, ord_end, points, point5, data3d, data4d); break; case 21: /* line string whose vertices are connected by straight line segments */ if (compound_type) osClosedPolygon(hand, &newshape, obj, ord_start, (compound_count= compound_lenght) { osCloneShape(&newshape, shape, data3d, data4d); msFreeShape(&newshape); } if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; /* prepare for next cycle */ ord_start = ord_end; elem += 3; if (compound_type) compound_count++; } while (elem < nelems); /* end of element loop */ } /* end of gtype big-if */ } /* end of not-null-object if */ if (compound_type) msFreeShape(&newshape); return MS_SUCCESS; } static void msOCICloseConnection( void *hand ) { msOCICloseHandlers( (msOracleSpatialHandler *)hand ); } /* opens a layer by connecting to db with username/password@database stored in layer->connection */ int msOracleSpatialLayerOpen( layerObj *layer ) { char *username = NULL, *password = NULL, *dblink = NULL; msOracleSpatialLayerInfo *layerinfo = NULL; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialStatement *sthand = NULL, *sthand2 = NULL; msOracleSpatialHandler *hand = NULL; if (layer->debug) msDebug("msOracleSpatialLayerOpen called with: %s (Layer pointer %p)\n",layer->data, layer); if (layer->layerinfo != NULL) /* Skip if layer is already open */ return MS_SUCCESS; if (layer->data == NULL) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be:" "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'." "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE.", "msOracleSpatialLayerOpen()"); return MS_FAILURE; } layerinfo = (msOracleSpatialLayerInfo *)malloc(sizeof(msOracleSpatialLayerInfo)); dthand = (msOracleSpatialDataHandler *)malloc(sizeof(msOracleSpatialDataHandler)); sthand = (msOracleSpatialStatement *)malloc(sizeof(msOracleSpatialStatement)); sthand2 = (msOracleSpatialStatement *)malloc(sizeof(msOracleSpatialStatement)); if ((dthand == NULL) || (layerinfo == NULL)) { msSetError(MS_MEMERR, NULL, "msOracleSpatialLayerOpen()"); return MS_FAILURE; } memset( dthand, 0, sizeof(msOracleSpatialDataHandler) ); memset( sthand, 0, sizeof(msOracleSpatialStatement) ); memset( sthand2, 0, sizeof(msOracleSpatialStatement) ); memset( layerinfo, 0, sizeof(msOracleSpatialLayerInfo) ); msSplitLogin( layer->connection, layer->map, &username, &password, &dblink ); hand = (msOracleSpatialHandler *) msConnPoolRequest( layer ); if( hand == NULL ) { hand = msOCISetHandlers( username, password, dblink ); if (hand == NULL) { msOCICloseDataHandlers( dthand ); msOCIFinishStatement( sthand ); msOCIFinishStatement( sthand2 ); msOCIClearLayerInfo( layerinfo ); if (username) free(username); if (password) free(password); if (dblink) free(dblink); return MS_FAILURE; } if ( layer->debug ) msDebug("msOracleSpatialLayerOpen. Shared connection not available. Creating one.\n"); msConnPoolRegister( layer, hand, msOCICloseConnection ); } else { hand->ref_count++; hand->last_oci_status = MS_SUCCESS; hand->last_oci_error[0] = (text)'\0'; } if (!(msOCISetDataHandlers(hand, dthand) & msOCIOpenStatement(hand, sthand) & msOCIOpenStatement(hand, sthand2))) { msSetError( MS_ORACLESPATIALERR, "Cannot create OCI LayerInfo. " "Connection failure.", "msOracleSpatialLayerOpen()"); if (layer->debug) msDebug("msOracleSpatialLayerOpen. Cannot create OCI LayerInfo. Connection failure.\n"); msOCICloseDataHandlers ( dthand ); msOCICloseHandlers( hand ); msOCIClearLayerInfo( layerinfo ); } layerinfo->orahandlers = hand; layerinfo->oradatahandlers = dthand; layerinfo->orastmt = sthand; layerinfo->orastmt2 = sthand2; layer->layerinfo = layerinfo; if (username) free(username); if (password) free(password); if (dblink) free(dblink); return layer->layerinfo != NULL ? MS_SUCCESS : MS_FAILURE; } /* return MS_TRUE if layer is open, MS_FALSE otherwise.*/ int msOracleSpatialLayerIsOpen(layerObj *layer) { if (layer->layerinfo != NULL) return MS_TRUE; return MS_FALSE; } /* closes the layer, disconnecting from db if connected. layer->layerinfo is freed */ int msOracleSpatialLayerClose( layerObj *layer ) { msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; /*int lIntSuccessFree = 0;*/ if (layer->debug) msDebug("msOracleSpatialLayerClose was called. Layer: %p, Layer name: %s. Layer connection: %s\n", layer, layer->name, layer->connection); if (layerinfo != NULL) { /* * Some errors with the OCIObjectFree with query function * If uncomment draw mode will work but no query modes * Need to investigate the error cause */ /*lIntSuccessFree = TRY (layerinfo->orahandlers, OCIObjectFree(layerinfo->orahandlers->envhp, layerinfo->orahandlers->errhp, (dvoid *)layerinfo->obj, (ub2)OCI_OBJECTFREE_FORCE)); *if (!lIntSuccessFree) * msDebug("Error: %s\n", layerinfo->orahandlers->last_oci_error); */ /* Release Statement Handles */ if (layerinfo->orastmt != NULL) { msOCIFinishStatement(layerinfo->orastmt); layerinfo->orastmt = NULL; } if (layerinfo->orastmt2 != NULL) { msOCIFinishStatement(layerinfo->orastmt2); layerinfo->orastmt2 = NULL; } /* Release Datahandlers */ if (layer->debug) msDebug("msOracleSpatialLayerClose. Cleaning layerinfo handlers.\n"); msOCICloseDataHandlers( layerinfo->oradatahandlers ); layerinfo->oradatahandlers = NULL; /* Free the OCI cache only if there is no more layer that could use it */ layerinfo->orahandlers->ref_count--; if (layerinfo->orahandlers->ref_count == 0) OCICacheFree (layerinfo->orahandlers->envhp, layerinfo->orahandlers->errhp, layerinfo->orahandlers->svchp); /* Release Mapserver Pool */ if (layer->debug) msDebug("msOracleSpatialLayerClose. Release the Oracle Pool.\n"); msConnPoolRelease( layer, layerinfo->orahandlers ); /* Release Layerinfo */ layerinfo->orahandlers = NULL; msOCIClearLayerInfo( layerinfo ); layer->layerinfo = NULL; } return MS_SUCCESS; } /* create SQL statement for retrieving shapes */ /* Sets up cursor for use in *NextShape and *GetShape */ int msOracleSpatialLayerWhichShapes( layerObj *layer, rectObj rect, int isQuery) { int success, i; int function = 0; int version = 0; char query_str[6000]; char query_str2[256]; char *tmp_str=NULL, *tmp1_str=NULL; char *table_name; char *geom_column_name = NULL, *unique = NULL, *srid = NULL; OCIDefine *adtp = NULL; OCIDefine **items = NULL; OCINumber oci_number; OCIBind *bnd1p = NULL, *bnd2p = NULL; int existunique = MS_FALSE; int rownumisuniquekey = MS_FALSE; int numitemsinselect = 0; /* get layerinfo */ msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerWhichShapes called on unopened layer", "msOracleSpatialLayerWhichShapes()" ); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *)layerinfo->orastmt2; } /*init uniqueindex field*/ sthand->uniqueidindex=0; table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); /* parse geom_column_name and table_name */ if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version)) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be:" "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'." "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE." "Your data statement: %s", "msOracleSpatialLayerWhichShapes()", layer->data ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } /*rownum will be the first in the select if no UNIQUE key is defined or will be added at the end of the select*/ rownumisuniquekey = MS_TRUE; /*Define the unique*/ if (unique[0] == '\0') strcpy( unique, "rownum" ); else rownumisuniquekey = MS_FALSE; /* Check if the unique field is already in the items list */ existunique = MS_FALSE; if (unique) { for( i=0; i < layer->numitems; ++i ) { if (strcasecmp(unique, layer->items[i])==0) { sthand->uniqueidindex = i; existunique = MS_TRUE; break; } } } /* If no SRID is provided, set it to -1 (NULL) for binding */ if (strcmp(srid,"NULL") == 0) strcpy(srid,"-1"); snprintf( query_str, sizeof(query_str), "SELECT "); numitemsinselect = layer->numitems; /* allocate enough space for items */ if (layer->numitems >= 0) { /*we will always add a rownumber in the selection*/ numitemsinselect++; /*if unique key in the data is specfied and is not part of the current item lists, we should add it to the select*/ if(existunique == MS_FALSE && rownumisuniquekey == MS_FALSE) numitemsinselect++; /*the usinque index is there was no uniqueid given or the uniqueid given was not part of the items lists*/ if (existunique == MS_FALSE) sthand->uniqueidindex = layer->numitems; sthand->items = (item_text_array *)malloc( sizeof(item_text_array) * (numitemsinselect) ); if (sthand->items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate layerinfo->items buffer","msOracleSpatialLayerWhichShapes()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } items = (OCIDefine **)malloc(sizeof(OCIDefine *)*(numitemsinselect)); if (items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer","msOracleSpatialLayerWhichShapes()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } memset(items ,0,sizeof(OCIDefine *)*(numitemsinselect)); } /* define SQL query */ for( i=0; i < layer->numitems; ++i ) { snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s, ", layer->items[i] ); } /*we add the uniqueid if it was not part of the current item list*/ if(existunique == MS_FALSE && rownumisuniquekey == MS_FALSE) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s,", unique); /*we always want to add rownum is the selection to allow paging to work*/ snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s, ", "rownum"); snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s FROM %s", geom_column_name, table_name ); osFilteritem(layer, function, query_str, sizeof(query_str), 1); if (layer->maxfeatures > 0 && layer->startindex < 0) { if (function == FUNCTION_NONE && layer->filter.string == NULL) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s"," WHERE "); else if (function == FUNCTION_NONE && layer->filter.string != NULL) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s"," AND "); snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " ROWNUM<=%d ", layer->maxfeatures); if (function != FUNCTION_NONE) snprintf (query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " AND "); } if ((((atol(srid) >= 8192) && (atol(srid) <= 8330)) || (atol(srid) == 2) || (atol(srid) == 5242888) || (atol(srid) == 2000001)) && (version == VERSION_9i)) osGeodeticData(function, version, query_str, sizeof(query_str), geom_column_name, srid, rect); else osNoGeodeticData(function, version, query_str, sizeof(query_str), geom_column_name, srid, rect); /*assuming startindex starts at 1*/ if (layer->startindex > 0) { tmp1_str = msStrdup("SELECT * from (SELECT atmp.*, ROWNUM rnum from ("); tmp_str = msStringConcatenate(tmp_str, tmp1_str); msFree(tmp1_str); tmp_str = msStringConcatenate(tmp_str, query_str); /*oder by rowid does not seem to work with function using the spatial filter, at least on layers loaded using ogr in a 11g database*/ if (function == FUNCTION_NONE || function == FUNCTION_RELATE || function == FUNCTION_GEOMRELATE) tmp1_str = msStrdup( "order by rowid"); else tmp1_str = msStrdup(""); if (layer->maxfeatures > 0) snprintf(query_str2, sizeof(query_str2), " %s) atmp where ROWNUM<=%d) where rnum >=%d", tmp1_str, layer->maxfeatures+layer->startindex-1, layer->startindex); else snprintf( query_str2, sizeof(query_str2), " %s) atmp) where rnum >=%d", tmp1_str, layer->startindex); msFree(tmp1_str); tmp_str = msStringConcatenate(tmp_str, query_str2); snprintf(query_str, sizeof(query_str), "%s", tmp_str); msFree(tmp_str); } if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes. Using this Sql to retrieve the data: %s\n", query_str); if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes. Bind values: srid:%s minx:%f miny:%f maxx:%f maxy:%f \n", srid, rect.minx, rect.miny, rect.maxx, rect.maxy); /* prepare */ success = TRY( hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) ); if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes getting ordinate definition.\n"); /* get the object definition of the ordinate array */ ordinates_tdo = get_tdo(SDO_ORDINATE_ARRAY, hand, dthand ); if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes converting to OCIColl.\n"); /* initialized the collection array */ success = TRY( hand, OCIObjectNew(hand->envhp, hand->errhp, hand->svchp, OCI_TYPECODE_VARRAY, ordinates_tdo, (dvoid *)NULL, OCI_DURATION_SESSION, FALSE, (dvoid **)&ordinates) ); /* convert it to a OCI number and then append minx...maxy to the collection */ success = TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.minx), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)) &&TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.miny), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)) &&TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.maxx), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)) &&TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.maxy), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)); if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes bind by name and object.\n"); /* do the actual binding */ if (success && function != FUNCTION_NONE) { const char* bind_key; char* bind_value; char* bind_tag; success = TRY( hand, /* bind in srid */ OCIBindByName( sthand->stmthp, &bnd2p, hand->errhp, (text *) ":srid", strlen(":srid"),(ub1 *) srid, strlen(srid)+1, SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT) ) && TRY(hand, /* bind in rect by name */ 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)) && TRY(hand, /* bind in rect object */ OCIBindObject(bnd1p, hand->errhp, ordinates_tdo, (dvoid **)&ordinates, (ub4 *)0, (dvoid **)0, (ub4 *)0)); /* bind the variables from the bindvals hash */ bind_key = (char*)msFirstKeyFromHashTable(&layer->bindvals); while(bind_key != NULL) { bind_value = msLookupHashTable(&layer->bindvals, bind_key); bind_tag = (char*)malloc(sizeof(char) * strlen(bind_key) + 2); sprintf(bind_tag, ":%s", bind_key); 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, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)); bind_key = msNextKeyFromHashTable(&layer->bindvals, bind_key); } } if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes name and object now bound.\n"); if (success && layer->numitems >= 0) { for( i=0; i < numitemsinselect && success; ++i ) 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 ) ); } if (success) { int cursor_type = OCI_DEFAULT; if(isQuery) cursor_type =OCI_STMT_SCROLLABLE_READONLY; success = TRY( hand, /* define spatial position adtp ADT object */ OCIDefineByPos( sthand->stmthp, &adtp, hand->errhp, (ub4)numitemsinselect+1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT) ) && TRY( hand, /* define object tdo from adtp */ OCIDefineObject( adtp, hand->errhp, dthand->tdo, (dvoid **)sthand->obj, (ub4 *)0, (dvoid **)sthand->ind, (ub4 *)0 ) ) && TRY(hand, /* execute */ OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)cursor_type ) ) && TRY( hand, /* get rows fetched */ OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ) && TRY( hand, /* get rows count */ OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_count, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp ) ); } if (!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s . " "Check your data statement.", "msOracleSpatialLayerWhichShapes()", hand->last_oci_error, query_str ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } /* should begin processing first row */ sthand->row_num = sthand->row = 0; /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_SUCCESS; } /* fetch next shape from previous SELECT stmt (see *WhichShape()) */ int msOracleSpatialLayerNextShape( layerObj *layer, shapeObj *shape ) { SDOGeometryObj *obj; SDOGeometryInd *ind; int success, /*lIntSuccessFree,*/ i; /* get layerinfo */ msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerWhichShapes called on unopened layer", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *)layerinfo->orastmt2; } /* no rows fetched */ if (sthand->rows_fetched == 0) return MS_DONE; if(layer->debug >=5 ) msDebug("msOracleSpatialLayerNextShape on layer %p, row_num: %d\n", layer, sthand->row_num); do{ /* is buffer empty? */ if (sthand->row >= sthand->rows_fetched) { /* fetch more */ success = TRY( hand, OCIStmtFetch2( sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_count, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp ) ); if(layer->debug >= 4 ) msDebug("msOracleSpatialLayerNextShape on layer %p, Fetched %d more rows (%d total)\n", layer, sthand->rows_fetched, sthand->rows_count); if (!success || sthand->rows_fetched == 0) return MS_DONE; if (sthand->row_num >= sthand->rows_count) return MS_DONE; sthand->row = 0; /* reset buffer row index */ } /* set obj & ind for current row */ obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape->index = atol( (char *)(sthand->items[sthand->uniqueidindex][ sthand->row ])); /* Primary Key */ shape->resultindex = sthand->row_num; shape->numvalues = layer->numitems; shape->values = (char **)malloc( sizeof(char*) * shape->numvalues ); if (shape->values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } for( i=0; i < shape->numvalues; ++i ) { shape->values[i] = (char *)malloc(strlen((char *)sthand->items[i][ sthand->row ])+1); if (shape->values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } else { strcpy(shape->values[i], (char *)sthand->items[i][ sthand->row ]); shape->values[i][strlen((char *)sthand->items[i][ sthand->row ])] = '\0'; } } /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, shape, obj, ind); /* increment for next row */ sthand->row_num++; sthand->row++; if (success != MS_SUCCESS) { return MS_FAILURE; } osShapeBounds(shape); }while(shape->type == MS_SHAPE_NULL); return MS_SUCCESS; } int msOracleSpatialLayerGetShape( layerObj *layer, shapeObj *shape, resultObj *record) { int success, i; SDOGeometryObj *obj; SDOGeometryInd *ind; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialLayerInfo *layerinfo; msOracleSpatialStatement *sthand = NULL; long shapeindex = record->shapeindex; int resultindex = record->resultindex; if(layer == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape called on unopened layer","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape called on unopened layer (layerinfo)","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } /* If resultindex is set, fetch the shape from the resultcache, otherwise fetch it from the DB */ if (resultindex >= 0) { long buffer_first_row_num, buffer_last_row_num; /* get layerinfo */ dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *)layerinfo->orastmt2; if (layer->resultcache == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape called before msOracleSpatialLayerWhichShapes()","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } if (resultindex >= sthand->rows_count) { if (layer->debug >= 5) msDebug("msOracleSpatialLayerGetShape problem with cursor. Trying to fetch record = %ld of %ld, falling back to GetShape\n", resultindex, sthand->rows_count); msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape record out of range","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } if (layer->debug >= 5) msDebug("msOracleSpatialLayerGetShape was called. Using the record = %ld of %ld. (shape: %ld should equal pkey: %ld)\n", resultindex, layer->resultcache->numresults, layer->resultcache->results[resultindex].shapeindex, shapeindex); /* NOTE: with the way the resultcache works, we should see items in increasing order, but some may have been filtered out. */ /* Best case: item in buffer */ /* Next best case: item is in next fetch block */ /* Worst case: item is random access */ buffer_first_row_num = sthand->row_num - sthand->row; /* cursor id of first item in buffer */ buffer_last_row_num = buffer_first_row_num + sthand->rows_fetched - 1; /* cursor id of last item in buffer */ if(resultindex >= buffer_first_row_num && resultindex <= buffer_last_row_num) /* Item is in buffer. Calculate position in buffer */ { sthand->row += resultindex - sthand->row_num; /* move sthand row an row_num by offset from last call */ sthand->row_num += resultindex - sthand->row_num; } else /* Item is not in buffer. Fetch item from Oracle */ { if (layer->debug >= 4) msDebug("msOracleSpatialLayerGetShape: Fetching result from DB start: %ld end:%ld record: %ld\n", buffer_first_row_num, buffer_last_row_num, resultindex); success = TRY( hand, OCIStmtFetch2( sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub2)OCI_FETCH_ABSOLUTE, (sb4)resultindex+1, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ); ERROR("msOracleSpatialLayerGetShape", hand, dthand); sthand->row_num = resultindex; sthand->row = 0; /* reset row index */ if (!success || sthand->rows_fetched == 0) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape could not fetch specified record.", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } } /* set obj & ind for current row */ obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape->index = shapeindex; /* By definition this is what we asked for */ shape->numvalues = layer->numitems; shape->values = (char **)malloc( sizeof(char*) * shape->numvalues ); if (shape->values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } for( i=0; i < shape->numvalues; ++i ) { shape->values[i] = (char *)malloc(strlen((char *)sthand->items[i][ sthand->row ])+1); if (shape->values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } else { strcpy(shape->values[i], (char *)sthand->items[i][ sthand->row ]); shape->values[i][strlen((char *)sthand->items[i][ sthand->row ])] = '\0'; } } /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, shape, obj, ind); if (success != MS_SUCCESS) { msSetError( MS_ORACLESPATIALERR, "Call to osGetOrdinates failed.", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } osShapeBounds(shape); if(shape->type == MS_SHAPE_NULL) { 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()" ); return MS_FAILURE; } return (MS_SUCCESS); } else /* no resultindex, fetch the shape from the DB */ { char *table_name; char query_str[6000], *geom_column_name = NULL, *unique = NULL, *srid = NULL; int function = 0; int version = 0; sb2 *nullind = NULL; /*OCIDefine *adtp = NULL, *items[QUERY_SIZE] = { NULL };*/ OCIDefine *adtp = NULL; OCIDefine **items = NULL; if (layer->debug) msDebug("msOracleSpatialLayerGetShape was called. Using the record = %ld.\n", shapeindex); dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; /* allocate enough space for items */ if (layer->numitems > 0) { if (sthand->items_query == NULL) sthand->items_query = (item_text_array_query *)malloc( sizeof(item_text_array_query) * (layer->numitems) ); if (sthand->items_query == NULL) { msSetError( MS_ORACLESPATIALERR, "Cannot allocate layerinfo->items_query buffer", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } nullind = (sb2 *)malloc( sizeof(sb2) * (layer->numitems) ); if (nullind == NULL) { msSetError( MS_ORACLESPATIALERR, "Cannot allocate nullind buffer", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } memset(nullind ,0, sizeof(sb2) * (layer->numitems) ); items = (OCIDefine **)malloc(sizeof(OCIDefine *)*layer->numitems); if (items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer","msOracleSpatialLayerWhichShapes()" ); /* clean nullind */ free(nullind); return MS_FAILURE; } memset(items ,0,sizeof(OCIDefine *)*layer->numitems); } table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version )) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: %s", "msOracleSpatialLayerGetShape()", layer->data ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } /*Define the first query to retrive itens*/ if (unique[0] == '\0') { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable for query. To execute " "query functions you need to define one " "unique column [USING UNIQUE <#column>]", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } else snprintf( query_str, sizeof(query_str), "SELECT"); /*Define the query*/ for( i = 0; i < layer->numitems; ++i ) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " %s,", layer->items[i] ); 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); /*if (layer->filter.string != NULL) sprintf( query_str + strlen(query_str), " AND %s", (layer->filter.string));*/ osFilteritem(layer, FUNCTION_NONE, query_str, sizeof(query_str), 2); if (layer->debug) msDebug("msOracleSpatialLayerGetShape. Sql: %s\n", query_str); /*Prepare the handlers to the query*/ success = TRY( hand,OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) ); if (success && layer->numitems > 0) { for( i = 0; i < layer->numitems && success; i++ ) 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 ) ); } if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s . " "Check your data statement.", "msOracleSpatialLayerGetShape()", hand->last_oci_error, query_str ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (success) { 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) ) && TRY( hand, OCIDefineObject( adtp, hand->errhp, dthand->tdo, (dvoid **)sthand->obj, (ub4 *)0, (dvoid **)sthand->ind, (ub4 *)0 ) ) && TRY (hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT )) && TRY (hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp )); } if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s ." "Check your data statement.", "msOracleSpatialLayerGetShape()", hand->last_oci_error, query_str ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } shape->type = MS_SHAPE_NULL; /* no rows fetched */ if (sthand->rows_fetched == 0) { /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return (MS_DONE); } obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape->numvalues = layer->numitems; shape->values = (char **) malloc(sizeof(char *) * layer->numitems); if (shape->values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values.", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } shape->index = shapeindex; for( i = 0; i < layer->numitems; ++i ) { shape->values[i] = (char *)malloc(strlen((char *)sthand->items_query[sthand->row][i])+1); if (shape->values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items buffer.", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } else { if (nullind[i] != OCI_IND_NULL) { strcpy(shape->values[i], (char *)sthand->items_query[sthand->row][i]); shape->values[i][strlen((char *)sthand->items_query[sthand->row][i])] = '\0'; } else { shape->values[i][0] = '\0'; } } } /* increment for next row */ sthand->row_num++; sthand->row++; /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, shape, obj, ind); if (success != MS_SUCCESS) { msSetError( MS_ORACLESPATIALERR, "Cannot execute query", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } osShapeBounds(shape); sthand->row = sthand->row_num = 0; /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return (MS_SUCCESS); } } int msOracleSpatialLayerInitItemInfo( layerObj *layer ) { int i; int *itemindexes ; if (layer->debug) msDebug("msOracleSpatialLayerInitItemInfo was called.\n"); if (layer->numitems == 0) return MS_SUCCESS; if (layer->iteminfo) free( layer->iteminfo ); if ((layer->iteminfo = (long *)malloc(sizeof(int)*layer->numitems))== NULL) { msSetError(MS_MEMERR, NULL, "msOracleSpatialLayerInitItemInfo()"); return MS_FAILURE; } itemindexes = (int*)layer->iteminfo; for(i=0; i < layer->numitems; i++) itemindexes[i] = i; /*last one is always the geometry one - the rest are non-geom*/ return MS_SUCCESS; } /* AutoProjection Support for RFC 37 #3333 * TODO: Needs testing */ int msOracleSpatialLayerGetAutoProjection( layerObj *layer, projectionObj *projection ) { char *table_name; char *query_str, *geom_column_name = NULL, *unique = NULL, *srid = NULL; int success; int function = 0; int version = 0; char wktext[4000]; OCIDefine *def1p = NULL; OCIBind *bnd1p = NULL, *bnd2p = NULL; msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layer->debug) msDebug("msOracleSpatialLayerGetAutoProjection was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetAutoProjection called on unopened layer","msOracleSpatialLayerGetAutoProjection()"); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; } table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version )) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: %s", "msOracleSpatialLayerGetAutoProjection()", layer->data ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } 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 " "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"; if (layer->debug) msDebug("msOracleSpatialLayerGetAutoProjection. Using this Sql to retrieve the projection: %s.\n", query_str); /*Prepare the handlers to the query*/ success = TRY( hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT ) ) && 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 ) ) && 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 ) ) && 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 ) ) && TRY( hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)0, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ); if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s . " "Check your data statement.", "msOracleSpatialLayerGetAutoProjection()", hand->last_oci_error, query_str ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } do { success = TRY( hand, OCIStmtFetch( sthand->stmthp, hand->errhp, (ub4)1, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ); if (success && sthand->rows_fetched > 0) { if( layer->debug ) msDebug("Found WKT projection for table %s: %s\n", table_name, wktext); if(wktext != NULL && projection != NULL) if(msOGCWKT2ProjectionObj(wktext, projection, layer->debug) == MS_FAILURE) return(MS_FAILURE); } } while (sthand->rows_fetched > 0); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_SUCCESS; } /********************************************************************** * msOracleSpatialGetFieldDefn() * * Pass the field definitions through to the layer metadata in the * "gml_[item]_{type,width,precision}" set of metadata items for * defining fields. **********************************************************************/ static void msOracleSpatialGetFieldDefn( layerObj *layer, msOracleSpatialHandler *hand, const char *item, OCIParam *pard ) { const char *gml_type = "Character"; char md_item_name[256]; char gml_width[32], gml_precision[32]; int success; ub2 rzttype, nOCILen; gml_width[0] = '\0'; gml_precision[0] = '\0'; /* -------------------------------------------------------------------- */ /* Get basic parameter details. */ /* -------------------------------------------------------------------- */ success = TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&rzttype,(ub4 *)0, (ub4) OCI_ATTR_DATA_TYPE, hand->errhp )) && TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&nOCILen ,(ub4 *)0, (ub4) OCI_ATTR_DATA_SIZE, hand->errhp )); if( !success ) return; switch( rzttype ) { case SQLT_CHR: case SQLT_AFC: gml_type = "Character"; if( nOCILen <= 4000 ) sprintf( gml_width, "%d", nOCILen ); break; case SQLT_NUM: { /* NOTE: OCI docs say this should be ub1 type, but we have determined that oracle is actually returning a short so we use that type and try to compensate for possible problems by initializing, and dividing by 256 if it is large. */ unsigned short byPrecision = 0; sb1 nScale = 0; if( !TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&byPrecision ,(ub4 *)0, (ub4) OCI_ATTR_PRECISION, hand->errhp )) || !TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&nScale,(ub4 *)0, (ub4) OCI_ATTR_SCALE, hand->errhp )) ) return; if( byPrecision > 255 ) byPrecision = byPrecision / 256; if( nScale > 0 ) { gml_type = "Real"; sprintf( gml_width, "%d", byPrecision ); sprintf( gml_precision, "%d", nScale ); } else if( nScale < 0 ) gml_type = "Real"; else { gml_type = "Integer"; if( byPrecision < 38 ) sprintf( gml_width, "%d", byPrecision ); } } break; case SQLT_DAT: case SQLT_DATE: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: case SQLT_TIME: case SQLT_TIME_TZ: gml_type = "Date"; break; default: gml_type = "Character"; } snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", item ); if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", item ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",item ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); } int msOracleSpatialLayerGetItems( layerObj *layer ) { char *rzt = ""; ub2 rzttype = 0; char *flk = ""; int function = 0; int version = 0; int existgeom; int count_item, flk_len, success, i; char *table_name; char query_str[6000], *geom_column_name = NULL, *unique = NULL, *srid = NULL; OCIParam *pard = (OCIParam *) 0; msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *) layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; int get_field_details = 0; const char *value; if (layer->debug) msDebug("msOracleSpatialLayerGetItems was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetItems called on unopened layer", "msOracleSpatialLayerGetItems()" ); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; } /* Will we want to capture the field details? */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) get_field_details = 1; table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData(layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version)) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: %s", "msOracleSpatialLayerGetItems()", layer->data ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } snprintf( query_str, sizeof(query_str), "SELECT * FROM %s", table_name ); success = TRY( hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DESCRIBE_ONLY) ) && TRY( hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DESCRIBE_ONLY ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&layer->numitems, (ub4 *)0, OCI_ATTR_PARAM_COUNT, hand->errhp) ); if (!success) { msSetError( MS_QUERYERR, "Cannot retrieve column list", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } sthand->row_num = sthand->row = 0; layer->numitems = layer->numitems-1; layer->items = malloc (sizeof(char *) * (layer->numitems)); if (layer->items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (layer->numitems > 0) { if (sthand->items_query == NULL) sthand->items_query = (item_text_array_query *)malloc( sizeof(item_text_array_query) * (layer->numitems) ); if (sthand->items_query == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } } count_item = 0; existgeom = 0; /*Upcase conversion for the geom_column_name*/ for (i=0; geom_column_name[i] != '\0'; i++) geom_column_name[i] = toupper(geom_column_name[i]); /*Retrive columns name from the user table*/ for (i = 0; i <= layer->numitems; i++) { success = TRY( hand, OCIParamGet ((dvoid*) sthand->stmthp, (ub4)OCI_HTYPE_STMT,hand->errhp,(dvoid*)&pard, (ub4)i+1)) && TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM,(dvoid*)&rzttype,(ub4 *)0, (ub4) OCI_ATTR_DATA_TYPE, hand->errhp )) && TRY( hand, OCIParamGet ((dvoid*) sthand->stmthp, (ub4)OCI_HTYPE_STMT,hand->errhp,(dvoid*)&pard, (ub4)i+1)) && TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM,(dvoid*)&rzt,(ub4 *)&flk_len, (ub4) OCI_ATTR_NAME, hand->errhp )); /* if (layer->debug) msDebug("msOracleSpatialLayerGetItems checking type. Column = %s Type = %d\n", rzt, rzttype); */ flk = (char *)malloc(sizeof(char*) * flk_len+1); if (flk == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } else { strlcpy(flk, rzt, flk_len+1); } /*Comapre the column name (flk) with geom_column_name and ignore with true*/ if (strcmp(flk, geom_column_name) != 0) { if (rzttype!=OCI_TYPECODE_BLOB) { layer->items[count_item] = (char *)malloc(sizeof(char) * flk_len+1); if (layer->items[count_item] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items buffer", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } strcpy(layer->items[count_item], flk); count_item++; if( get_field_details ) msOracleSpatialGetFieldDefn( layer, hand, layer->items[count_item-1], pard ); } } else existgeom = 1; strcpy( rzt, "" ); free(flk); /* Better?!*/ flk_len = 0; } layer->numitems = count_item; if (!(existgeom)) { msSetError (MS_ORACLESPATIALERR, "No geometry column, check stmt", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return msOracleSpatialLayerInitItemInfo( layer ); } int msOracleSpatialLayerGetExtent(layerObj *layer, rectObj *extent) { char *table_name; char query_str[6000], *geom_column_name = NULL, *unique = NULL, *srid = NULL; int success, i; int function = 0; int version = 0; SDOGeometryObj *obj = NULL; SDOGeometryInd *ind = NULL; shapeObj shape; rectObj bounds; /*OCIDefine *adtp = NULL, *items[QUERY_SIZE] = { NULL };*/ OCIDefine *adtp = NULL; OCIDefine **items = NULL; msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layer->debug) msDebug("msOracleSpatialLayerGetExtent was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetExtent called on unopened layer","msOracleSpatialLayerGetExtent()"); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; } /* allocate enough space for items */ if (layer->numitems > 0) { sthand->items_query = (item_text_array_query *)malloc( sizeof(item_text_array_query) * (layer->numitems) ); if (sthand->items_query == NULL) { msSetError( MS_ORACLESPATIALERR, "Cannot allocate layerinfo->items buffer", "msOracleSpatialLayerGetExtent()" ); return MS_FAILURE; } items = (OCIDefine **)malloc(sizeof(OCIDefine *)*layer->numitems); if (items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer","msOracleSpatialLayerWhichShapes()" ); return MS_FAILURE; } memset(items ,0,sizeof(OCIDefine *)*layer->numitems); } table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &function, &version )) { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: %s", "msOracleSpatialLayerGetExtent()", layer->data ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (version == VERSION_10g) osAggrGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); else { if (((atol(srid) < 8192) || (atol(srid) > 8330)) && (atol(srid) != 2) && (atol(srid) != 5242888) && (atol(srid) != 2000001)) { if (version == VERSION_9i) osAggrGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); else osConvexHullGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); } else osConvexHullGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); } if (layer->debug) msDebug("msOracleSpatialLayerGetExtent. Using this Sql to retrieve the extent: %s.\n", query_str); /*Prepare the handlers to the query*/ success = TRY( hand,OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) ); if (success && layer->numitems > 0) { for( i = 0; i < layer->numitems && success; ++i ) 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 ) ); } if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s . " "Check your data statement.", "msOracleSpatialLayerGetExtent()", hand->last_oci_error, query_str ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } if (success) { 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) ) && TRY( hand, OCIDefineObject( adtp, hand->errhp, dthand->tdo, (dvoid **)sthand->obj, (ub4 *)0, (dvoid **)sthand->ind, (ub4 *)0 ) ) && TRY (hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT )) && TRY (hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp )); } if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s ." "Check your data statement.", "msOracleSpatialLayerGetExtent()", hand->last_oci_error, query_str ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } /* should begin processing first row */ sthand->row_num = sthand->row = 0; msInitShape( &shape ); do{ /* is buffer empty? */ if (sthand->row_num >= sthand->rows_fetched) { /* fetch more */ success = TRY( hand, OCIStmtFetch( sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp ) ); if (!success || sthand->rows_fetched == 0) break; if (sthand->row_num >= sthand->rows_fetched) break; sthand->row = 0; /* reset row index */ } /* no rows fetched */ if (sthand->rows_fetched == 0) break; obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape.numvalues = layer->numitems; shape.values = (char **) malloc(sizeof(char *) * layer->numitems); if (shape.values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values.", "msOracleSpatialLayerGetExtent()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } shape.index = sthand->row_num; for( i = 0; i < layer->numitems; ++i ) { shape.values[i] = (char *)malloc(strlen((char *)sthand->items_query[sthand->row][i])+1); if (shape.values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items buffer.", "msOracleSpatialLayerGetExtent()" ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } else { strcpy(shape.values[i], (char *)sthand->items_query[sthand->row][i]); shape.values[i][strlen((char *)sthand->items_query[sthand->row][i])] = '\0'; } } /* increment for next row */ sthand->row_num++; sthand->row++; /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, &shape, obj, ind); if (success != MS_SUCCESS) { msSetError( MS_ORACLESPATIALERR, "Cannot execute query", "msOracleSpatialLayerGetExtent()" ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } }while(sthand->row <= sthand->rows_fetched); sthand->row = sthand->row_num = 0; osShapeBounds(&shape); bounds = shape.bounds; extent->minx = bounds.minx; extent->miny = bounds.miny; extent->maxx = bounds.maxx; extent->maxy = bounds.maxy; msFreeShape(&shape); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return(MS_SUCCESS); } void msOracleSpatialLayerFreeItemInfo( layerObj *layer ) { if (layer->debug) msDebug("msOracleSpatialLayerFreeItemInfo was called.\n"); if (layer->iteminfo) free(layer->iteminfo); layer->iteminfo = NULL; /* nothing to do */ } int msOracleSpatialLayerGetAutoStyle( mapObj *map, layerObj *layer, classObj *c, shapeObj *shape ) { msSetError( MS_ORACLESPATIALERR, "Function not implemented yet", "msLayerGetAutoStyle()" ); return MS_FAILURE; } #else /* OracleSpatial "not-supported" procedures */ int msOracleSpatialLayerOpen(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerOpen()" ); return MS_FAILURE; } int msOracleSpatialLayerIsOpen(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerIsOpen()" ); return MS_FALSE; } int msOracleSpatialLayerClose(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerClose()" ); return MS_FAILURE; } int msOracleSpatialLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerWhichShapes()" ); return MS_FAILURE; } int msOracleSpatialLayerNextShape(layerObj *layer, shapeObj *shape) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } int msOracleSpatialLayerGetItems(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerGetItems()" ); return MS_FAILURE; } int msOracleSpatialLayerGetShape( layerObj *layer, shapeObj *shape, resultObj *record ) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } int msOracleSpatialLayerGetExtent(layerObj *layer, rectObj *extent) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerGetExtent()" ); return MS_FAILURE; } int msOracleSpatialLayerInitItemInfo(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerInitItemInfo()" ); return MS_FAILURE; } void msOracleSpatialLayerFreeItemInfo(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerFreeItemInfo()" ); } int msOracleSpatialLayerGetAutoStyle( mapObj *map, layerObj *layer, classObj *c, shapeObj *shape ) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerGetAutoStyle()" ); return MS_FAILURE; } #endif #ifdef USE_ORACLE_PLUGIN #ifdef USE_ORACLESPATIAL MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) { assert(layer != NULL); assert(vtable != NULL); vtable->LayerInitItemInfo = msOracleSpatialLayerInitItemInfo; vtable->LayerFreeItemInfo = msOracleSpatialLayerFreeItemInfo; vtable->LayerOpen = msOracleSpatialLayerOpen; vtable->LayerIsOpen = msOracleSpatialLayerIsOpen; vtable->LayerWhichShapes = msOracleSpatialLayerWhichShapes; vtable->LayerNextShape = msOracleSpatialLayerNextShape; vtable->LayerGetShape = msOracleSpatialLayerGetShape; vtable->LayerClose = msOracleSpatialLayerClose; vtable->LayerGetItems = msOracleSpatialLayerGetItems; vtable->LayerGetExtent = msOracleSpatialLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ vtable->LayerCloseConnection = msOracleSpatialLayerClose; vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection = msOracleSpatialLayerGetAutoProjection; Disabled until tested */ return MS_SUCCESS; } #endif #endif int msOracleSpatialLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msOracleSpatialLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msOracleSpatialLayerFreeItemInfo; layer->vtable->LayerOpen = msOracleSpatialLayerOpen; layer->vtable->LayerIsOpen = msOracleSpatialLayerIsOpen; layer->vtable->LayerWhichShapes = msOracleSpatialLayerWhichShapes; layer->vtable->LayerNextShape = msOracleSpatialLayerNextShape; layer->vtable->LayerGetShape = msOracleSpatialLayerGetShape; layer->vtable->LayerClose = msOracleSpatialLayerClose; layer->vtable->LayerGetItems = msOracleSpatialLayerGetItems; layer->vtable->LayerGetExtent = msOracleSpatialLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ layer->vtable->LayerCloseConnection = msOracleSpatialLayerClose; layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; layer->vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection = msOracleSpatialLayerGetAutoProjection; Disabled until tested */ return MS_SUCCESS; }