Пример #1
0
QSqlRecord QPSQLResult::record() const
{
    QSqlRecord info;
    if (!isActive() || !isSelect())
        return info;

    int count = PQnfields(d->result);
    for (int i = 0; i < count; ++i) {
        QSqlField f;
        if (d->driver->isUtf8)
            f.setName(QString::fromUtf8(PQfname(d->result, i)));
        else
            f.setName(QString::fromLocal8Bit(PQfname(d->result, i)));
        f.setType(qDecodePSQLType(PQftype(d->result, i)));
        int len = PQfsize(d->result, i);
        int precision = PQfmod(d->result, i);
        // swap length and precision if length == -1
        if (len == -1 && precision > -1) {
            len = precision - 4;
            precision = -1;
        }
        f.setLength(len);
        f.setPrecision(precision);
        f.setSqlType(PQftype(d->result, i));
        info.append(f);
    }
    return info;
}
Пример #2
0
//==================================================================================
//Create a cursor result set
bool PostgresqlCursor::drv_open(const KDbEscapedString& sql)
{
    d->res = d->executeSQL(sql);
    d->resultStatus = PQresultStatus(d->res);
    if (d->resultStatus != PGRES_TUPLES_OK && d->resultStatus != PGRES_COMMAND_OK) {
        storeResultAndClear(&d->res, d->resultStatus);
        return false;
    }
    m_fieldsToStoreInRecord = PQnfields(d->res);
    m_fieldCount = m_fieldsToStoreInRecord - (containsRecordIdInfo() ? 1 : 0);
    m_numRows = PQntuples(d->res);
    m_records_in_buf = m_numRows;
    m_buffering_completed = true;

    // get real types for all fields
    PostgresqlDriver* drv = static_cast<PostgresqlDriver*>(connection()->driver());

    m_realTypes.resize(m_fieldsToStoreInRecord);
    m_realLengths.resize(m_fieldsToStoreInRecord);
    for (int i = 0; i < int(m_fieldsToStoreInRecord); i++) {
        const int pqtype = PQftype(d->res, i);
        const int pqfmod = PQfmod(d->res, i);
        m_realTypes[i] = drv->pgsqlToKDbType(pqtype, pqfmod, &m_realLengths[i]);
    }
    return true;
}
Пример #3
0
static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno)
{
	pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
	struct pdo_column_data *cols = stmt->columns;
	struct pdo_bound_param_data *param;
	char *str;

	if (!S->result) {
		return 0;
	}

	str = PQfname(S->result, colno);
	cols[colno].name = zend_string_init(str, strlen(str), 0);
	cols[colno].maxlen = PQfsize(S->result, colno);
	cols[colno].precision = PQfmod(S->result, colno);
	S->cols[colno].pgsql_type = PQftype(S->result, colno);

	switch (S->cols[colno].pgsql_type) {

		case BOOLOID:
			cols[colno].param_type = PDO_PARAM_BOOL;
			break;

		case OIDOID:
			/* did the user bind the column as a LOB ? */
			if (stmt->bound_columns && (
					(param = zend_hash_index_find_ptr(stmt->bound_columns, colno)) != NULL ||
					(param = zend_hash_find_ptr(stmt->bound_columns, cols[colno].name)) != NULL)) {

				if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
					cols[colno].param_type = PDO_PARAM_LOB;
					break;
				}
			}
			cols[colno].param_type = PDO_PARAM_INT;
			break;

		case INT2OID:
		case INT4OID:
			cols[colno].param_type = PDO_PARAM_INT;
			break;

		case INT8OID:
			if (sizeof(zend_long)>=8) {
				cols[colno].param_type = PDO_PARAM_INT;
			} else {
				cols[colno].param_type = PDO_PARAM_STR;
			}
			break;

		case BYTEAOID:
			cols[colno].param_type = PDO_PARAM_LOB;
			break;

		default:
			cols[colno].param_type = PDO_PARAM_STR;
	}

	return 1;
}
Пример #4
0
/*
 *	Read in field descriptions from a libpq result set.
 *	If self is not null, then also store the information.
 *	If self is null, then just read, don't store.
 */
BOOL
CI_read_fields_from_pgres(ColumnInfoClass *self, PGresult *pgres)
{
	CSTR		func = "CI_read_fields";
	Int2		lf;
	int			new_num_fields;
	OID		new_adtid, new_relid = 0, new_attid = 0;
	Int2		new_adtsize;
	Int4		new_atttypmod = -1;
	char	   *new_field_name;

	/* at first read in the number of fields that are in the query */
	new_num_fields = PQnfields(pgres);

	mylog("num_fields = %d\n", new_num_fields);

	if (self)
	{
		/* according to that allocate memory */
		CI_set_num_fields(self, new_num_fields);
		if (NULL == self->coli_array)
			return FALSE;
	}

	/* now read in the descriptions */
	for (lf = 0; lf < new_num_fields; lf++)
	{
		new_field_name = PQfname(pgres, lf);
		new_relid = PQftable(pgres, lf);
		new_attid = PQftablecol(pgres, lf);
		new_adtid = PQftype(pgres, lf);
		new_adtsize = PQfsize(pgres, lf);

		mylog("READING ATTTYPMOD\n");
		new_atttypmod = PQfmod(pgres, lf);

		/* Subtract the header length */
		switch (new_adtid)
		{
			case PG_TYPE_DATETIME:
			case PG_TYPE_TIMESTAMP_NO_TMZONE:
			case PG_TYPE_TIME:
			case PG_TYPE_TIME_WITH_TMZONE:
				break;
			default:
				new_atttypmod -= 4;
		}
		if (new_atttypmod < 0)
			new_atttypmod = -1;

		mylog("%s: fieldname='%s', adtid=%d, adtsize=%d, atttypmod=%d (rel,att)=(%d,%d)\n", func, new_field_name, new_adtid, new_adtsize, new_atttypmod, new_relid, new_attid);

		if (self)
			CI_set_field_info(self, lf, new_field_name, new_adtid, new_adtsize, new_atttypmod, new_relid, new_attid);
	}

	return TRUE;
}
Пример #5
0
/*
 * call-seq:
 *    res.fmod( column_number )
 *
 * Returns the type modifier associated with column _column_number_. See
 * the #ftype method for an example of how to use this.
 *
 * Raises an ArgumentError if _column_number_ is out of range.
 */
static VALUE
pgresult_fmod(VALUE self, VALUE column_number)
{
	PGresult *result = pgresult_get(self);
	int fnumber = NUM2INT(column_number);
	int modifier;
	if (fnumber < 0 || fnumber >= PQnfields(result)) {
		rb_raise(rb_eArgError, "Column number is out of range: %d",
			fnumber);
	}
	modifier = PQfmod(result,fnumber);

	return INT2NUM(modifier);
}
Пример #6
0
/*
** Get the internal database type of the given column.
*/
static char *getcolumntype (PGconn *conn, PGresult *result, int i, char *buff) {
	Oid codigo = PQftype (result, i);
	char stmt[100];
	PGresult *res;

	sprintf (stmt, "select typname from pg_type where oid = %d", codigo);
	res = PQexec(conn, stmt);
	strcpy (buff, "undefined");

	if (PQresultStatus (res) == PGRES_TUPLES_OK) {
		if (PQntuples(res) > 0) {
			char *name = PQgetvalue(res, 0, 0);
			if (strcmp (name, "bpchar")==0 || strcmp (name, "varchar")==0) {
				int modifier = PQfmod (result, i) - 4;
				sprintf (buff, "%.20s (%d)", name, modifier);
			}
			else
				strncpy (buff, name, 20);
		}
	}
	PQclear(res);
	return buff;
}
Пример #7
0
RS_DBI_fields *
RS_PostgreSQL_createDataMappings(Res_Handle * rsHandle)
{
    PGresult *my_result;

    RS_DBI_connection *con;
    RS_DBI_resultSet *result;
    RS_DBI_fields *flds;

    int j, num_fields, internal_type;
    char errMsg[128];

    result = RS_DBI_getResultSet(rsHandle);
    my_result = (PGresult *) result->drvResultSet;

    con = RS_DBI_getConnection(rsHandle);
    num_fields = PQnfields(my_result);

    flds = RS_DBI_allocFields(num_fields); /* this returns malloced data (not from R) */

    char buff[1000];            /* Buffer to hold the sql query to check whether the given column is nullable */
    PGconn *conn;
    PGresult *res;
    conn = (PGconn *) con->drvConnection;

    for (j = 0; j < num_fields; j++) {

        flds->name[j] = RS_DBI_copyString(PQfname(my_result, j));

        flds->type[j] = (int) PQftype(my_result, j);

        flds->length[j] = (Sint) PQfsize(my_result, j);

        /* NOTE: PQfmod is -1 incase of no information */
        flds->precision[j] = (Sint) PQfmod(my_result, j);

        flds->scale[j] = (Sint) - 1;

        /* PQftablecol returns the column number (within its table) of
         * the column making up the specified query result column.Zero
         * is returned if the column number is out of range, or if the
         * specified column is not a simple reference to a table
         * column, or when using pre-3.0 protocol. So
         * "if(PQftablecol(my_result,j) !=0)" checks whether the
         * particular colomn in the result set is column of table or
         * not. Or else there is no meaning in checking whether a
         * column is nullable or not if it does not belong to the
         * table.
         */

        flds->nullOk[j] = (Sint) INT_MIN; /* This should translate to NA in R */

        if (PQftablecol(my_result, j) != 0) {
            /* Code to find whether a row can be nullable or not */
            /* we might better just store the table id and column number
               for lazy evaluation at dbColumnInfo call*/
            /* although the database structure can change, we are not in transaction anyway
               and there is no guarantee in current code */
            snprintf(buff, 1000, "select attnotnull from pg_attribute where attrelid=%d and attnum='%d'",
                     PQftable(my_result, j), PQftablecol(my_result, j));
            res = PQexec(conn, buff);

            if (res && (PQntuples(res) > 0)) {
                const char * attnotnull = PQgetvalue(res, 0, 0);
                if(strcmp(attnotnull, "f") == 0) {
                    flds->nullOk[j] = (Sint) 1; /* nollOK is TRUE when attnotnull is f*/
                }
                if(strcmp(attnotnull, "t") == 0) {
                    flds->nullOk[j] = (Sint) 0; /* nollOK is FALSE when attnotnull is t*/
                }
            }
            PQclear(res);
        }

        internal_type = (int) PQftype(my_result, j);

        switch (internal_type) {
        case BOOLOID:
            flds->Sclass[j] = LOGICAL_TYPE;
            break;
        case BPCHAROID:
            flds->Sclass[j] = CHARACTER_TYPE;
            flds->isVarLength[j] = (Sint) 0;
            break;
        case VARCHAROID:
        case TEXTOID:
        case BYTEAOID:
        case NAMEOID:
        case MACADDROID:
        case INETOID:
            flds->Sclass[j] = CHARACTER_TYPE;
            flds->isVarLength[j] = (Sint) 1;
            break;
        case INT2OID:
        case INT4OID:
        case OIDOID:
            flds->Sclass[j] = INTEGER_TYPE;
            break;
        case INT8OID:
            if (sizeof(Sint) >= 8) {
                flds->Sclass[j] = INTEGER_TYPE;
            }
            else {
                flds->Sclass[j] = NUMERIC_TYPE;
            }
            break;
        case NUMERICOID:
        case FLOAT8OID:
        case FLOAT4OID:
            flds->Sclass[j] = NUMERIC_TYPE;
            break;
        case DATEOID:
        case TIMEOID:
        case TIMETZOID:
        case TIMESTAMPOID:
        case TIMESTAMPTZOID:
        case INTERVALOID:
            flds->Sclass[j] = CHARACTER_TYPE;
            /*flds->isVarLength[j] = (Sint) 1; */
            break;
        default:
            flds->Sclass[j] = CHARACTER_TYPE;
            flds->isVarLength[j] = (Sint) 1;
            snprintf(buff, 1000, "select typname, typcategory from pg_type where oid = %d", internal_type);
            res = PQexec(conn, buff);
            if (res) {
                char * typename;
                char * typecat;
                int ntuples;
                ntuples = PQntuples(res);
                if(ntuples == 1) {
                    typename = PQgetvalue(res, 0, 0);
                    typecat = PQgetvalue(res, 0, 1);
                    if(*typecat == 'E') { /* This is enum, ok */
                    } else if(*typecat == 'A') { /*This is array, ok */
                    } else {
                        snprintf(errMsg, 128, "unrecognized PostgreSQL field type %s (id:%d) in column %d", typename, internal_type, j);
                        RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
                    }
                } else {
                    snprintf(errMsg, 128, "oid: %d, ntuples: %d", internal_type, ntuples);
                    RS_DBI_errorMessage(errMsg, RS_DBI_WARNING);
                }
                PQclear(res);
            } else {
Пример #8
0
static HB_ERRCODE pgsqlOpen( SQLBASEAREAP pArea )
{
   PGconn *       pConn = ( ( SDDCONN * ) pArea->pConnection->pSDDConn )->pConn;
   SDDDATA *      pSDDData;
   PGresult *     pResult;
   ExecStatusType status;
   PHB_ITEM       pItemEof, pItem;
   HB_USHORT      uiFields, uiCount;
   HB_BOOL        bError;
   DBFIELDINFO    pFieldInfo;

   pArea->pSDDData = memset( hb_xgrab( sizeof( SDDDATA ) ), 0, sizeof( SDDDATA ) );
   pSDDData        = ( SDDDATA * ) pArea->pSDDData;

   pResult = PQexec( pConn, pArea->szQuery );
   if( ! pResult )
   {
      hb_errRT_PostgreSQLDD( EG_OPEN, ESQLDD_LOWMEMORY, "Query failed", NULL, 0 );  /* Low memory, etc */
      return HB_FAILURE;
   }

   status = PQresultStatus( pResult );
   if( status != PGRES_TUPLES_OK && status != PGRES_COMMAND_OK )
   {
      hb_errRT_PostgreSQLDD( EG_OPEN, ESQLDD_INVALIDQUERY, PQresultErrorMessage( pResult ), pArea->szQuery, ( HB_ERRCODE ) status );
      PQclear( pResult );
      return HB_FAILURE;
   }

   pSDDData->pResult = pResult;

   uiFields = ( HB_USHORT ) PQnfields( pResult );
   SELF_SETFIELDEXTENT( ( AREAP ) pArea, uiFields );

   pItemEof = hb_itemArrayNew( uiFields );
   pItem    = hb_itemNew( NULL );

   bError = HB_FALSE;
   for( uiCount = 0; uiCount < uiFields; uiCount++ )
   {
      pFieldInfo.atomName = PQfname( pResult, ( int ) uiCount );
      pFieldInfo.uiDec    = 0;

      switch( PQftype( pResult, ( int ) uiCount ) )
      {
         case BPCHAROID:
         case VARCHAROID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = ( HB_USHORT ) PQfmod( pResult, uiCount ) - 4;
            break;

         case TEXTOID:
            pFieldInfo.uiType = HB_FT_MEMO;
            pFieldInfo.uiLen  = 10;
            break;

         case NUMERICOID:
            pFieldInfo.uiType = HB_FT_DOUBLE;
            pFieldInfo.uiLen  = ( PQfmod( pResult, uiCount ) - 4 ) >> 16;
            pFieldInfo.uiDec  = ( PQfmod( pResult, uiCount ) - 4 ) & 0xFFFF;
            break;

         case INT2OID:
            pFieldInfo.uiType = HB_FT_INTEGER;
            pFieldInfo.uiLen  = 6;
            break;

         case INT4OID:
            pFieldInfo.uiType = HB_FT_INTEGER;
            pFieldInfo.uiLen  = 11;
            break;

         case INT8OID:
         case OIDOID:
            pFieldInfo.uiType = HB_FT_LONG;
            pFieldInfo.uiLen  = 20;
            break;

         case FLOAT4OID:
         case FLOAT8OID:
         case CASHOID:  /* TODO: ??? */
            pFieldInfo.uiType = HB_FT_DOUBLE;
            pFieldInfo.uiLen  = 16;
            pFieldInfo.uiDec  = 2;   /* TODO: hb_set.SET_DECIMALS ??? */
            break;

         case BOOLOID:
            pFieldInfo.uiType = HB_FT_LOGICAL;
            pFieldInfo.uiLen  = 1;
            break;

         case DATEOID:
            pFieldInfo.uiType = HB_FT_DATE;
            pFieldInfo.uiLen  = 8;
            break;

         case INETOID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = 29;
            break;

         case CIDROID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = 32;
            break;

         case MACADDROID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = 17;
            break;

         case BITOID:
         case VARBITOID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = ( HB_USHORT ) PQfsize( pResult, uiCount );
            break;

         case TIMEOID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = 12;
            break;

         case TIMESTAMPOID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = 23;
            break;

         case TIMETZOID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = 15;
            break;

         case TIMESTAMPTZOID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = 26;
            break;

         case NAMEOID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = 63;
            break;

         case BYTEAOID:
            pFieldInfo.uiType = HB_FT_STRING;
            pFieldInfo.uiLen  = 0;
            break;

         default:
            pFieldInfo.uiType = 0;
            pFieldInfo.uiLen  = 0;
            bError = HB_TRUE;
            break;
      }
      /* printf( "field:%s \ttype:%d \tsize:%d \tformat:%d \tmod:%d err=%d\n", pFieldInfo.atomName, PQftype( pResult, ( int ) uiCount ), PQfsize( pResult, uiCount ), PQfformat( pResult, uiCount ) , PQfmod( pResult, uiCount ), bError ); */

      if( ! bError )
      {
         switch( pFieldInfo.uiType )
         {
            case HB_FT_STRING:
            {
               char * pStr;

               pStr = ( char * ) hb_xgrab( pFieldInfo.uiLen + 1 );
               memset( pStr, ' ', pFieldInfo.uiLen );
               pStr[ pFieldInfo.uiLen ] = '\0';

               hb_itemPutCL( pItem, pStr, pFieldInfo.uiLen );
               hb_xfree( pStr );
               break;
            }
            case HB_FT_MEMO:
               hb_itemPutC( pItem, NULL );
               hb_itemSetCMemo( pItem );
               break;

            case HB_FT_INTEGER:
               hb_itemPutNI( pItem, 0 );
               break;

            case HB_FT_LONG:
               hb_itemPutNL( pItem, 0 );
               break;

            case HB_FT_DOUBLE:
               hb_itemPutND( pItem, 0.0 );
               break;

            case HB_FT_LOGICAL:
               hb_itemPutL( pItem, HB_FALSE );
               break;

            case HB_FT_DATE:
               hb_itemPutDS( pItem, NULL );
               break;

            default:
               hb_itemClear( pItem );
               bError = HB_TRUE;
               break;
         }

         hb_arraySetForward( pItemEof, uiCount + 1, pItem );

/*       if( pFieldInfo.uiType == HB_IT_DOUBLE || pFieldInfo.uiType == HB_IT_INTEGER )
            pFieldInfo.uiType = HB_IT_LONG;
 */

         if( ! bError )
            bError = ( SELF_ADDFIELD( ( AREAP ) pArea, &pFieldInfo ) == HB_FAILURE );
      }

      if( bError )
         break;
   }

   hb_itemRelease( pItem );

   if( bError )
   {
      hb_itemClear( pItemEof );
      hb_itemRelease( pItemEof );
      hb_errRT_PostgreSQLDD( EG_CORRUPTION, ESQLDD_INVALIDFIELD, "Invalid field type", pArea->szQuery, 0 );
      return HB_FAILURE;
   }

   pArea->ulRecCount = ( HB_ULONG ) PQntuples( pResult );

   pArea->pRow      = ( void ** ) hb_xgrab( ( pArea->ulRecCount + 1 ) * sizeof( void * ) );
   pArea->pRowFlags = ( HB_BYTE * ) hb_xgrab( ( pArea->ulRecCount + 1 ) * sizeof( HB_BYTE ) );
   memset( pArea->pRowFlags, 0, ( pArea->ulRecCount + 1 ) * sizeof( HB_BYTE ) );

   *pArea->pRow = pItemEof;
   pArea->pRowFlags[ 0 ] = SQLDD_FLAG_CACHED;
   pArea->fFetched       = HB_TRUE;

   return HB_SUCCESS;
}
Пример #9
0
OGRFeatureDefn *OGRPGResultLayer::ReadResultDefinition(PGresult *hInitialResultIn)

{
    PGresult            *hResult = hInitialResultIn;

/* -------------------------------------------------------------------- */
/*      Parse the returned table information.                           */
/* -------------------------------------------------------------------- */
    OGRFeatureDefn *poDefn = new OGRFeatureDefn( "sql_statement" );
    int            iRawField;

    poDefn->Reference();

    for( iRawField = 0; iRawField < PQnfields(hResult); iRawField++ )
    {
        OGRFieldDefn    oField( PQfname(hResult,iRawField), OFTString);
        Oid             nTypeOID;

        nTypeOID = PQftype(hResult,iRawField);
        
        if( EQUAL(oField.GetNameRef(),"ogc_fid") )
        {
            bHasFid = TRUE;
            pszFIDColumn = CPLStrdup(oField.GetNameRef());
            continue;
        }
        else if( nTypeOID == poDS->GetGeometryOID()  ||
                 nTypeOID == poDS->GetGeographyOID()  ||
                 EQUAL(oField.GetNameRef(),"ST_AsText") ||
                 EQUAL(oField.GetNameRef(),"ST_AsBinary") ||
                 EQUAL(oField.GetNameRef(),"AsBinary") ||
                 EQUAL(oField.GetNameRef(),"asEWKT") ||
                 EQUAL(oField.GetNameRef(),"asText") )
        {
            if (bHasPostGISGeometry || bHasPostGISGeography )
            {
                CPLError(CE_Warning, CPLE_AppDefined,
                         "More than one geometry column was found in the result of the SQL request. Only last one will be used");
            }
            if (nTypeOID == poDS->GetGeographyOID())
                bHasPostGISGeography = TRUE;
            else
                bHasPostGISGeometry = TRUE;
            CPLFree(pszGeomColumn);
            pszGeomColumn = CPLStrdup(oField.GetNameRef());
            continue;
        }
        else if( EQUAL(oField.GetNameRef(),"WKB_GEOMETRY") )
        {
            bHasWkb = TRUE;
            if( nTypeOID == OIDOID )
                bWkbAsOid = TRUE;
            continue;
        }

        if( nTypeOID == BYTEAOID )
        {
            oField.SetType( OFTBinary );
        }
        else if( nTypeOID == CHAROID ||
                 nTypeOID == TEXTOID ||
                 nTypeOID == BPCHAROID ||
                 nTypeOID == VARCHAROID )
        {
            oField.SetType( OFTString );

            /* See http://www.mail-archive.com/[email protected]/msg57726.html */
            /* nTypmod = width + 4 */
            int nTypmod = PQfmod(hResult, iRawField);
            if (nTypmod >= 4 && (nTypeOID == BPCHAROID ||
                               nTypeOID == VARCHAROID ) )
            {
                oField.SetWidth( nTypmod - 4);
            }
        }
        else if( nTypeOID == BOOLOID )
        {
            oField.SetType( OFTInteger );
            oField.SetWidth( 1 );
        }
        else if (nTypeOID == INT2OID )
        {
            oField.SetType( OFTInteger );
            oField.SetWidth( 5 );
        }
        else if (nTypeOID == INT4OID )
        {
            oField.SetType( OFTInteger );
        }
        else if ( nTypeOID == INT8OID )
        {
            /* FIXME: OFTInteger can not handle 64bit integers */
            oField.SetType( OFTInteger );
        }
        else if( nTypeOID == FLOAT4OID ||
                 nTypeOID == FLOAT8OID )
        {
            oField.SetType( OFTReal );
        }
        else if( nTypeOID == NUMERICOID )
        {
            /* See http://www.mail-archive.com/[email protected]/msg57726.html */
            /* typmod = (width << 16) + precision + 4 */
            int nTypmod = PQfmod(hResult, iRawField);
            if (nTypmod >= 4)
            {
                int nWidth = (nTypmod - 4) >> 16;
                int nPrecision = (nTypmod - 4) & 0xFFFF;
                if (nWidth <= 10 && nPrecision == 0)
                {
                    oField.SetType( OFTInteger );
                    oField.SetWidth( nWidth );
                }
                else
                {
                    oField.SetType( OFTReal );
                    oField.SetWidth( nWidth );
                    oField.SetPrecision( nPrecision );
                }
            }
            else
Пример #10
0
int get_column_info(PGresult * res, int col, int *pgtype, int *gpgtype,
		    int *sqltype, int *size)
{
    *pgtype = (int)PQftype(res, col);
    *gpgtype = get_gpg_type(*pgtype);

    /* Convert internal type to PG_TYPE_* */

    /* TODO: we should load field names from pg_type table
       instead of using copy of #defines */
    switch (*gpgtype) {
    case PG_TYPE_BIT:
    case PG_TYPE_INT2:
    case PG_TYPE_INT4:
    case PG_TYPE_INT8:
    case PG_TYPE_SERIAL:
    case PG_TYPE_OID:
	*sqltype = DB_SQL_TYPE_INTEGER;
	*size = PQfsize(res, col);
	break;

    case PG_TYPE_CHAR:
    case PG_TYPE_BPCHAR:
    case PG_TYPE_VARCHAR:
	*sqltype = DB_SQL_TYPE_CHARACTER;
	*size = PQfmod(res, col) - 4;	/* Looks strange but works, something better? */
	break;

    case PG_TYPE_TEXT:
	*sqltype = DB_SQL_TYPE_TEXT;
	break;

    case PG_TYPE_FLOAT4:
    case PG_TYPE_FLOAT8:
    case PG_TYPE_NUMERIC:
	*sqltype = DB_SQL_TYPE_DOUBLE_PRECISION;
	*size = PQfsize(res, col);
	break;

	/* I'm not sure if text length is correct for size */
    case PG_TYPE_DATE:
	*sqltype = DB_SQL_TYPE_DATE;
	*size = 10;		/* YYYY-MM-DD */
	break;

    case PG_TYPE_TIME:
	*sqltype = DB_SQL_TYPE_TIME;
	*size = 8;		/* HH:MM:SS */
	break;

    case PG_TYPE_TIMESTAMP:
	*sqltype = DB_SQL_TYPE_TIMESTAMP;
	*size = 22;		/* YYYY-MM-DD HH:MM:SS+TZ */
	break;

    case PG_TYPE_BOOL:
	*sqltype = DB_SQL_TYPE_CHARACTER;
	*size = 1;
	break;

    default:
	*sqltype = DB_SQL_TYPE_UNKNOWN;
	*size = 0;
    }

    return 0;
}
Пример #11
0
int pg_createrowset(ClipMachine* mp,SQLROWSET* rs,ClipVar* ap,ClipVar* idname,const char* gen_idSQL){
	PG_ROWSET* rowset = (PG_ROWSET*)rs;
	PG_STMT* stmt = rowset->stmt;
	PG_CONN* conn = rowset->conn;
	int i,mod;

	pg_bindpars(stmt,ap);
	if(!stmt->sql){
		_clip_trap_err(mp,0,0,0,subsys,ER_NOSQL,er_nosql);
		return 1;
	}

	stmt->res = PQexec(conn->conn,stmt->sql);
	if(!stmt->res){
		_clip_trap_err(mp,0,0,0,subsys,ER_BADSTATEMENT,
			PQresultErrorMessage(stmt->res));
		return 1;
	}
	if(PQresultStatus(stmt->res)!=PGRES_TUPLES_OK){
		_clip_trap_err(mp,0,0,0,subsys,ER_BADSELECT,
			PQresultErrorMessage(stmt->res));
		return 1;
	}

	rowset->rowset_item =
		_clip_store_c_item(mp,rowset,_C_ITEM_TYPE_SQL,destroy_pg_rowset);

	rowset->binary = PQbinaryTuples(stmt->res);
	rowset->nfields = PQnfields(stmt->res);
	rowset->fields = calloc(1,rowset->nfields*sizeof(SQLFIELD));
	rowset->id = -1;
	for(i=0;i<rowset->nfields;i++){
		strncpy(rowset->fields[i].name,PQfname(stmt->res,i),
			MAXFIELDNAME);
		rowset->fields[i].name[MAXFIELDNAME] = 0;
		rowset->fields[i].type = PQftype(stmt->res,i);
		rowset->fields[i].ctype[0] = _pg_ctype(rowset->fields[i].type);
		rowset->fields[i].dec = 0;
		mod = PQfmod(stmt->res,i);
		switch(rowset->fields[i].type){
			case PGT_BPCHAR:
			case PGT_CHAR:
			case PGT_VARCHAR:
				rowset->fields[i].len = mod-4;
				break;
			case PGT_TEXT:
				rowset->fields[i].len = 10;
				break;
			case PGT_NUMERIC:
				rowset->fields[i].len = (mod >> 16);
				rowset->fields[i].dec = (mod & 0xffff)-4;
				break;
			case PGT_DATE:
				rowset->fields[i].len = 8;
				break;
			default:
				rowset->fields[i].len = PQfsize(stmt->res,i);
				break;
		}
		rowset->fields[i].ops = 0;
		if(idname && idname->t.type == CHARACTER_t && idname->s.str.buf){
			if(!strcasecmp(rowset->fields[i].name,idname->s.str.buf)){
				rowset->id = i;
			}
		} else if(rowset->fields[i].type == PGT_OID){
			rowset->id = i;
		}
	}

	rowset->lastrec = PQntuples(stmt->res);
	rowset->data = calloc(rowset->lastrec,sizeof(void*));
	return 0;
}