RETCODE SQL_API SQLExecDirect(HSTMT StatementHandle, SQLCHAR *StatementText, SQLINTEGER TextLength) { CSTR func = "SQLExecDirect"; RETCODE ret; StatementClass *stmt = (StatementClass *) StatementHandle; UWORD flag = 0; mylog("[%s]", func); ENTER_STMT_CS(stmt); SC_clear_error(stmt); if (PG_VERSION_GE(SC_get_conn(stmt), 7.4)) flag |= PODBC_WITH_HOLD; if (SC_opencheck(stmt, func)) ret = SQL_ERROR; else { StartRollbackState(stmt); ret = PGAPI_ExecDirect(StatementHandle, StatementText, TextLength, flag); ret = DiscardStatementSvp(stmt, ret, FALSE); } LEAVE_STMT_CS(stmt); return ret; }
RETCODE SQL_API SQLExecDirectW(HSTMT StatementHandle, SQLWCHAR *StatementText, SQLINTEGER TextLength) { CSTR func = "SQLExecDirectW"; RETCODE ret; char *stxt; SQLLEN slen; StatementClass *stmt = (StatementClass *) StatementHandle; UWORD flag = 0; mylog("[%s]", func); stxt = ucs2_to_utf8(StatementText, TextLength, &slen, FALSE); ENTER_STMT_CS(stmt); SC_clear_error(stmt); if (PG_VERSION_GE(SC_get_conn(stmt), 7.4)) flag |= PODBC_WITH_HOLD; StartRollbackState(stmt); if (SC_opencheck(stmt, func)) ret = SQL_ERROR; else ret = PGAPI_ExecDirect(StatementHandle, stxt, (SQLINTEGER) slen, flag); ret = DiscardStatementSvp(stmt, ret, FALSE); LEAVE_STMT_CS(stmt); if (stxt) free(stxt); return ret; }
RETCODE SQL_API SQLExecute(HSTMT StatementHandle) { CSTR func = "SQLExecute"; RETCODE ret; StatementClass *stmt = (StatementClass *) StatementHandle; UWORD flag = 0; mylog("[%s]", func); ENTER_STMT_CS(stmt); SC_clear_error(stmt); if (PG_VERSION_GE(SC_get_conn(stmt), 7.4)) flag |= PODBC_WITH_HOLD; if (SC_opencheck(stmt, func)) ret = SQL_ERROR; else { StartRollbackState(stmt); stmt->exec_current_row = -1; ret = PGAPI_Execute(StatementHandle, flag); ret = DiscardStatementSvp(stmt, ret, FALSE); } LEAVE_STMT_CS(stmt); return ret; }
/* * Transfer octet length. */ Int4 pgtype_transfer_octet_length(StatementClass *stmt, OID type, int column_size) { ConnectionClass *conn = SC_get_conn(stmt); int coef = 1; Int4 maxvarc; switch (type) { case PG_TYPE_VARCHAR: case PG_TYPE_BPCHAR: case PG_TYPE_TEXT: if (SQL_NO_TOTAL == column_size) return column_size; #ifdef UNICODE_SUPPORT if (CC_is_in_unicode_driver(conn)) return column_size * 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 column_size; maxvarc = conn->connInfo.drivers.max_varchar_size; if (column_size <= maxvarc && column_size * coef > maxvarc) return maxvarc; return coef * column_size; case PG_TYPE_BYTEA: return column_size; default: if (type == conn->lobj_type) return column_size; } return -1; }
int StartRollbackState(StatementClass *stmt) { CSTR func = "StartRollbackState"; int ret; ConnectionClass *conn; ConnInfo *ci = NULL; inolog("%s:%p->internal=%d\n", func, stmt, stmt->internal); conn = SC_get_conn(stmt); if (conn) ci = &conn->connInfo; ret = 0; if (!ci || ci->rollback_on_error < 0) /* default */ { if (conn && PG_VERSION_GE(conn, 8.0)) ret = 2; /* statement rollback */ else ret = 1; /* transaction rollback */ } else { ret = ci->rollback_on_error; if (2 == ret && PG_VERSION_LT(conn, 8.0)) ret = 1; } switch (ret) { case 1: SC_start_tc_stmt(stmt); break; case 2: SC_start_rb_stmt(stmt); break; } return ret; }
void SC_setInsertedTable(StatementClass *stmt, RETCODE retval) { const char *cmd = stmt->statement, *ptr; ConnectionClass *conn; size_t len; if (STMT_TYPE_INSERT != stmt->statement_type) return; if (SQL_NEED_DATA == retval) return; conn = SC_get_conn(stmt); #ifdef NOT_USED /* give up the use of lastval() */ if (PG_VERSION_GE(conn, 8.1)) /* lastval() is available */ return; #endif /* NOT_USED */ /*if (!CC_fake_mss(conn)) return;*/ while (isspace((UCHAR) *cmd)) cmd++; if (!*cmd) return; len = 6; if (strnicmp(cmd, "insert", len)) return; cmd += len; while (isspace((UCHAR) *(++cmd))); if (!*cmd) return; len = 4; if (strnicmp(cmd, "into", len)) return; cmd += len; while (isspace((UCHAR) *(++cmd))); if (!*cmd) return; NULL_THE_NAME(conn->schemaIns); NULL_THE_NAME(conn->tableIns); if (!SQL_SUCCEEDED(retval)) return; ptr = NULL; if (IDENTIFIER_QUOTE == *cmd) { if (ptr = strchr(cmd + 1, IDENTIFIER_QUOTE), NULL == ptr) return; if ('.' == ptr[1]) { len = ptr - cmd - 1; STRN_TO_NAME(conn->schemaIns, cmd + 1, len); cmd = ptr + 2; ptr = NULL; } } else { if (ptr = strchr(cmd + 1, '.'), NULL != ptr) { len = ptr - cmd; STRN_TO_NAME(conn->schemaIns, cmd, len); cmd = ptr + 1; ptr = NULL; } } if (IDENTIFIER_QUOTE == *cmd && NULL == ptr) { if (ptr = strchr(cmd + 1, IDENTIFIER_QUOTE), NULL == ptr) return; } if (IDENTIFIER_QUOTE == *cmd) { len = ptr - cmd - 1; STRN_TO_NAME(conn->tableIns, cmd + 1, len); } else { ptr = cmd; while (*ptr && !isspace((UCHAR) *ptr)) ptr++; len = ptr - cmd; STRN_TO_NAME(conn->tableIns, cmd, len); } }
/* * Must be in a transaction or the subsequent execution * invokes a transaction. */ RETCODE SetStatementSvp(StatementClass *stmt) { CSTR func = "SetStatementSvp"; char esavepoint[32], cmd[64]; ConnectionClass *conn = SC_get_conn(stmt); QResultClass *res; RETCODE ret = SQL_SUCCESS_WITH_INFO; if (CC_is_in_error_trans(conn)) return ret; if (0 == stmt->lock_CC_for_rb) { ENTER_CONN_CS(conn); stmt->lock_CC_for_rb++; } switch (stmt->statement_type) { case STMT_TYPE_SPECIAL: case STMT_TYPE_TRANSACTION: return ret; } if (!SC_accessed_db(stmt)) { BOOL need_savep = FALSE; if (stmt->internal) { if (PG_VERSION_GE(conn, 8.0)) SC_start_rb_stmt(stmt); else SC_start_tc_stmt(stmt); } if (SC_is_rb_stmt(stmt)) { if (CC_is_in_trans(conn)) { need_savep = TRUE; } } if (need_savep) { sprintf(esavepoint, "_EXEC_SVP_%p", stmt); snprintf(cmd, sizeof(cmd), "SAVEPOINT %s", esavepoint); res = CC_send_query(conn, cmd, NULL, 0, NULL); if (QR_command_maybe_successful(res)) { SC_set_accessed_db(stmt); SC_start_rbpoint(stmt); ret = SQL_SUCCESS; } else { SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal SAVEPOINT failed", func); ret = SQL_ERROR; } QR_Destructor(res); } else SC_set_accessed_db(stmt); } inolog("%s:%p->accessed=%d\n", func, stmt, SC_accessed_db(stmt)); return ret; }
/* * This function works under Windows or Unicode case only. * Simply returns NULL under other OSs. */ const char * get_environment_encoding(const ConnectionClass *conn, const char *setenc, const char *currenc, BOOL bStartup) { const char *wenc = NULL; #ifdef WIN32 int acp; #endif /* WIN32 */ #ifdef UNICODE_SUPPORT if (CC_is_in_unicode_driver(conn)) return "UTF8"; #endif /* UNICODE_SUPPORT */ if (setenc && stricmp(setenc, OTHER_STRING)) return setenc; #ifdef WIN32 acp = GetACP(); if (acp >= 1251 && acp <= 1258) { if (bStartup || stricmp(currenc, "SQL_ASCII") == 0) return wenc; } switch (acp) { case 932: wenc = "SJIS"; break; case 936: if (!bStartup && PG_VERSION_GT(conn, 7.2)) wenc = "GBK"; break; case 949: if (!bStartup && PG_VERSION_GT(conn, 7.2)) wenc = "UHC"; break; case 950: wenc = "BIG5"; break; case 1250: wenc = "WIN1250"; break; case 1251: wenc = "WIN1251"; break; case 1256: if (PG_VERSION_GE(conn, 7.3)) wenc = "WIN1256"; break; case 1252: if (strnicmp(currenc, "LATIN", 5) == 0) break; if (PG_VERSION_GE(conn, 8.1)) wenc = "WIN1252"; else wenc = "LATIN1"; break; case 1258: if (PG_VERSION_GE(conn, 8.1)) wenc = "WIN1258"; break; case 1253: if (PG_VERSION_GE(conn, 8.2)) wenc = "WIN1253"; break; case 1254: if (PG_VERSION_GE(conn, 8.2)) wenc = "WIN1254"; break; case 1255: if (PG_VERSION_GE(conn, 8.2)) wenc = "WIN1255"; break; case 1257: if (PG_VERSION_GE(conn, 8.2)) wenc = "WIN1257"; break; } #endif /* WIN32 */ return wenc; }
/* * This corresponds to "precision" in ODBC 2.x. * * For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will * override this length with the atttypmod length from pg_attribute . * * If col >= 0, then will attempt to get the info from the result set. * This is used for functions SQLDescribeCol and SQLColAttributes. */ Int4 /* PostgreSQL restriction */ pgtype_column_size(StatementClass *stmt, OID type, int col, int handle_unknown_size_as) { ConnectionClass *conn = SC_get_conn(stmt); ConnInfo *ci = &(conn->connInfo); if (handle_unknown_size_as == UNKNOWNS_AS_DEFAULT) handle_unknown_size_as = ci->drivers.unknown_sizes; switch (type) { case PG_TYPE_CHAR: return 1; case PG_TYPE_CHAR2: return 2; case PG_TYPE_CHAR4: return 4; case PG_TYPE_CHAR8: return 8; case PG_TYPE_NAME: { int value = 0; if (PG_VERSION_GT(conn, 7.4)) value = CC_get_max_idlen(conn); #ifdef NAME_FIELD_SIZE else value = NAME_FIELD_SIZE; #endif /* NAME_FIELD_SIZE */ if (0 == value) { if (PG_VERSION_GE(conn, 7.3)) value = NAMEDATALEN_V73; else value = NAMEDATALEN_V72; } return value; } case PG_TYPE_INT2: return 5; case PG_TYPE_OID: case PG_TYPE_XID: case PG_TYPE_INT4: return 10; case PG_TYPE_INT8: return 19; /* signed */ case PG_TYPE_NUMERIC: return getNumericColumnSize(stmt, type, col); case PG_TYPE_FLOAT4: case PG_TYPE_MONEY: return 7; case PG_TYPE_FLOAT8: return 15; case PG_TYPE_DATE: return 10; case PG_TYPE_TIME: return 8; case PG_TYPE_ABSTIME: case PG_TYPE_TIMESTAMP: return 22; case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP_NO_TMZONE: /* return 22; */ return getTimestampColumnSize(stmt, type, col); case PG_TYPE_BOOL: return ci->true_is_minus1 ? 2 : 1; case PG_TYPE_MACADDR: return 17; case PG_TYPE_INET: case PG_TYPE_CIDR: return sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128"); case PG_TYPE_UUID: return sizeof("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); case PG_TYPE_LO_UNDEFINED: return SQL_NO_TOTAL; default: if (type == stmt->hdbc->lobj_type) /* hack until permanent * type is available */ return SQL_NO_TOTAL; if (PG_TYPE_BYTEA == type && ci->bytea_as_longvarbinary) return SQL_NO_TOTAL; /* Handle Character types and unknown types */ return getCharColumnSize(stmt, type, col, handle_unknown_size_as); } }
Int4 getCharColumnSize(StatementClass *stmt, OID type, int col, int handle_unknown_size_as) { CSTR func = "getCharColumnSize"; int p = -1, attlen = -1, adtsize = -1, maxsize; QResultClass *result; ConnectionClass *conn = SC_get_conn(stmt); ConnInfo *ci = &(conn->connInfo); mylog("%s: type=%d, col=%d, unknown = %d\n", func, type, col, handle_unknown_size_as); /* Assign Maximum size based on parameters */ switch (type) { case PG_TYPE_TEXT: if (ci->drivers.text_as_longvarchar) maxsize = ci->drivers.max_longvarchar_size; else maxsize = ci->drivers.max_varchar_size; break; case PG_TYPE_VARCHAR: case PG_TYPE_BPCHAR: maxsize = ci->drivers.max_varchar_size; break; default: if (ci->drivers.unknowns_as_longvarchar) maxsize = ci->drivers.max_longvarchar_size; else maxsize = ci->drivers.max_varchar_size; break; } #ifdef UNICODE_SUPPORT if (CC_is_in_unicode_driver(conn) && isSqlServr() && maxsize > 4000) maxsize = 4000; #endif /* UNICODE_SUPPORT */ if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */ { if (PG_VERSION_GE(SC_get_conn(stmt), 7.1)) maxsize = 0; else maxsize = TEXT_FIELD_SIZE; } /* * Static ColumnSize (i.e., the Maximum ColumnSize of the datatype) This * has nothing to do with a result set. */ if (col < 0) return maxsize; if (result = SC_get_Curres(stmt), NULL == result) return maxsize; /* * Catalog Result Sets -- use assigned column width (i.e., from * set_tuplefield_string) */ adtsize = QR_get_fieldsize(result, col); if (stmt->catalog_result) { if (adtsize > 0) return adtsize; return maxsize; } p = QR_get_display_size(result, col); /* longest */ attlen = QR_get_atttypmod(result, col); /* Size is unknown -- handle according to parameter */ if (attlen > 0) /* maybe the length is known */ { if (attlen >= p) return attlen; switch (type) { case PG_TYPE_VARCHAR: case PG_TYPE_BPCHAR: #if (ODBCVER >= 0x0300) return attlen; #else if (CC_is_in_unicode_driver(conn) || conn->ms_jet) return attlen; return p; #endif /* ODBCVER */ } } /* The type is really unknown */ switch (handle_unknown_size_as) { case UNKNOWNS_AS_DONTKNOW: return -1; case UNKNOWNS_AS_LONGEST: mylog("%s: LONGEST: p = %d\n", func, p); if (p > 0) return p; break; case UNKNOWNS_AS_MAX: break; default: return -1; } if (maxsize <= 0) return maxsize; switch (type) { case PG_TYPE_BPCHAR: case PG_TYPE_VARCHAR: case PG_TYPE_TEXT: return maxsize; } if (p > maxsize) maxsize = p; return maxsize; }
OID sqltype_to_pgtype(StatementClass *stmt, SQLSMALLINT fSqlType) { OID pgType; ConnectionClass *conn = SC_get_conn(stmt); ConnInfo *ci = &(conn->connInfo); pgType = 0; /* ??? */ switch (fSqlType) { case SQL_BINARY: pgType = PG_TYPE_BYTEA; break; case SQL_CHAR: pgType = PG_TYPE_BPCHAR; break; #ifdef UNICODE_SUPPORT case SQL_WCHAR: pgType = PG_TYPE_BPCHAR; break; #endif /* UNICODE_SUPPORT */ case SQL_BIT: pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL; break; #if (ODBCVER >= 0x0300) case SQL_TYPE_DATE: #endif /* ODBCVER */ case SQL_DATE: pgType = PG_TYPE_DATE; break; case SQL_DOUBLE: case SQL_FLOAT: pgType = PG_TYPE_FLOAT8; break; case SQL_DECIMAL: case SQL_NUMERIC: pgType = PG_TYPE_NUMERIC; break; case SQL_BIGINT: pgType = PG_TYPE_INT8; break; case SQL_INTEGER: pgType = PG_TYPE_INT4; break; case SQL_LONGVARBINARY: if (ci->bytea_as_longvarbinary) pgType = PG_TYPE_BYTEA; else pgType = conn->lobj_type; break; case SQL_LONGVARCHAR: pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR; break; #ifdef UNICODE_SUPPORT case SQL_WLONGVARCHAR: pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR; break; #endif /* UNICODE_SUPPORT */ case SQL_REAL: pgType = PG_TYPE_FLOAT4; break; case SQL_SMALLINT: case SQL_TINYINT: pgType = PG_TYPE_INT2; break; case SQL_TIME: #if (ODBCVER >= 0x0300) case SQL_TYPE_TIME: #endif /* ODBCVER */ pgType = PG_TYPE_TIME; break; case SQL_TIMESTAMP: #if (ODBCVER >= 0x0300) case SQL_TYPE_TIMESTAMP: #endif /* ODBCVER */ pgType = PG_TYPE_DATETIME; break; case SQL_VARBINARY: pgType = PG_TYPE_BYTEA; break; case SQL_VARCHAR: pgType = PG_TYPE_VARCHAR; break; #if UNICODE_SUPPORT case SQL_WVARCHAR: pgType = PG_TYPE_VARCHAR; break; #endif /* UNICODE_SUPPORT */ #if (ODBCVER >= 0x0350) case SQL_GUID: if (PG_VERSION_GE(conn, 8.3)) pgType = PG_TYPE_UUID; break; #endif /* ODBCVER */ } return pgType; }
/* * 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); } }
static const char * get_environment_encoding(const ConnectionClass *conn, const char *setenc, const char *currenc) { const char *wenc = NULL; #ifdef WIN32 int acp; #endif /* WIN32 */ if (setenc && stricmp(setenc, "OTHER")) return setenc; if (wenc = getenv("PGCLIENTENCODING"), NULL != wenc) return wenc; #ifdef WIN32 acp = GetACP(); if (acp >= 1251 && acp <= 1258) { if (stricmp(currenc, "SQL_ASCII") == 0) return wenc; } switch (acp) { case 932: wenc = "SJIS"; break; case 936: wenc = "GBK"; break; case 949: wenc = "UHC"; break; case 950: wenc = "BIG5"; break; case 1250: wenc = "WIN1250"; break; case 1251: wenc = "WIN1251"; break; case 1256: wenc = "WIN1256"; break; case 1252: if (strnicmp(currenc, "LATIN", 5) == 0) break; if (PG_VERSION_GE(conn, 8.1)) wenc = "WIN1252"; else wenc = "LATIN1"; break; case 1258: if (PG_VERSION_GE(conn, 8.1)) wenc = "WIN1258"; break; case 1253: if (PG_VERSION_GE(conn, 8.2)) wenc = "WIN1253"; break; case 1254: if (PG_VERSION_GE(conn, 8.2)) wenc = "WIN1254"; break; case 1255: if (PG_VERSION_GE(conn, 8.2)) wenc = "WIN1255"; break; case 1257: if (PG_VERSION_GE(conn, 8.2)) wenc = "WIN1257"; break; } #endif /* WIN32 */ return wenc; }
/* * Read in field descriptions. * If self is not null, then also store the information. * If self is null, then just read, don't store. */ char CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn) { 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; /* COLUMN_NAME_STORAGE_LEN may be sufficient but for safety */ char new_field_name[2 * COLUMN_NAME_STORAGE_LEN + 1]; SocketClass *sock; ConnInfo *ci; sock = CC_get_socket(conn); ci = &conn->connInfo; /* at first read in the number of fields that are in the query */ new_num_fields = (Int2) SOCK_get_int(sock, sizeof(Int2)); mylog("num_fields = %d\n", new_num_fields); if (self) /* according to that allocate memory */ CI_set_num_fields(self, new_num_fields, PROTOCOL_74(ci)); /* now read in the descriptions */ for (lf = 0; lf < new_num_fields; lf++) { SOCK_get_string(sock, new_field_name, 2 * COLUMN_NAME_STORAGE_LEN); if (PROTOCOL_74(ci)) /* tableid & columnid */ { new_relid = SOCK_get_int(sock, sizeof(Int4)); new_attid = SOCK_get_int(sock, sizeof(Int2)); } new_adtid = (OID) SOCK_get_int(sock, 4); new_adtsize = (Int2) SOCK_get_int(sock, 2); /* If 6.4 protocol, then read the atttypmod field */ if (PG_VERSION_GE(conn, 6.4)) { mylog("READING ATTTYPMOD\n"); new_atttypmod = (Int4) SOCK_get_int(sock, 4); /* 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; if (PROTOCOL_74(ci)) /* format */ SOCK_get_int(sock, sizeof(Int2)); } 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 (SOCK_get_errcode(sock) == 0); }
OID sqltype_to_pgtype(const ConnectionClass *conn, SQLSMALLINT fSqlType) { OID pgType; const ConnInfo *ci = &(conn->connInfo); pgType = 0; /* ??? */ switch (fSqlType) { case SQL_BINARY: pgType = PG_TYPE_BYTEA; break; case SQL_CHAR: pgType = PG_TYPE_BPCHAR; break; #ifdef UNICODE_SUPPORT case SQL_WCHAR: pgType = PG_TYPE_BPCHAR; break; #endif /* UNICODE_SUPPORT */ case SQL_BIT: pgType = PG_TYPE_BOOL; break; case SQL_TYPE_DATE: case SQL_DATE: pgType = PG_TYPE_DATE; break; case SQL_DOUBLE: case SQL_FLOAT: pgType = PG_TYPE_FLOAT8; break; case SQL_DECIMAL: case SQL_NUMERIC: pgType = PG_TYPE_NUMERIC; break; case SQL_BIGINT: pgType = PG_TYPE_INT8; break; case SQL_INTEGER: pgType = PG_TYPE_INT4; break; case SQL_LONGVARBINARY: if (ci->bytea_as_longvarbinary) pgType = PG_TYPE_BYTEA; else pgType = conn->lobj_type; break; case SQL_LONGVARCHAR: pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR; break; #ifdef UNICODE_SUPPORT case SQL_WLONGVARCHAR: pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR; break; #endif /* UNICODE_SUPPORT */ case SQL_REAL: pgType = PG_TYPE_FLOAT4; break; case SQL_SMALLINT: case SQL_TINYINT: pgType = PG_TYPE_INT2; break; case SQL_TIME: case SQL_TYPE_TIME: pgType = PG_TYPE_TIME; break; case SQL_TIMESTAMP: case SQL_TYPE_TIMESTAMP: pgType = PG_TYPE_DATETIME; break; case SQL_VARBINARY: pgType = PG_TYPE_BYTEA; break; case SQL_VARCHAR: pgType = PG_TYPE_VARCHAR; break; #ifdef UNICODE_SUPPORT case SQL_WVARCHAR: pgType = PG_TYPE_VARCHAR; break; #endif /* UNICODE_SUPPORT */ case SQL_GUID: if (PG_VERSION_GE(conn, 8.3)) pgType = PG_TYPE_UUID; break; case SQL_INTERVAL_MONTH: case SQL_INTERVAL_YEAR: case SQL_INTERVAL_YEAR_TO_MONTH: case SQL_INTERVAL_DAY: case SQL_INTERVAL_HOUR: case SQL_INTERVAL_MINUTE: case SQL_INTERVAL_SECOND: case SQL_INTERVAL_DAY_TO_HOUR: case SQL_INTERVAL_DAY_TO_MINUTE: case SQL_INTERVAL_DAY_TO_SECOND: case SQL_INTERVAL_HOUR_TO_MINUTE: case SQL_INTERVAL_HOUR_TO_SECOND: case SQL_INTERVAL_MINUTE_TO_SECOND: pgType = PG_TYPE_INTERVAL; break; } return pgType; }
/* * Casting parameters e.g. ?::timestamp is much more flexible * than specifying parameter datatype oids determined by * sqltype_to_bind_pgtype() via parse message. */ const char * sqltype_to_pgcast(const ConnectionClass *conn, SQLSMALLINT fSqlType) { const char *pgCast = NULL_STRING; switch (fSqlType) { case SQL_BINARY: case SQL_VARBINARY: pgCast = "::bytea"; break; case SQL_TYPE_DATE: case SQL_DATE: pgCast = "::date"; break; case SQL_DECIMAL: case SQL_NUMERIC: pgCast = "::numeric"; break; case SQL_BIGINT: pgCast = "::int8"; break; case SQL_INTEGER: pgCast = "::int4"; break; case SQL_REAL: pgCast = "::float4"; break; case SQL_SMALLINT: case SQL_TINYINT: pgCast = "::int2"; break; case SQL_TIME: case SQL_TYPE_TIME: pgCast = "::time"; break; case SQL_TIMESTAMP: case SQL_TYPE_TIMESTAMP: pgCast = "::timestamp"; break; case SQL_GUID: if (PG_VERSION_GE(conn, 8.3)) pgCast = "::uuid"; break; case SQL_INTERVAL_MONTH: case SQL_INTERVAL_YEAR: case SQL_INTERVAL_YEAR_TO_MONTH: case SQL_INTERVAL_DAY: case SQL_INTERVAL_HOUR: case SQL_INTERVAL_MINUTE: case SQL_INTERVAL_SECOND: case SQL_INTERVAL_DAY_TO_HOUR: case SQL_INTERVAL_DAY_TO_MINUTE: case SQL_INTERVAL_DAY_TO_SECOND: case SQL_INTERVAL_HOUR_TO_MINUTE: case SQL_INTERVAL_HOUR_TO_SECOND: case SQL_INTERVAL_MINUTE_TO_SECOND: pgCast = "::interval"; break; } return pgCast; }