in src/odbc/rsodbc/rslibpq.c [2013:2190]
static void getResultDescription(PGresult *pgResult, RS_RESULT_INFO *pResult, int iFetchRefCursor)
{
// SELECT kind of operation returning rows
int col;
// #of cols
pResult->iNumberOfCols = PQnfields(pgResult);
pResult->pIRDRecs = (RS_DESC_REC *)rs_calloc(pResult->iNumberOfCols,sizeof(RS_DESC_REC));
// Get column(s) infomation
for(col = 0; col < pResult->iNumberOfCols; col++)
{
RS_DESC_REC *pDescRec = &pResult->pIRDRecs[col];
Oid pgType;
int pgMod;
char *pName;
char *pTemp;
int case_sensitive;
pDescRec->hRecNumber = col + 1;
if(col)
{
// Link previous element to this one.
pResult->pIRDRecs[col - 1].pNext = pDescRec;
}
// Column name is allocated in libpq
pName = PQfname(pgResult, col);
copyStrDataSmallLen(pName, SQL_NTS, pDescRec->szName, MAX_IDEN_LEN, NULL);
if(pResult->phstmt && pResult->phstmt->iCatalogQuery)
{
// Make the column name upper case
_strupr(pDescRec->szName);
}
pResult->columnNameIndexMap[pName] = col + 1;
pgType = PQftype(pgResult, col);
pDescRec->hType = mapPgTypeToSqlType(pgType,&(pDescRec->hRsSpecialType));
if(iFetchRefCursor && (pgType == REFCURSOROID))
{
// Mark result for auto refcursor fetch
pResult->iRefCursorInResult = TRUE;
}
pgMod = PQfmod(pgResult, col);
if(pgMod < 0)
{
if(pgType == NAMEOID)
pDescRec->iSize = MAX_NAMEOID_SIZE;
else
if(pgType == TIMETZOID)
pDescRec->iSize = MAX_TIMETZOID_SIZE;
else
if(pgType == REFCURSOROID || pgType == VOIDOID)
pDescRec->iSize = 65535;
else
if(pgType == TIMESTAMPTZOID)
pDescRec->iSize = MAX_TIMESTAMPTZOID_SIZE;
else
if(pgType == INTERVALY2MOID)
pDescRec->iSize = MAX_INTERVALY2MOID_SIZE;
else
if(pgType == INTERVALD2SOID)
pDescRec->iSize = MAX_INTERVALD2SOID_SIZE;
else
if(pgType == SUPER)
pDescRec->iSize = MAX_SUPER_SIZE;
else
if(pgType == VARBYTE)
pDescRec->iSize = MAX_VARBYTE_SIZE;
else
if (pgType == GEOMETRY
|| pgType == GEOMETRYHEX)
pDescRec->iSize = MAX_GEOMETRY_SIZE;
else
if (pgType == GEOGRAPHY)
pDescRec->iSize = MAX_GEOGRAPHY_SIZE;
else
pDescRec->iSize = 0; // Unknown
}
else
{
if(pDescRec->hType == SQL_NUMERIC
|| pDescRec->hType == SQL_DECIMAL)
{
// Upper 2 bytes are precision
pDescRec->iSize = (pgMod >> 16) & 0xFFFF;
}
else
if(pgType == TIMETZOID)
pDescRec->iSize = MAX_TIMETZOID_SIZE;
else
{
pDescRec->iSize = pgMod - 4; // 4 for sizeof(int) itself.
}
}
if(pDescRec->hType == SQL_NUMERIC
|| pDescRec->hType == SQL_DECIMAL)
{
if(pgMod == -1)
pDescRec->hScale = 0;
else
{
// Lower 2 bytes are scale
pDescRec->hScale = (pgMod & 0xFFFF) -4; // 4 for sizeof(int) itself.
}
}
else
pDescRec->hScale = 0;
pDescRec->hNullable = PQfnullable(pgResult, col);
// Get col attributes
pDescRec->cAutoInc = (PQfauto_increment(pgResult, col) == 1) ? SQL_TRUE : SQL_FALSE;
// Catalog name is allocated in libpq
pTemp = PQfcatalog_name(pgResult, col);
if (pTemp)
{
copyStrDataSmallLen(pTemp, SQL_NTS, pDescRec->szCatalogName, MAX_IDEN_LEN, NULL);
if (pResult->phstmt && pResult->phstmt->iCatalogQuery)
{
// Make the catalog name upper case
_strupr(pDescRec->szCatalogName);
}
}
else
pDescRec->szCatalogName[0] = '\0';
// Schema name is allocated in libpq
pTemp = PQfschema_name(pgResult, col);
if (pTemp)
{
copyStrDataSmallLen(pTemp, SQL_NTS, pDescRec->szSchemaName, MAX_IDEN_LEN, NULL);
if (pResult->phstmt && pResult->phstmt->iCatalogQuery)
{
// Make the catalog name upper case
_strupr(pDescRec->szSchemaName);
}
}
else
pDescRec->szSchemaName[0] = '\0';
// Table name is allocated in libpq
pTemp = PQftable_name(pgResult, col);
if (pTemp)
{
copyStrDataSmallLen(pTemp, SQL_NTS, pDescRec->szTableName, MAX_IDEN_LEN, NULL);
if (pResult->phstmt && pResult->phstmt->iCatalogQuery)
{
// Make the catalog name upper case
_strupr(pDescRec->szTableName);
}
}
else
pDescRec->szTableName[0] = '\0';
case_sensitive = PQfcase_sensitive(pgResult, col);
pDescRec->cCaseSensitive = getCaseSensitive(pDescRec->hType, pDescRec->hRsSpecialType, case_sensitive);
pDescRec->iDisplaySize = getDisplaySize(pDescRec->hType, pDescRec->iSize, pDescRec->hRsSpecialType);
pDescRec->cFixedPrecScale = SQL_FALSE;
getLiteralPrefix(pDescRec->hType, pDescRec->szLiteralPrefix, pDescRec->hRsSpecialType);
getLiteralSuffix(pDescRec->hType, pDescRec->szLiteralSuffix, pDescRec->hRsSpecialType);
getTypeName(pDescRec->hType, pDescRec->szTypeName, sizeof(pDescRec->szTypeName), pDescRec->hRsSpecialType);
pDescRec->iNumPrecRadix = getNumPrecRadix(pDescRec->hType);
pDescRec->iOctetLen = getOctetLen(pDescRec->hType, pDescRec->iSize, pDescRec->hRsSpecialType);
pDescRec->iPrecision = getPrecision(pDescRec->hType, pDescRec->iSize, pDescRec->hRsSpecialType);
pDescRec->iSearchable = getSearchable(pDescRec->hType, pDescRec->hRsSpecialType);
pDescRec->iUnNamed = getUnNamed(pDescRec->szName);
pDescRec->cUnsigned = getUnsigned(pDescRec->hType);
pDescRec->iUpdatable = getUpdatable();
} // Col loop
}