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; }
//================================================================================== //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; }
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; }
/* * 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; }
/* * 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); }
/* ** 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; }
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 {
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; }
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
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; }
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; }