📄 ogrpgtablelayer.cpp
字号:
// Grow the command buffer? if( strlen(pszStrValue) + strlen(pszCommand+nOffset) + nOffset > nCommandBufSize-50 ) { nCommandBufSize = strlen(pszCommand) + strlen(pszStrValue) + 10000; pszCommand = (char *) CPLRealloc(pszCommand, nCommandBufSize ); } if( poFeatureDefn->GetFieldDefn(i)->GetType() != OFTInteger && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTReal ) { int iChar; /* We need to quote and escape string fields. */ strcat( pszCommand+nOffset, "'" ); nOffset += strlen(pszCommand+nOffset); for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ ) { if( poFeatureDefn->GetFieldDefn(i)->GetType() != OFTIntegerList && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTRealList && poFeatureDefn->GetFieldDefn(i)->GetWidth() > 0 && iChar == poFeatureDefn->GetFieldDefn(i)->GetWidth() ) { CPLDebug( "PG", "Truncated %s field value, it was too long.", poFeatureDefn->GetFieldDefn(i)->GetNameRef() ); break; } if( pszStrValue[iChar] == '\\' || pszStrValue[iChar] == '\'' ) { pszCommand[nOffset++] = '\\'; pszCommand[nOffset++] = pszStrValue[iChar]; } else pszCommand[nOffset++] = pszStrValue[iChar]; } pszCommand[nOffset] = '\0'; strcat( pszCommand+nOffset, "'" ); } else { strcat( pszCommand+nOffset, pszStrValue ); } if( pszNeedToFree ) CPLFree( pszNeedToFree ); } strcat( pszCommand+nOffset, ")" );/* -------------------------------------------------------------------- *//* Execute the insert. *//* -------------------------------------------------------------------- */ hResult = PQexec(hPGConn, pszCommand); if( PQresultStatus(hResult) != PGRES_COMMAND_OK ) { CPLDebug( "OGR_PG", "PQexec(%s)\n", pszCommand ); CPLFree( pszCommand ); CPLError( CE_Failure, CPLE_AppDefined, "INSERT command for new feature failed.\n%s", PQerrorMessage(hPGConn) ); PQclear( hResult ); poDS->SoftRollback(); return OGRERR_FAILURE; } CPLFree( pszCommand );#ifdef notdef /* Should we use this oid to get back the FID and assign back to the feature? I think we are supposed to. */ Oid nNewOID = PQoidValue( hResult ); printf( "nNewOID = %d\n", (int) nNewOID );#endif PQclear( hResult ); return poDS->SoftCommit();}/************************************************************************//* TestCapability() *//************************************************************************/int OGRPGTableLayer::TestCapability( const char * pszCap ){ if( EQUAL(pszCap,OLCSequentialWrite) || EQUAL(pszCap,OLCRandomWrite) ) return bUpdateAccess; else if( EQUAL(pszCap,OLCCreateField) ) return bUpdateAccess; else if( EQUAL(pszCap,OLCRandomRead) ) return bHasFid; else return OGRPGLayer::TestCapability( pszCap );}/************************************************************************//* CreateField() *//************************************************************************/OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK ){ PGconn *hPGConn = poDS->GetPGConn(); PGresult *hResult; char szCommand[1024]; char szFieldType[256]; OGRFieldDefn oField( poFieldIn );/* -------------------------------------------------------------------- *//* Do we want to "launder" the column names into Postgres *//* friendly format? *//* -------------------------------------------------------------------- */ if( bLaunderColumnNames ) { char *pszSafeName = poDS->LaunderName( oField.GetNameRef() ); oField.SetName( pszSafeName ); CPLFree( pszSafeName ); if( EQUAL(oField.GetNameRef(),"oid") ) { CPLError( CE_Warning, CPLE_AppDefined, "Renaming field 'oid' to 'oid_' to avoid conflict with internal oid field." ); oField.SetName( "oid_" ); } } /* -------------------------------------------------------------------- *//* Work out the PostgreSQL type. *//* -------------------------------------------------------------------- */ if( oField.GetType() == OFTInteger ) { if( oField.GetWidth() > 0 && bPreservePrecision ) sprintf( szFieldType, "NUMERIC(%d,0)", oField.GetWidth() ); else strcpy( szFieldType, "INTEGER" ); } else if( oField.GetType() == OFTReal ) { if( oField.GetWidth() > 0 && oField.GetPrecision() > 0 && bPreservePrecision ) sprintf( szFieldType, "NUMERIC(%d,%d)", oField.GetWidth(), oField.GetPrecision() ); else strcpy( szFieldType, "FLOAT8" ); } else if( oField.GetType() == OFTString ) { if( oField.GetWidth() == 0 || !bPreservePrecision ) strcpy( szFieldType, "VARCHAR" ); else sprintf( szFieldType, "CHAR(%d)", oField.GetWidth() ); } else if( oField.GetType() == OFTIntegerList ) { strcpy( szFieldType, "INTEGER[]" ); } else if( oField.GetType() == OFTRealList ) { strcpy( szFieldType, "FLOAT8[]" ); } else if( bApproxOK ) { CPLError( CE_Warning, CPLE_NotSupported, "Can't create field %s with type %s on PostgreSQL layers. Creating as VARCHAR.", oField.GetNameRef(), OGRFieldDefn::GetFieldTypeName(oField.GetType()) ); strcpy( szFieldType, "VARCHAR" ); } else { CPLError( CE_Failure, CPLE_NotSupported, "Can't create field %s with type %s on PostgreSQL layers.", oField.GetNameRef(), OGRFieldDefn::GetFieldTypeName(oField.GetType()) ); return OGRERR_FAILURE; }/* -------------------------------------------------------------------- *//* Create the new field. *//* -------------------------------------------------------------------- */ poDS->FlushSoftTransaction(); hResult = PQexec(hPGConn, "BEGIN"); PQclear( hResult ); sprintf( szCommand, "ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s", poFeatureDefn->GetName(), oField.GetNameRef(), szFieldType ); hResult = PQexec(hPGConn, szCommand); if( PQresultStatus(hResult) != PGRES_COMMAND_OK ) { CPLError( CE_Failure, CPLE_AppDefined, "%s\n%s", szCommand, PQerrorMessage(hPGConn) ); PQclear( hResult ); hResult = PQexec( hPGConn, "ROLLBACK" ); PQclear( hResult ); return OGRERR_FAILURE; } PQclear( hResult ); hResult = PQexec(hPGConn, "COMMIT"); PQclear( hResult ); poFeatureDefn->AddFieldDefn( &oField ); return OGRERR_NONE;}/************************************************************************//* GetFeature() *//************************************************************************/OGRFeature *OGRPGTableLayer::GetFeature( long nFeatureId ){ if( pszFIDColumn == NULL ) return OGRLayer::GetFeature( nFeatureId );/* -------------------------------------------------------------------- *//* Discard any existing resultset. *//* -------------------------------------------------------------------- */ ResetReading();/* -------------------------------------------------------------------- *//* Issue query for a single record. *//* -------------------------------------------------------------------- */ OGRFeature *poFeature = NULL; PGresult *hResult; PGconn *hPGConn = poDS->GetPGConn(); char *pszFieldList = BuildFields(); char *pszCommand = (char *) CPLMalloc(strlen(pszFieldList)+2000); poDS->FlushSoftTransaction(); poDS->SoftStartTransaction(); sprintf( pszCommand, "DECLARE getfeaturecursor CURSOR for " "SELECT %s FROM \"%s\" WHERE %s = %ld", pszFieldList, poFeatureDefn->GetName(), pszFIDColumn, nFeatureId ); CPLFree( pszFieldList ); hResult = PQexec(hPGConn, pszCommand ); CPLFree( pszCommand ); if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK ) { PQclear( hResult ); hResult = PQexec(hPGConn, "FETCH ALL in getfeaturecursor" ); if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK ) { hCursorResult = hResult; poFeature = RecordToFeature( 0 ); hCursorResult = NULL; } }/* -------------------------------------------------------------------- *//* Cleanup *//* -------------------------------------------------------------------- */ PQclear( hResult ); hResult = PQexec(hPGConn, "CLOSE getfeaturecursor"); PQclear( hResult ); poDS->FlushSoftTransaction(); return poFeature;}/************************************************************************//* GetFeatureCount() *//* *//* If a spatial filter is in effect, we turn control over to *//* the generic counter. Otherwise we return the total count. *//* Eventually we should consider implementing a more efficient *//* way of counting features matching a spatial query. *//************************************************************************/int OGRPGTableLayer::GetFeatureCount( int bForce ){/* -------------------------------------------------------------------- *//* Use a more brute force mechanism if we have a spatial query *//* in play. *//* -------------------------------------------------------------------- */ if( m_poFilterGeom != NULL && !bHasPostGISGeometry ) return OGRPGLayer::GetFeatureCount( bForce );/* -------------------------------------------------------------------- *//* In theory it might be wise to cache this result, but it *//* won't be trivial to work out the lifetime of the value. *//* After all someone else could be adding records from another *//* application when working against a database. *//* -------------------------------------------------------------------- */ PGconn *hPGConn = poDS->GetPGConn(); PGresult *hResult; char szCommand[4096]; int nCount = 0; poDS->FlushSoftTransaction(); hResult = PQexec(hPGConn, "BEGIN"); PQclear( hResult ); sprintf( szCommand, "DECLARE countCursor CURSOR for " "SELECT count(*) FROM \"%s\" " "%s", poFeatureDefn->GetName(), pszWHERE ); CPLDebug( "OGR_PG", "PQexec(%s)\n", szCommand ); hResult = PQexec(hPGConn, szCommand); PQclear( hResult ); hResult = PQexec(hPGConn, "FETCH ALL in countCursor"); if( hResult != NULL && PQresultStatus(hResult) == PGRES_TUPLES_OK ) nCount = atoi(PQgetvalue(hResult,0,0)); else CPLDebug( "OGR_PG", "%s; failed.", szCommand ); PQclear( hResult ); hResult = PQexec(hPGConn, "CLOSE countCursor"); PQclear( hResult ); hResult = PQexec(hPGConn, "COMMIT"); PQclear( hResult ); return nCount;}/************************************************************************//* GetSpatialRef() *//* *//* We override this to try and fetch the table SRID from the *//* geometry_columns table if the srsid is -2 (meaning we *//* haven't yet even looked for it). *//************************************************************************/OGRSpatialReference *OGRPGTableLayer::GetSpatialRef(){ if( nSRSId == -2 ) { PGconn *hPGConn = poDS->GetPGConn(); PGresult *hResult; char szCommand[1024]; nSRSId = -1; poDS->SoftStartTransaction(); sprintf( szCommand, "SELECT srid FROM geometry_columns " "WHERE f_table_name = '%s'", poFeatureDefn->GetName() ); hResult = PQexec(hPGConn, szCommand ); if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK && PQntuples(hResult) == 1 ) { nSRSId = atoi(PQgetvalue(hResult,0,0)); } PQclear( hResult ); poDS->SoftCommit(); } return OGRPGLayer::GetSpatialRef();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -