Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 0cbeafc4a4
Fetching contributors…

Cannot retrieve contributors at this time

3681 lines (3080 sloc) 138.518 kB
/******************************************************************************
* 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 <assert.h>
#ifdef USE_ORACLESPATIAL
#include <oci.h>
#include <ctype.h>
#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;
/* Driver handling of pagination, enabled by default */
int paging;
} 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 *)&paramp, (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 *)&paramp, (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 *)&gtype ) );
/*&& (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)?ord_end+2:ord_end, points, elem_type, data3d, data4d);
else
osClosedPolygon(hand, shape, obj, ord_start, ord_end, points, elem_type, data3d, data4d);
break;
case 22: /* compound type */
if (compound_type)
osArcPolygon(hand, &newshape, obj, ord_start, (compound_count<compound_lenght)?ord_end+2:ord_end , points, elem_type, data3d, data4d);
else
osArcPolygon(hand, shape, obj, ord_start, ord_end, points, elem_type, data3d, data4d);
break;
case 31: /* simple polygon with n points, last point equals the first one */
osClosedPolygon(hand, shape, obj, ord_start, ord_end, points, elem_type, data3d, data4d);
break;
case 32: /* Polygon with arcs */
osArcPolygon(hand, shape, obj, ord_start, ord_end, points, elem_type, data3d, data4d);
break;
case 33: /* rectangle defined by 2 points */
osRectangle(hand, shape, obj, ord_start, ord_end, points, point5, data3d, data4d);
break;
case 34: /* circle defined by 3 points */
osCircle(hand, shape, obj, ord_start, ord_end, points, point5, data3d, data4d);
break;
}
if (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 <column> SRID srid# FUNCTION]' or "
"'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> 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) );
layerinfo->paging = MS_TRUE;
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 <column> SRID srid# FUNCTION]' or "
"'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> 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 (layerinfo->paging && 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 (layerinfo->paging && 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 <column> SRID srid# FUNCTION]' or "
"'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> 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 <column> SRID srid# FUNCTION]' or "
"'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> 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 <column> SRID srid# FUNCTION]' or "
"'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> 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 <column> SRID srid# FUNCTION]' or "
"'geometry_column FROM (SELECT stmt) [USING UNIQUE <column> 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;
}
int msOrableSpatialGetPaging(layerObj *layer)
{
msOracleSpatialLayerInfo *layerinfo = NULL;
if (layer->debug)
msDebug("msOracleSpatialLayerGetPaging was called.\n");
if(!msOracleSpatialLayerIsOpen(layer))
return MS_TRUE;
assert( layer->layerinfo != NULL);
layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo;
return layerinfo->paging;
}
void msOrableSpatialEnablePaging(layerObj *layer, int value)
{
msOracleSpatialLayerInfo *layerinfo = NULL;
if (layer->debug)
msDebug("msOracleSpatialLayerEnablePaging was called.\n");
if(!msOracleSpatialLayerIsOpen(layer))
msOracleSpatialLayerOpen(layer);
assert( layer->layerinfo != NULL);
layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo;
layerinfo->paging = value;
return;
}
#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;
}
void msOrableSpatialEnablePaging(layerObj *layer, int value)
{
msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerEnablePaging()" );
return;
}
int msOrableSpatialGetPaging(layerObj *layer)
{
msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerGetPaging()" );
return;
}
#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 */
vtable->LayerEnablePaging = msOrableSpatialEnablePaging;
vtable->LayerGetPaging = msOrableSpatialGetPaging;
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;