static void getResultDescription()

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
}