OGR_PG驱动源码-OGRPGDataSource
读取Layer
1.papoLayers被写入
OGRPGDataSource通过成员变量papoLayers
保存Layer数组,该变量数据的写入分析如下:
该数组数据的新增仅在OGRPGDataSource::OpenTable()
和OGRPGDataSource::ICreateLayer()
中实现。
OpenTable()
在OGRPGDataSource::GetLayerByName()
和OGRPGDataSource::LoadTables()
中会被调用。
LoadTables()
在OGRPGDataSource::GetLayerCount()
中被调用。
除开ICreateLayer()
和GetLayerByName()
,papoLayers
被写入就只有一条调用线:GetLayerCount()->LoadTables()->OpenTable()。
2.OGRPGDataSource::LoadTables()
LoadTables()中,读取成员变量pszForcedTables
,从中获取出需要读取的表名,多个表名由逗号分割,如下为LoadTables()部分源码:
if( pszForcedTables )
{
char **papszTableList = CSLTokenizeString2( pszForcedTables, ",", 0 );
for( int i = 0; i < CSLCount(papszTableList); i++ )
{
pszForcedTables
在OGRPGDataSource::Open()
的时候被赋值,首先遍历传入的OpenOptions,取出设置的tables的值,如果OpenOptions中没有设置,则在DataSource接收的连接字符串中查找并取出该值(连接字符串示例:PG:dbname=db1 host=127.0.0.1 port=5432 user=u password=p tables=t1,t2
),如下为Open()部分源码:
std::string osForcedTables;
for(const char* pszOpenOption: apszOpenOptions)
{
const char* pszVal = CSLFetchNameValue(papszOpenOptions, pszOpenOption);
if( pszVal && strcmp(pszOpenOption, "active_schema") == 0 )
{
osActiveSchema = pszVal;
}
else if( pszVal && strcmp(pszOpenOption, "schemas") == 0 )
{
osSchemas = pszVal;
}
else if( pszVal && strcmp(pszOpenOption, "tables") == 0 )
{
osForcedTables = pszVal;
}
......
}
......
/* -------------------------------------------------------------------- */
/* Determine if the connection string contains an optional */
/* TABLES portion. If so, parse it out. The expected */
/* connection string in this case will be, e.g.: */
/* */
/* 'PG:dbname=warmerda user=warmerda tables=s1.t1,[s2.t2,...] */
/* - where sN is schema and tN is table name */
/* We must also strip this information from the connection */
/* string; PQconnectdb() does not like unknown directives */
/* -------------------------------------------------------------------- */
if( !osForcedTables.empty() ||
(!bIsURI && ParseAndRemoveParam(pszConnectionNameNoPrefix, "tables", osForcedTables)) )
{
pszForcedTables = CPLStrdup(osForcedTables.c_str());
}
继续回到LoadTables()部分,获取到表名后,构建PGTableEntry
实体,追加到临时数组papsTables
中,并设置SchemaName和TableName,每有一个table,则nTableCount
自增1,源码如下:
papsTables = static_cast<PGTableEntry**>(CPLRealloc(papsTables, sizeof(PGTableEntry*) * (nTableCount + 1)));
papsTables[nTableCount] = static_cast<PGTableEntry*>(CPLCalloc(1, sizeof(PGTableEntry)));
if (pszGeomColumnName)
OGRPGTableEntryAddGeomColumn(papsTables[nTableCount], pszGeomColumnName);
if( nParts == 2 )
{
papsTables[nTableCount]->pszSchemaName = CPLStrdup( papszQualifiedParts[0] );
papsTables[nTableCount]->pszTableName = CPLStrdup( papszQualifiedParts[1] );
}
else
{
papsTables[nTableCount]->pszSchemaName = CPLStrdup( osActiveSchema.c_str());
papsTables[nTableCount]->pszTableName = CPLStrdup( papszQualifiedParts[0] );
}
nTableCount ++;
接下来会判断nTableCount
的值,如果为0则代表没有从连接字符串中获取到指定表,则加载所有的表:
if( nTableCount == 0 && bHavePostGIS && sPostGISVersion.nMajor >= 2 &&
!bListAllTables &&
/* Config option mostly for comparison/debugging/etc... */
CPLTestBool(CPLGetConfigOption("PG_USE_POSTGIS2_OPTIM", "YES")) )
{......}
else if (nTableCount == 0)
{......}
最后遍历加载到的所有表,调用OpenTable()
写入papoLayers
:
/* -------------------------------------------------------------------- */
/* Register the available tables. */
/* -------------------------------------------------------------------- */
for( int iRecord = 0; iRecord < nTableCount; iRecord++ )
{
......
OGRPGTableLayer* poLayer =
OpenTable( osCurrentSchema, papsTables[iRecord]->pszTableName,
papsTables[iRecord]->pszSchemaName,
papsTables[iRecord]->pszDescription,
nullptr, bDSUpdate, FALSE );
......
}