Int4 pgtype_desclength(StatementClass *stmt, OID type, int col, int handle_unknown_size_as) { switch (type) { case PG_TYPE_INT2: return 2; case PG_TYPE_OID: case PG_TYPE_XID: case PG_TYPE_INT4: return 4; case PG_TYPE_INT8: return 20; /* signed: 19 digits + sign */ case PG_TYPE_NUMERIC: return getNumericColumnSize(stmt, type, col) + 2; case PG_TYPE_FLOAT4: case PG_TYPE_MONEY: return 4; case PG_TYPE_FLOAT8: return 8; case PG_TYPE_DATE: case PG_TYPE_TIME: case PG_TYPE_ABSTIME: case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP_NO_TMZONE: case PG_TYPE_TIMESTAMP: case PG_TYPE_VARCHAR: case PG_TYPE_BPCHAR: return pgtype_column_size(stmt, type, col, handle_unknown_size_as); default: return pgtype_column_size(stmt, type, col, handle_unknown_size_as); } }
Int4 pgtype_display_size(StatementClass *stmt, OID type, int col, int handle_unknown_size_as) { int dsize; switch (type) { case PG_TYPE_INT2: return 6; case PG_TYPE_OID: case PG_TYPE_XID: return 10; case PG_TYPE_INT4: return 11; case PG_TYPE_INT8: return 20; /* signed: 19 digits + sign */ case PG_TYPE_NUMERIC: dsize = getNumericColumnSize(stmt, type, col); return dsize < 0 ? dsize : dsize + 2; case PG_TYPE_MONEY: return 15; /* ($9,999,999.99) */ case PG_TYPE_FLOAT4: return 13; case PG_TYPE_FLOAT8: return 22; #if (ODBCVER >= 0x0350) case PG_TYPE_UUID: return 36; #endif /* ODBCVER */ /* Character types use regular precision */ default: return pgtype_column_size(stmt, type, col, handle_unknown_size_as); } }
/* * Transfer octet length. */ Int4 pgtype_transfer_octet_length(StatementClass *stmt, OID type, int col, int handle_unknown_size_as) { ConnectionClass *conn = SC_get_conn(stmt); int coef = 1; Int4 prec = pgtype_column_size(stmt, type, col, handle_unknown_size_as), maxvarc; switch (type) { case PG_TYPE_VARCHAR: case PG_TYPE_BPCHAR: case PG_TYPE_TEXT: if (SQL_NO_TOTAL == prec) return prec; #ifdef UNICODE_SUPPORT if (CC_is_in_unicode_driver(conn)) return prec * WCLEN; #endif /* UNICODE_SUPPORT */ /* after 7.2 */ if (PG_VERSION_GE(conn, 7.2)) coef = conn->mb_maxbyte_per_char; if (coef < 2 && (conn->connInfo).lf_conversion) /* CR -> CR/LF */ coef = 2; if (coef == 1) return prec; maxvarc = conn->connInfo.drivers.max_varchar_size; if (prec <= maxvarc && prec * coef > maxvarc) return maxvarc; return coef * prec; case PG_TYPE_BYTEA: return prec; default: if (type == conn->lobj_type) return prec; } return -1; }
/* * The length in bytes of data transferred on an SQLGetData, SQLFetch, * or SQLFetchScroll operation if SQL_C_DEFAULT is specified. */ Int4 pgtype_buffer_length(StatementClass *stmt, OID type, int col, int handle_unknown_size_as) { ConnectionClass *conn = SC_get_conn(stmt); switch (type) { case PG_TYPE_INT2: return 2; /* sizeof(SQLSMALLINT) */ case PG_TYPE_OID: case PG_TYPE_XID: case PG_TYPE_INT4: return 4; /* sizeof(SQLINTEGER) */ case PG_TYPE_INT8: if (SQL_C_CHAR == pgtype_to_ctype(stmt, type)) return 20; /* signed: 19 digits + sign */ return 8; /* sizeof(SQLSBININT) */ case PG_TYPE_NUMERIC: return getNumericColumnSize(stmt, type, col) + 2; case PG_TYPE_FLOAT4: case PG_TYPE_MONEY: return 4; /* sizeof(SQLREAL) */ case PG_TYPE_FLOAT8: return 8; /* sizeof(SQLFLOAT) */ case PG_TYPE_DATE: case PG_TYPE_TIME: return 6; /* sizeof(DATE(TIME)_STRUCT) */ case PG_TYPE_ABSTIME: case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP: case PG_TYPE_TIMESTAMP_NO_TMZONE: return 16; /* sizeof(TIMESTAMP_STRUCT) */ case PG_TYPE_UUID: return 16; /* sizeof(SQLGUID) */ /* Character types use the default precision */ case PG_TYPE_VARCHAR: case PG_TYPE_BPCHAR: { int coef = 1; Int4 prec = pgtype_column_size(stmt, type, col, handle_unknown_size_as), maxvarc; if (SQL_NO_TOTAL == prec) return prec; #ifdef UNICODE_SUPPORT if (CC_is_in_unicode_driver(conn)) return prec * WCLEN; #endif /* UNICODE_SUPPORT */ /* after 7.2 */ if (PG_VERSION_GE(conn, 7.2)) coef = conn->mb_maxbyte_per_char; if (coef < 2 && (conn->connInfo).lf_conversion) /* CR -> CR/LF */ coef = 2; if (coef == 1) return prec; maxvarc = conn->connInfo.drivers.max_varchar_size; if (prec <= maxvarc && prec * coef > maxvarc) return maxvarc; return coef * prec; } default: return pgtype_column_size(stmt, type, col, handle_unknown_size_as); } }
/* * Returns the description of a parameter marker. * This function is listed as not being supported by SQLGetFunctions() because it is * used to describe "parameter markers" (not bound parameters), in which case, * the dbms should return info on the markers. Since Postgres doesn't support that, * it is best to say this function is not supported and let the application assume a * data type (most likely varchar). */ RETCODE SQL_API PGAPI_DescribeParam(HSTMT hstmt, SQLUSMALLINT ipar, SQLSMALLINT FAR * pfSqlType, SQLULEN FAR * pcbParamDef, SQLSMALLINT FAR * pibScale, SQLSMALLINT FAR * pfNullable) { StatementClass *stmt = (StatementClass *) hstmt; CSTR func = "PGAPI_DescribeParam"; IPDFields *ipdopts; RETCODE ret = SQL_SUCCESS; int num_params; OID pgtype; mylog("%s: entering...%d\n", func, ipar); if (!stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } SC_clear_error(stmt); ipdopts = SC_get_IPDF(stmt); /*if ((ipar < 1) || (ipar > ipdopts->allocated))*/ num_params = stmt->num_params; if (num_params < 0) { SQLSMALLINT num_p; PGAPI_NumParams(stmt, &num_p); num_params = num_p; } if ((ipar < 1) || (ipar > num_params)) { inolog("num_params=%d\n", stmt->num_params); SC_set_error(stmt, STMT_BAD_PARAMETER_NUMBER_ERROR, "Invalid parameter number for PGAPI_DescribeParam.", func); return SQL_ERROR; } extend_iparameter_bindings(ipdopts, stmt->num_params); #define return DONT_CALL_RETURN_FROM_HERE??? /* StartRollbackState(stmt); */ if (NOT_YET_PREPARED == stmt->prepared) { decideHowToPrepare(stmt, FALSE); inolog("howTo=%d\n", SC_get_prepare_method(stmt)); switch (SC_get_prepare_method(stmt)) { case NAMED_PARSE_REQUEST: case PARSE_TO_EXEC_ONCE: case PARSE_REQ_FOR_INFO: if (ret = prepareParameters(stmt), SQL_ERROR == ret) goto cleanup; } } ipar--; pgtype = PIC_get_pgtype(ipdopts->parameters[ipar]); /* * This implementation is not very good, since it is supposed to * describe */ /* parameter markers, not bound parameters. */ if (pfSqlType) { inolog("[%d].SQLType=%d .PGType=%d\n", ipar, ipdopts->parameters[ipar].SQLType, pgtype); if (ipdopts->parameters[ipar].SQLType) *pfSqlType = ipdopts->parameters[ipar].SQLType; else if (pgtype) *pfSqlType = pgtype_to_concise_type(stmt, pgtype, PG_STATIC); else { ret = SQL_ERROR; SC_set_error(stmt, STMT_EXEC_ERROR, "Unfortunatley couldn't get this paramater's info", func); goto cleanup; } } if (pcbParamDef) { *pcbParamDef = 0; if (ipdopts->parameters[ipar].SQLType) *pcbParamDef = ipdopts->parameters[ipar].column_size; if (0 == *pcbParamDef && pgtype) *pcbParamDef = pgtype_column_size(stmt, pgtype, PG_STATIC, PG_STATIC); } if (pibScale) { *pibScale = 0; if (ipdopts->parameters[ipar].SQLType) *pibScale = ipdopts->parameters[ipar].decimal_digits; else if (pgtype) *pibScale = pgtype_scale(stmt, pgtype, -1); } if (pfNullable) *pfNullable = pgtype_nullable(SC_get_conn(stmt), ipdopts->parameters[ipar].paramType); cleanup: #undef return if (stmt->internal) ret = DiscardStatementSvp(stmt, ret, FALSE); return ret; }