1235
1311
/************************************************************************/
1236
/* FinalizeNewLayer() */
1238
/* Our main job here is to update the USER_SDO_GEOM_METADATA */
1239
/* table to include the correct array of dimension object with */
1240
/* the appropriate extents for this layer. We may also do */
1241
/* spatial indexing at this point. */
1312
/* UpdateLayerExtents() */
1242
1313
/************************************************************************/
1244
void OGROCITableLayer::FinalizeNewLayer()
1315
void OGROCITableLayer::UpdateLayerExtents()
1247
OGROCIStringBuf sDimUpdate;
1249
FlushPendingFeatures();
1251
/* -------------------------------------------------------------------- */
1252
/* If the dimensions are degenerate (all zeros) then we assume */
1253
/* there were no geometries, and we don't bother setting the */
1255
/* -------------------------------------------------------------------- */
1256
if( sExtent.MaxX == 0 && sExtent.MinX == 0
1257
&& sExtent.MaxY == 0 && sExtent.MinY == 0 )
1318
if( !bExtentUpdated )
1321
bExtentUpdated = false;
1323
/* -------------------------------------------------------------------- */
1324
/* Do we have existing layer extents we need to merge in to the */
1325
/* ones we collected as we created features? */
1326
/* -------------------------------------------------------------------- */
1327
bool bHaveOldExtent = false;
1329
if( !bNewLayer && pszGeomName )
1259
CPLError( CE_Warning, CPLE_AppDefined,
1260
"Layer %s appears to have no geometry ... not setting SDO DIMINFO metadata.",
1261
poFeatureDefn->GetName() );
1331
OGROCIStringBuf oCommand;
1333
oCommand.Appendf(1000,
1334
"select min(case when r=1 then sdo_lb else null end) minx, min(case when r=2 then sdo_lb else null end) miny, "
1335
"min(case when r=1 then sdo_ub else null end) maxx, min(case when r=2 then sdo_ub else null end) maxy"
1336
" from (SELECT d.sdo_dimname, d.sdo_lb, sdo_ub, sdo_tolerance, rownum r"
1337
" FROM ALL_SDO_GEOM_METADATA m, table(m.diminfo) d"
1338
" where m.table_name = UPPER('%s') and m.COLUMN_NAME = UPPER('%s')",
1339
osTableName.c_str(), pszGeomName );
1343
oCommand.Appendf(500, " AND OWNER = UPPER('%s')", osOwner.c_str() );
1346
oCommand.Append(" ) ");
1348
OGROCISession *poSession = poDS->GetSession();
1349
CPLAssert( NULL != poSession );
1351
OGROCIStatement oGetExtent( poSession );
1353
if( oGetExtent.Execute( oCommand.GetString() ) == CE_None )
1355
char **papszRow = oGetExtent.SimpleFetchRow();
1357
if( papszRow != NULL
1358
&& papszRow[0] != NULL && papszRow[1] != NULL
1359
&& papszRow[2] != NULL && papszRow[3] != NULL )
1361
OGREnvelope sOldExtent;
1363
bHaveOldExtent = true;
1365
sOldExtent.MinX = CPLAtof(papszRow[0]);
1366
sOldExtent.MinY = CPLAtof(papszRow[1]);
1367
sOldExtent.MaxX = CPLAtof(papszRow[2]);
1368
sOldExtent.MaxY = CPLAtof(papszRow[3]);
1370
if( sOldExtent.Contains( sExtent ) )
1373
sExtent = sOldExtent;
1374
bExtentUpdated = false;
1379
sExtent.Merge( sOldExtent );
1266
1385
/* -------------------------------------------------------------------- */
1290
1409
dfZMax = 100000.0;
1291
1410
dfZRes = 0.002;
1292
1411
ParseDIMINFO( "DIMINFO_Z", &dfZMin, &dfZMax, &dfZRes );
1413
/* -------------------------------------------------------------------- */
1414
/* If we already have an extent in the table, we will need to */
1415
/* update it in place. */
1416
/* -------------------------------------------------------------------- */
1417
OGROCIStringBuf sDimUpdate;
1419
if( bHaveOldExtent )
1421
sDimUpdate.Append( "UPDATE USER_SDO_GEOM_METADATA " );
1422
sDimUpdate.Append( "SET DIMINFO =" );
1423
sDimUpdate.Append( "MDSYS.SDO_DIM_ARRAY(" );
1424
sDimUpdate.Appendf(200,
1425
"MDSYS.SDO_DIM_ELEMENT('X',%.16g,%.16g,%.12g)",
1426
dfXMin, dfXMax, dfXRes );
1427
sDimUpdate.Appendf(200,
1428
",MDSYS.SDO_DIM_ELEMENT('Y',%.16g,%.16g,%.12g)",
1429
dfYMin, dfYMax, dfYRes );
1431
if( nDimension == 3 )
1433
sDimUpdate.Appendf(200,
1434
",MDSYS.SDO_DIM_ELEMENT('Z',%.16g,%.16g,%.12g)",
1435
dfZMin, dfZMax, dfZRes );
1438
sDimUpdate.Appendf(strlen(poFeatureDefn->GetName()) + 100,") WHERE TABLE_NAME = '%s'", poFeatureDefn->GetName());
1294
1443
/* -------------------------------------------------------------------- */
1295
1444
/* Prepare dimension update statement. */
1296
1445
/* -------------------------------------------------------------------- */
1297
sDimUpdate.Append( "INSERT INTO USER_SDO_GEOM_METADATA VALUES " );
1298
sDimUpdate.Appendf( strlen(poFeatureDefn->GetName()) + 100,
1300
poFeatureDefn->GetName(),
1303
sDimUpdate.Append( "MDSYS.SDO_DIM_ARRAY(" );
1304
sDimUpdate.Appendf(200,
1305
"MDSYS.SDO_DIM_ELEMENT('X',%.16g,%.16g,%.12g)",
1306
dfXMin, dfXMax, dfXRes );
1307
sDimUpdate.Appendf(200,
1308
",MDSYS.SDO_DIM_ELEMENT('Y',%.16g,%.16g,%.12g)",
1309
dfYMin, dfYMax, dfYRes );
1311
if( nDimension == 3 )
1313
sDimUpdate.Appendf(200,
1314
",MDSYS.SDO_DIM_ELEMENT('Z',%.16g,%.16g,%.12g)",
1315
dfZMin, dfZMax, dfZRes );
1446
sDimUpdate.Append( "INSERT INTO USER_SDO_GEOM_METADATA VALUES " );
1447
sDimUpdate.Appendf( strlen(poFeatureDefn->GetName()) + 100,
1449
poFeatureDefn->GetName(),
1452
sDimUpdate.Append( "MDSYS.SDO_DIM_ARRAY(" );
1453
sDimUpdate.Appendf(200,
1454
"MDSYS.SDO_DIM_ELEMENT('X',%.16g,%.16g,%.12g)",
1455
dfXMin, dfXMax, dfXRes );
1456
sDimUpdate.Appendf(200,
1457
",MDSYS.SDO_DIM_ELEMENT('Y',%.16g,%.16g,%.12g)",
1458
dfYMin, dfYMax, dfYRes );
1460
if( nDimension == 3 )
1462
sDimUpdate.Appendf(200,
1463
",MDSYS.SDO_DIM_ELEMENT('Z',%.16g,%.16g,%.12g)",
1464
dfZMin, dfZMax, dfZRes );
1468
sDimUpdate.Append( "), NULL)" );
1470
sDimUpdate.Appendf( 100, "), %d)", nSRID );
1319
sDimUpdate.Append( "), NULL)" );
1321
sDimUpdate.Appendf( 100, "), %d)", nSRID );
1323
1473
/* -------------------------------------------------------------------- */
1324
/* Execute the metadata update. */
1474
/* Run the update/insert command. */
1325
1475
/* -------------------------------------------------------------------- */
1326
1476
OGROCIStatement oExecStatement( poDS->GetSession() );
1328
if( oExecStatement.Execute( sDimUpdate.GetString() ) != CE_None )
1478
oExecStatement.Execute( sDimUpdate.GetString() );
1481
/************************************************************************/
1482
/* FinalizeNewLayer() */
1484
/* Our main job here is to update the USER_SDO_GEOM_METADATA */
1485
/* table to include the correct array of dimension object with */
1486
/* the appropriate extents for this layer. We may also do */
1487
/* spatial indexing at this point. */
1488
/************************************************************************/
1490
void OGROCITableLayer::FinalizeNewLayer()
1493
UpdateLayerExtents();
1495
/* -------------------------------------------------------------------- */
1496
/* For new layers we try to create a spatial index. */
1497
/* -------------------------------------------------------------------- */
1498
if( bNewLayer && sExtent.IsInit() )
1331
1500
/* -------------------------------------------------------------------- */
1332
1501
/* If the user has disabled INDEX support then don't create the */
1334
1503
/* -------------------------------------------------------------------- */
1335
if( !CSLFetchBoolean( papszOptions, "INDEX", TRUE ) )
1504
if( !CSLFetchBoolean( papszOptions, "INDEX", TRUE ) )
1338
1507
/* -------------------------------------------------------------------- */
1339
1508
/* Establish an index name. For some reason Oracle 8.1.7 does */
1340
1509
/* not support spatial index names longer than 18 characters so */
1341
1510
/* we magic up an index name if it would be too long. */
1342
1511
/* -------------------------------------------------------------------- */
1343
char szIndexName[20];
1345
if( strlen(poFeatureDefn->GetName()) < 15 )
1346
sprintf( szIndexName, "%s_idx", poFeatureDefn->GetName() );
1347
else if( strlen(poFeatureDefn->GetName()) < 17 )
1348
sprintf( szIndexName, "%si", poFeatureDefn->GetName() );
1352
const char *pszSrcName = poFeatureDefn->GetName();
1354
for( i = 0; pszSrcName[i] != '\0'; i++ )
1355
nHash = (nHash + i * pszSrcName[i]) % 987651;
1512
char szIndexName[20];
1514
if( strlen(poFeatureDefn->GetName()) < 15 )
1515
sprintf( szIndexName, "%s_idx", poFeatureDefn->GetName() );
1516
else if( strlen(poFeatureDefn->GetName()) < 17 )
1517
sprintf( szIndexName, "%si", poFeatureDefn->GetName() );
1521
const char *pszSrcName = poFeatureDefn->GetName();
1523
for( i = 0; pszSrcName[i] != '\0'; i++ )
1524
nHash = (nHash + i * pszSrcName[i]) % 987651;
1357
sprintf( szIndexName, "OSI_%d", nHash );
1526
sprintf( szIndexName, "OSI_%d", nHash );
1360
poDS->GetSession()->CleanName( szIndexName );
1529
poDS->GetSession()->CleanName( szIndexName );
1362
1531
/* -------------------------------------------------------------------- */
1363
1532
/* Try creating an index on the table now. Use a simple 5 */
1364
1533
/* level quadtree based index. Would R-tree be a better default? */
1365
1534
/* -------------------------------------------------------------------- */
1367
// Disable for now, spatial index creation always seems to cause me to
1368
// lose my connection to the database!
1369
OGROCIStringBuf sIndexCmd;
1371
sIndexCmd.Appendf( 10000, "CREATE INDEX \"%s\" ON %s(\"%s\") "
1372
"INDEXTYPE IS MDSYS.SPATIAL_INDEX ",
1374
poFeatureDefn->GetName(),
1377
if( CSLFetchNameValue( papszOptions, "INDEX_PARAMETERS" ) != NULL )
1379
sIndexCmd.Append( " PARAMETERS( '" );
1380
sIndexCmd.Append( CSLFetchNameValue(papszOptions,"INDEX_PARAMETERS") );
1381
sIndexCmd.Append( "' )" );
1384
if( oExecStatement.Execute( sIndexCmd.GetString() ) != CE_None )
1386
char szDropCommand[2000];
1387
sprintf( szDropCommand, "DROP INDEX \"%s\"", szIndexName );
1388
oExecStatement.Execute( szDropCommand );
1535
OGROCIStringBuf sIndexCmd;
1536
OGROCIStatement oExecStatement( poDS->GetSession() );
1539
sIndexCmd.Appendf( 10000, "CREATE INDEX \"%s\" ON %s(\"%s\") "
1540
"INDEXTYPE IS MDSYS.SPATIAL_INDEX ",
1542
poFeatureDefn->GetName(),
1545
if( CSLFetchNameValue( papszOptions, "INDEX_PARAMETERS" ) != NULL )
1547
sIndexCmd.Append( " PARAMETERS( '" );
1548
sIndexCmd.Append( CSLFetchNameValue(papszOptions,"INDEX_PARAMETERS") );
1549
sIndexCmd.Append( "' )" );
1552
if( oExecStatement.Execute( sIndexCmd.GetString() ) != CE_None )
1554
CPLString osDropCommand;
1555
osDropCommand.Printf( "DROP INDEX \"%s\"", szIndexName );
1556
oExecStatement.Execute( osDropCommand );
1392
1561
/************************************************************************/
1393
/* AllocAndBindForWrite() */
1562
/* AllocAndBindForWrite(int eType) */
1394
1563
/************************************************************************/
1396
int OGROCITableLayer::AllocAndBindForWrite()
1565
/* -------------------------------------------------------------------- */
1566
/* PJH: modified with geometry type parameter so as not to */
1567
/* attempt to write geometry if there is none to write as */
1568
/* Oracle will default the value of the column to Null. */
1569
/* -------------------------------------------------------------------- */
1570
int OGROCITableLayer::AllocAndBindForWrite(int eType)
1399
1573
OGROCISession *poSession = poDS->GetSession();
1436
1612
/* -------------------------------------------------------------------- */
1437
1613
/* Setup geometry indicator information. */
1438
1614
/* -------------------------------------------------------------------- */
1439
pasWriteGeomInd = (SDO_GEOMETRY_ind *)
1440
CPLCalloc(sizeof(SDO_GEOMETRY_ind),nWriteCacheMax);
1615
if (eType != wkbNone)
1617
pasWriteGeomInd = (SDO_GEOMETRY_ind *)
1618
CPLCalloc(sizeof(SDO_GEOMETRY_ind),nWriteCacheMax);
1442
papsWriteGeomIndMap = (SDO_GEOMETRY_ind **)
1443
CPLCalloc(sizeof(SDO_GEOMETRY_ind *),nWriteCacheMax);
1620
papsWriteGeomIndMap = (SDO_GEOMETRY_ind **)
1621
CPLCalloc(sizeof(SDO_GEOMETRY_ind *),nWriteCacheMax);
1445
for( i = 0; i < nWriteCacheMax; i++ )
1446
papsWriteGeomIndMap[i] = pasWriteGeomInd + i;
1623
for( i = 0; i < nWriteCacheMax; i++ )
1624
papsWriteGeomIndMap[i] = pasWriteGeomInd + i;
1448
1626
/* -------------------------------------------------------------------- */
1449
1627
/* Setup all the required geometry objects, and the */
1450
1628
/* corresponding indicator map. */
1451
1629
/* -------------------------------------------------------------------- */
1452
pasWriteGeoms = (SDO_GEOMETRY_TYPE *)
1453
CPLCalloc( sizeof(SDO_GEOMETRY_TYPE), nWriteCacheMax);
1454
papsWriteGeomMap = (SDO_GEOMETRY_TYPE **)
1455
CPLCalloc( sizeof(SDO_GEOMETRY_TYPE *), nWriteCacheMax );
1630
pasWriteGeoms = (SDO_GEOMETRY_TYPE *)
1631
CPLCalloc( sizeof(SDO_GEOMETRY_TYPE), nWriteCacheMax);
1632
papsWriteGeomMap = (SDO_GEOMETRY_TYPE **)
1633
CPLCalloc( sizeof(SDO_GEOMETRY_TYPE *), nWriteCacheMax );
1457
for( i = 0; i < nWriteCacheMax; i++ )
1458
papsWriteGeomMap[i] = pasWriteGeoms + i;
1635
for( i = 0; i < nWriteCacheMax; i++ )
1636
papsWriteGeomMap[i] = pasWriteGeoms + i;
1460
1638
/* -------------------------------------------------------------------- */
1461
1639
/* Allocate VARRAYs for the elem_info and ordinates. */
1462
1640
/* -------------------------------------------------------------------- */
1463
for( i = 0; i < nWriteCacheMax; i++ )
1465
if( poSession->Failed(
1641
for( i = 0; i < nWriteCacheMax; i++ )
1643
if( poSession->Failed(
1466
1644
OCIObjectNew( poSession->hEnv, poSession->hError,
1467
1645
poSession->hSvcCtx, OCI_TYPECODE_VARRAY,
1468
1646
poSession->hElemInfoTDO, (dvoid *)NULL,