diff --git a/src/interfaces/odbc/convert.c b/src/interfaces/odbc/convert.c index a4f1487e86..4cfe8d4567 100644 --- a/src/interfaces/odbc/convert.c +++ b/src/interfaces/odbc/convert.c @@ -40,6 +40,7 @@ #include #include "convert.h" #include "statement.h" +#include "qresult.h" #include "bind.h" #include "pgtypes.h" #include "lobj.h" @@ -895,6 +896,30 @@ int lobj_fd, retval; } else { + + /* begin transaction if needed */ + if(!CC_is_in_trans(stmt->hdbc)) { + QResultClass *res; + char ok; + + res = CC_send_query(stmt->hdbc, "BEGIN", NULL); + if (!res) { + stmt->errormsg = "Could not begin (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + SC_log_error(func, "", stmt); + return SQL_ERROR; + } + ok = QR_command_successful(res); + QR_Destructor(res); + if (!ok) { + stmt->errormsg = "Could not begin (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + SC_log_error(func, "", stmt); + return SQL_ERROR; + } + + CC_set_in_trans(stmt->hdbc); + } /* store the oid */ lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE); @@ -917,6 +942,30 @@ int lobj_fd, retval; retval = lo_write(stmt->hdbc, lobj_fd, buffer, used); lo_close(stmt->hdbc, lobj_fd); + + /* commit transaction if needed */ + if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) { + QResultClass *res; + char ok; + + res = CC_send_query(stmt->hdbc, "COMMIT", NULL); + if (!res) { + stmt->errormsg = "Could not commit (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + SC_log_error(func, "", stmt); + return SQL_ERROR; + } + ok = QR_command_successful(res); + QR_Destructor(res); + if (!ok) { + stmt->errormsg = "Could not commit (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + SC_log_error(func, "", stmt); + return SQL_ERROR; + } + + CC_set_no_trans(stmt->hdbc); + } } /* the oid of the large object -- just put that in for the @@ -1340,6 +1389,29 @@ BindInfoClass *bindInfo = NULL; */ if ( ! bindInfo || bindInfo->data_left == -1) { + + /* begin transaction if needed */ + if(!CC_is_in_trans(stmt->hdbc)) { + QResultClass *res; + char ok; + + res = CC_send_query(stmt->hdbc, "BEGIN", NULL); + if (!res) { + stmt->errormsg = "Could not begin (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + return COPY_GENERAL_ERROR; + } + ok = QR_command_successful(res); + QR_Destructor(res); + if (!ok) { + stmt->errormsg = "Could not begin (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + return COPY_GENERAL_ERROR; + } + + CC_set_in_trans(stmt->hdbc); + } + oid = atoi(value); stmt->lobj_fd = lo_open(stmt->hdbc, oid, INV_READ); if (stmt->lobj_fd < 0) { @@ -1374,6 +1446,29 @@ BindInfoClass *bindInfo = NULL; retval = lo_read(stmt->hdbc, stmt->lobj_fd, (char *) rgbValue, cbValueMax); if (retval < 0) { lo_close(stmt->hdbc, stmt->lobj_fd); + + /* commit transaction if needed */ + if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) { + QResultClass *res; + char ok; + + res = CC_send_query(stmt->hdbc, "COMMIT", NULL); + if (!res) { + stmt->errormsg = "Could not commit (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + return COPY_GENERAL_ERROR; + } + ok = QR_command_successful(res); + QR_Destructor(res); + if (!ok) { + stmt->errormsg = "Could not commit (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + return COPY_GENERAL_ERROR; + } + + CC_set_no_trans(stmt->hdbc); + } + stmt->lobj_fd = -1; stmt->errornumber = STMT_EXEC_ERROR; @@ -1396,6 +1491,29 @@ BindInfoClass *bindInfo = NULL; if (! bindInfo || bindInfo->data_left == 0) { lo_close(stmt->hdbc, stmt->lobj_fd); + + /* commit transaction if needed */ + if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) { + QResultClass *res; + char ok; + + res = CC_send_query(stmt->hdbc, "COMMIT", NULL); + if (!res) { + stmt->errormsg = "Could not commit (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + return COPY_GENERAL_ERROR; + } + ok = QR_command_successful(res); + QR_Destructor(res); + if (!ok) { + stmt->errormsg = "Could not commit (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + return COPY_GENERAL_ERROR; + } + + CC_set_no_trans(stmt->hdbc); + } + stmt->lobj_fd = -1; /* prevent further reading */ } diff --git a/src/interfaces/odbc/execute.c b/src/interfaces/odbc/execute.c index 13d979a01f..fd82e0df71 100644 --- a/src/interfaces/odbc/execute.c +++ b/src/interfaces/odbc/execute.c @@ -517,6 +517,31 @@ int i, retval; /* close the large object */ if ( stmt->lobj_fd >= 0) { lo_close(stmt->hdbc, stmt->lobj_fd); + + /* commit transaction if needed */ + if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) { + QResultClass *res; + char ok; + + res = CC_send_query(stmt->hdbc, "COMMIT", NULL); + if (!res) { + stmt->errormsg = "Could not commit (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + SC_log_error(func, "", stmt); + return SQL_ERROR; + } + ok = QR_command_successful(res); + QR_Destructor(res); + if (!ok) { + stmt->errormsg = "Could not commit (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + SC_log_error(func, "", stmt); + return SQL_ERROR; + } + + CC_set_no_trans(stmt->hdbc); + } + stmt->lobj_fd = -1; } @@ -607,6 +632,30 @@ char *buffer; /* Handle Long Var Binary with Large Objects */ if ( current_param->SQLType == SQL_LONGVARBINARY) { + /* begin transaction if needed */ + if(!CC_is_in_trans(stmt->hdbc)) { + QResultClass *res; + char ok; + + res = CC_send_query(stmt->hdbc, "BEGIN", NULL); + if (!res) { + stmt->errormsg = "Could not begin (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + SC_log_error(func, "", stmt); + return SQL_ERROR; + } + ok = QR_command_successful(res); + QR_Destructor(res); + if (!ok) { + stmt->errormsg = "Could not begin (in-line) a transaction"; + stmt->errornumber = STMT_EXEC_ERROR; + SC_log_error(func, "", stmt); + return SQL_ERROR; + } + + CC_set_in_trans(stmt->hdbc); + } + /* store the oid */ current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE); if (current_param->lobj_oid == 0) { diff --git a/src/interfaces/odbc/info.c b/src/interfaces/odbc/info.c index 8f630710da..4d544d42ce 100644 --- a/src/interfaces/odbc/info.c +++ b/src/interfaces/odbc/info.c @@ -705,8 +705,8 @@ Int2 sqlType; set_nullfield_string(&row->tuple[5], pgtype_create_params(stmt, pgType)); set_nullfield_int2(&row->tuple[9], pgtype_unsigned(stmt, pgType)); set_nullfield_int2(&row->tuple[11], pgtype_auto_increment(stmt, pgType)); - set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType)); - set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType)); + set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC)); + set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType, PG_STATIC)); QR_add_tuple(stmt->result, row); } @@ -1179,8 +1179,9 @@ StatementClass *col_stmt; char columns_query[MAX_STATEMENT_LEN]; RETCODE result; char table_owner[MAX_INFO_STRING], table_name[MAX_INFO_STRING], field_name[MAX_INFO_STRING], field_type_name[MAX_INFO_STRING]; -Int2 field_number, result_cols; -Int4 field_type, the_type, field_length, mod_length; +Int2 field_number, result_cols, scale; +Int4 field_type, the_type, field_length, mod_length, precision; +char useStaticPrecision; char not_null[MAX_INFO_STRING], relhasrules[MAX_INFO_STRING]; ConnInfo *ci; @@ -1400,7 +1401,7 @@ ConnInfo *ci; set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, the_type, PG_STATIC, PG_STATIC)); - set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type)); + set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type, PG_STATIC)); set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type)); set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS); set_tuplefield_string(&row->tuple[11], ""); @@ -1433,10 +1434,42 @@ ConnInfo *ci; VARCHAR - the length is stored in the pg_attribute.atttypmod field BPCHAR - the length is also stored as varchar is + NUMERIC - the scale is stored in atttypmod as follows: + precision = ((atttypmod - VARHDRSZ) >> 16) & 0xffff + scale = (atttypmod - VARHDRSZ) & 0xffff + + */ + qlog("SQLColumns: table='%s',field_name='%s',type=%d,sqltype=%d,name='%s'\n", + table_name,field_name,field_type,pgtype_to_sqltype,field_type_name); + + useStaticPrecision = TRUE; + + if (field_type == PG_TYPE_NUMERIC) { + if (mod_length >= 4) + mod_length -= 4; // the length is in atttypmod - 4 + + if (mod_length >= 0) { + useStaticPrecision = FALSE; + + precision = (mod_length >> 16) & 0xffff; + scale = mod_length & 0xffff; + + mylog("SQLColumns: field type is NUMERIC: field_type = %d, mod_length=%d, precision=%d, scale=%d\n", field_type, mod_length, precision, scale ); + + set_tuplefield_int4(&row->tuple[7], precision + 2); // sign+dec.point + set_tuplefield_int4(&row->tuple[6], precision); + set_tuplefield_int4(&row->tuple[12], precision + 2); // sign+dec.point + set_nullfield_int2(&row->tuple[8], scale); + } + } + + if((field_type == PG_TYPE_VARCHAR) || (field_type == PG_TYPE_BPCHAR)) { + useStaticPrecision = FALSE; + if (mod_length >= 4) mod_length -= 4; // the length is in atttypmod - 4 @@ -1445,19 +1478,21 @@ ConnInfo *ci; mylog("SQLColumns: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", field_type, mod_length); - set_tuplefield_int4(&row->tuple[7], mod_length); + set_tuplefield_int4(&row->tuple[7], mod_length); set_tuplefield_int4(&row->tuple[6], mod_length); set_tuplefield_int4(&row->tuple[12], mod_length); - } else { + set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, field_type, PG_STATIC)); + } + + if (useStaticPrecision) { mylog("SQLColumns: field type is OTHER: field_type = %d, pgtype_length = %d\n", field_type, pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, field_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, field_type, PG_STATIC, PG_STATIC)); - + set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, field_type, PG_STATIC)); } - set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, field_type)); set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type)); set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type))); set_tuplefield_string(&row->tuple[11], ""); @@ -1494,7 +1529,7 @@ ConnInfo *ci; set_tuplefield_string(&row->tuple[5], pgtype_to_name(stmt, the_type)); set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, the_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC)); - set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type)); + set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type, PG_STATIC)); set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type)); set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS); set_tuplefield_string(&row->tuple[11], ""); @@ -1622,7 +1657,7 @@ mylog("%s: entering...stmt=%u\n", func, stmt); set_tuplefield_string(&row->tuple[3], "OID"); set_tuplefield_int4(&row->tuple[4], pgtype_precision(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[5], pgtype_length(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC)); - set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, PG_TYPE_OID)); + set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, PG_TYPE_OID, PG_STATIC)); set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO); QR_add_tuple(stmt->result, row); @@ -1640,7 +1675,7 @@ mylog("%s: entering...stmt=%u\n", func, stmt); set_tuplefield_string(&row->tuple[3], pgtype_to_name(stmt, the_type)); set_tuplefield_int4(&row->tuple[4], pgtype_precision(stmt, the_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[5], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC)); - set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, the_type)); + set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, the_type, PG_STATIC)); set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO); QR_add_tuple(stmt->result, row); diff --git a/src/interfaces/odbc/pgtypes.c b/src/interfaces/odbc/pgtypes.c index 5c02c4c21a..3ee5e75c4e 100644 --- a/src/interfaces/odbc/pgtypes.c +++ b/src/interfaces/odbc/pgtypes.c @@ -130,10 +130,16 @@ Int4 pgType; pgType = PG_TYPE_FLOAT8; break; - case SQL_INTEGER: - case SQL_BIGINT: - case SQL_NUMERIC: 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; @@ -193,7 +199,6 @@ Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type) case PG_TYPE_CHAR2: case PG_TYPE_CHAR4: case PG_TYPE_CHAR8: - case PG_TYPE_CHAR16: case PG_TYPE_NAME: return SQL_CHAR; case PG_TYPE_BPCHAR: return SQL_CHAR; @@ -211,6 +216,9 @@ Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type) case PG_TYPE_XID: case PG_TYPE_INT4: return SQL_INTEGER; + case PG_TYPE_INT8: return SQL_BIGINT; + case PG_TYPE_NUMERIC: return SQL_NUMERIC; + case PG_TYPE_FLOAT4: return SQL_REAL; case PG_TYPE_FLOAT8: return SQL_FLOAT; case PG_TYPE_DATE: return SQL_DATE; @@ -236,6 +244,8 @@ Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type) Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type) { switch(type) { + case PG_TYPE_INT8: return SQL_C_CHAR; + case PG_TYPE_NUMERIC: return SQL_C_CHAR; case PG_TYPE_INT2: return SQL_C_SSHORT; case PG_TYPE_OID: case PG_TYPE_XID: @@ -269,7 +279,8 @@ char *pgtype_to_name(StatementClass *stmt, Int4 type) case PG_TYPE_CHAR2: return "char2"; case PG_TYPE_CHAR4: return "char4"; case PG_TYPE_CHAR8: return "char8"; - case PG_TYPE_CHAR16: return "char16"; + case PG_TYPE_INT8: return "int8"; + case PG_TYPE_NUMERIC: return "numeric"; case PG_TYPE_VARCHAR: return "varchar"; case PG_TYPE_BPCHAR: return "char"; case PG_TYPE_TEXT: return "text"; @@ -299,6 +310,70 @@ char *pgtype_to_name(StatementClass *stmt, Int4 type) } } +Int2 +getNumericScale(StatementClass *stmt, Int4 type, int col) +{ +Int4 atttypmod; +QResultClass *result; +ColumnInfoClass *flds; + +mylog("getNumericScale: type=%d, col=%d, unknown = %d\n", type,col); + + if (col < 0) + return PG_NUMERIC_MAX_SCALE; + + result = SC_get_Result(stmt); + + /* Manual Result Sets -- use assigned column width (i.e., from set_tuplefield_string) */ + if (stmt->manual_result) { + flds = result->fields; + if (flds) + return flds->adtsize[col]; + else + return PG_NUMERIC_MAX_SCALE; + } + + atttypmod = QR_get_atttypmod(result, col); + if ( atttypmod > -1 ) + return (atttypmod & 0xffff); + else + return ( QR_get_display_size(result, col) ? + QR_get_display_size(result, col) : + PG_NUMERIC_MAX_SCALE); +} + +Int4 +getNumericPrecision(StatementClass *stmt, Int4 type, int col) +{ +Int4 atttypmod; +QResultClass *result; +ColumnInfoClass *flds; + +mylog("getNumericPrecision: type=%d, col=%d, unknown = %d\n", type,col); + + if (col < 0) + return PG_NUMERIC_MAX_PRECISION; + + result = SC_get_Result(stmt); + + /* Manual Result Sets -- use assigned column width (i.e., from set_tuplefield_string) */ + if (stmt->manual_result) { + flds = result->fields; + if (flds) + return flds->adtsize[col]; + else + return PG_NUMERIC_MAX_PRECISION; + } + + atttypmod = QR_get_atttypmod(result, col); + if ( atttypmod > -1 ) + return (atttypmod >> 16) & 0xffff; + else + return ( QR_get_display_size(result, col) >= 0 ? + QR_get_display_size(result, col) : + PG_NUMERIC_MAX_PRECISION ); +} + Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) { @@ -362,7 +437,7 @@ mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unkno return p; } -/* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will +/* 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. @@ -377,7 +452,6 @@ Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unkno case PG_TYPE_CHAR2: return 2; case PG_TYPE_CHAR4: return 4; case PG_TYPE_CHAR8: return 8; - case PG_TYPE_CHAR16: return 16; case PG_TYPE_NAME: return NAME_FIELD_SIZE; @@ -387,6 +461,10 @@ Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unkno case PG_TYPE_XID: case PG_TYPE_INT4: return 10; + case PG_TYPE_INT8: return 19; /* signed */ + + case PG_TYPE_NUMERIC: return getNumericPrecision(stmt,type,col); + case PG_TYPE_FLOAT4: case PG_TYPE_MONEY: return 7; @@ -415,6 +493,7 @@ Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unkno Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) { + switch(type) { case PG_TYPE_INT2: return 6; @@ -423,6 +502,10 @@ Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_un case PG_TYPE_INT4: return 11; + case PG_TYPE_INT8: return 20; /* signed: 19 digits + sign */ + + case PG_TYPE_NUMERIC: return getNumericPrecision(stmt,type,col) + 2; + case PG_TYPE_MONEY: return 15; /* ($9,999,999.99) */ case PG_TYPE_FLOAT4: return 13; @@ -440,6 +523,7 @@ Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_un */ Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) { + switch(type) { case PG_TYPE_INT2: return 2; @@ -448,6 +532,10 @@ Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_ 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 getNumericPrecision(stmt,type,col) + 2; + case PG_TYPE_FLOAT4: case PG_TYPE_MONEY: return 4; @@ -461,13 +549,13 @@ Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_ case PG_TYPE_TIMESTAMP: return 16; - /* Character types use the default precision */ + /* Character types (and NUMERIC) use the default precision */ default: return pgtype_precision(stmt, type, col, handle_unknown_size_as); } } -Int2 pgtype_scale(StatementClass *stmt, Int4 type) +Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col) { switch(type) { @@ -475,6 +563,7 @@ Int2 pgtype_scale(StatementClass *stmt, Int4 type) case PG_TYPE_OID: case PG_TYPE_XID: case PG_TYPE_INT4: + case PG_TYPE_INT8: case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT8: case PG_TYPE_MONEY: @@ -485,6 +574,8 @@ Int2 pgtype_scale(StatementClass *stmt, Int4 type) case PG_TYPE_DATETIME: case PG_TYPE_TIMESTAMP: return 0; + case PG_TYPE_NUMERIC: return getNumericScale(stmt,type,col); + default: return -1; } } @@ -496,6 +587,8 @@ Int2 pgtype_radix(StatementClass *stmt, Int4 type) case PG_TYPE_INT2: case PG_TYPE_OID: case PG_TYPE_INT4: + case PG_TYPE_INT8: + case PG_TYPE_NUMERIC: case PG_TYPE_FLOAT4: case PG_TYPE_MONEY: case PG_TYPE_FLOAT8: return 10; @@ -521,6 +614,8 @@ Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type) case PG_TYPE_MONEY: case PG_TYPE_BOOL: case PG_TYPE_FLOAT8: + case PG_TYPE_INT8: + case PG_TYPE_NUMERIC: case PG_TYPE_DATE: case PG_TYPE_TIME: @@ -540,7 +635,6 @@ Int2 pgtype_case_sensitive(StatementClass *stmt, Int4 type) case PG_TYPE_CHAR2: case PG_TYPE_CHAR4: case PG_TYPE_CHAR8: - case PG_TYPE_CHAR16: case PG_TYPE_VARCHAR: case PG_TYPE_BPCHAR: @@ -566,7 +660,6 @@ Int2 pgtype_searchable(StatementClass *stmt, Int4 type) case PG_TYPE_CHAR2: case PG_TYPE_CHAR4: case PG_TYPE_CHAR8: - case PG_TYPE_CHAR16: case PG_TYPE_VARCHAR: case PG_TYPE_BPCHAR: @@ -585,6 +678,8 @@ Int2 pgtype_unsigned(StatementClass *stmt, Int4 type) case PG_TYPE_INT2: case PG_TYPE_INT4: + case PG_TYPE_INT8: + case PG_TYPE_NUMERIC: case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT8: case PG_TYPE_MONEY: return FALSE; @@ -601,6 +696,8 @@ char *pgtype_literal_prefix(StatementClass *stmt, Int4 type) case PG_TYPE_OID: case PG_TYPE_XID: case PG_TYPE_INT4: + case PG_TYPE_INT8: + case PG_TYPE_NUMERIC: case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT8: case PG_TYPE_MONEY: return NULL; @@ -617,6 +714,8 @@ char *pgtype_literal_suffix(StatementClass *stmt, Int4 type) case PG_TYPE_OID: case PG_TYPE_XID: case PG_TYPE_INT4: + case PG_TYPE_INT8: + case PG_TYPE_NUMERIC: case PG_TYPE_FLOAT4: case PG_TYPE_FLOAT8: case PG_TYPE_MONEY: return NULL; diff --git a/src/interfaces/odbc/pgtypes.h b/src/interfaces/odbc/pgtypes.h index 52b7a4a0c9..7b42af34dd 100644 --- a/src/interfaces/odbc/pgtypes.h +++ b/src/interfaces/odbc/pgtypes.h @@ -22,7 +22,7 @@ #define PG_TYPE_BYTEA 17 #define PG_TYPE_CHAR 18 #define PG_TYPE_NAME 19 -#define PG_TYPE_CHAR16 20 +#define PG_TYPE_INT8 20 #define PG_TYPE_INT2 21 #define PG_TYPE_INT2VECTOR 22 #define PG_TYPE_INT4 23 @@ -59,6 +59,7 @@ #define PG_TYPE_TIME 1083 #define PG_TYPE_DATETIME 1184 #define PG_TYPE_TIMESTAMP 1296 +#define PG_TYPE_NUMERIC 1700 /* extern Int4 pgtypes_defined[]; */ extern Int2 sqlTypes[]; @@ -77,7 +78,7 @@ Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unkno Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); -Int2 pgtype_scale(StatementClass *stmt, Int4 type); +Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col); Int2 pgtype_radix(StatementClass *stmt, Int4 type); Int2 pgtype_nullable(StatementClass *stmt, Int4 type); Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type); diff --git a/src/interfaces/odbc/psqlodbc.h b/src/interfaces/odbc/psqlodbc.h index c8d4923436..7e9493b90f 100644 --- a/src/interfaces/odbc/psqlodbc.h +++ b/src/interfaces/odbc/psqlodbc.h @@ -39,8 +39,9 @@ typedef UInt4 Oid; #define DRIVERNAME "PostgreSQL ODBC" #define DBMS_NAME "PostgreSQL" -#define DBMS_VERSION "06.40.0007 PostgreSQL 6.4" -#define POSTGRESDRIVERVERSION "06.40.0007" + +#define DBMS_VERSION "06.40.0008 PostgreSQL 6.4/6.5" +#define POSTGRESDRIVERVERSION "06.40.0008" #ifdef WIN32 #define DRIVER_FILE_NAME "PSQLODBC.DLL" @@ -158,6 +159,8 @@ typedef struct QueryInfo_ { #define NAME_FIELD_SIZE 32 /* size of name fields */ #define MAX_VARCHAR_SIZE 254 /* maximum size of a varchar (not including null term) */ +#define PG_NUMERIC_MAX_PRECISION 1000 +#define PG_NUMERIC_MAX_SCALE 1000 #include "misc.h" diff --git a/src/interfaces/odbc/results.c b/src/interfaces/odbc/results.c index 47291127d1..a6703290f1 100644 --- a/src/interfaces/odbc/results.c +++ b/src/interfaces/odbc/results.c @@ -320,7 +320,7 @@ RETCODE result; /************************/ if (pibScale) { Int2 scale; - scale = pgtype_scale(stmt, fieldtype); + scale = pgtype_scale(stmt, fieldtype, icol); if(scale == -1) { scale = 0; } *pibScale = scale; @@ -521,7 +521,7 @@ int len = 0, value = 0; break; case SQL_COLUMN_SCALE: - value = pgtype_scale(stmt, field_type); + value = pgtype_scale(stmt, field_type, icol); break; case SQL_COLUMN_SEARCHABLE: