Added numeric and int8 types.
authorByron Nikolaidis
Sun, 30 Jan 2000 21:14:25 +0000 (21:14 +0000)
committerByron Nikolaidis
Sun, 30 Jan 2000 21:14:25 +0000 (21:14 +0000)
Bug fix for LongVarBinary -- begin transaction

src/interfaces/odbc/convert.c
src/interfaces/odbc/execute.c
src/interfaces/odbc/info.c
src/interfaces/odbc/pgtypes.c
src/interfaces/odbc/pgtypes.h
src/interfaces/odbc/psqlodbc.h
src/interfaces/odbc/results.c

index a4f1487e868eee483d00c4de2ced53ce026a49ec..4cfe8d4567d7274e27876b5d0ae881e18193e174 100644 (file)
@@ -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 */
    }
 
index 13d979a01ffcabd3d5e235846a23275056c3d975..fd82e0df718ec414fdb9693f40eea5e4750772ab 100644 (file)
@@ -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) {
index 8f630710da029ae0043e75934a009c63f6611d86..4d544d42ce27b219db3654d89d3f1882a684e927 100644 (file)
@@ -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);
index 5c02c4c21a371177da6194bd7d37bbd883e9de2a..3ee5e75c4e5de48ae7e77828a3d5f2c8661529b3 100644 (file)
@@ -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;
index 52b7a4a0c975d85eb20c1f82b8acb0ff6423be3f..7b42af34ddee3a9cb99e0f693fe3604b6ffd7ca0 100644 (file)
@@ -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);
index c8d4923436ebdffbf244d32f7f0e84843e8a3d08..7e9493b90f6d9571562c1a6e021097402d99a67e 100644 (file)
@@ -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"
 
index 47291127d1e182b809efc60b7058ae708a5fad22..a6703290f16595f68bbac560167a3d510e3f72c1 100644 (file)
@@ -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: