Tim Bunce wrote:
> 
> If you tell me which you'd like to see and why, and I like what you say,
> then your word will be my command (eventually:) !
> 
> Better still (and faster still), send me a patch!
>
O.k. The patch is tested for OCI7 and OCI8 on WinNT 4.0, Borland 5.02.
The output for the test case now is:

TYPE    PREC    SCALE   NAME
3       38      0       CINTEGER
8       126     0       CNUMBER
3       38      0       CNUMBER_38_0
3       11      2       CNUMBER_11_2
3       38      2       CNUMBER_XX_2
8       126     0       CFLOAT
8       11      0       CFLOAT_11
8       63      0       CREAL
8       126     0       CDOUBLE_PRECISION
9       0       0       CDATE

The patch includes the necessary changes to distinguish exact
and approximate numeric types.
There are still some options (see comments for SQL_NUMERIC and
SQL_INTEGER), but this would potentially break more code that
relies on SQL_DECIMAL and needs additional entries in the
type_info structure. Any opinions about that?

--------------------------------------------------------------------
diff -ubr ./DBD-Oracle-1.06-orig/dbdimp.c ./DBD-Oracle-1.06/dbdimp.c
--- ./DBD-Oracle-1.06-orig/dbdimp.c     Sat Jul 15 00:52:12 2000
+++ ./DBD-Oracle-1.06/dbdimp.c  Wed Mar 28 09:38:38 2001
@@ -29,7 +29,13 @@
 static int set_sigint_handler  = 0;
 #endif
 
-static int ora2sql_type _((int oratype));
+typedef struct sql_fbh_st sql_fbh_t;
+struct sql_fbh_st {
+  int dbtype;
+  int prec;
+  int scale;
+};
+static sql_fbh_t ora2sql_type _((imp_fbh_t* fbh));
 
 void ora_free_phs_contents _((phs_t *phs));
 static void dump_env_to_trace();
@@ -1751,19 +1757,19 @@
        AV *av = newAV();
        retsv = newRV(sv_2mortal((SV*)av));
        while(--i >= 0)
-           av_store(av, i, newSViv(ora2sql_type(imp_sth->fbh[i].dbtype)));
+           av_store(av, i, newSViv(ora2sql_type(imp_sth->fbh+i).dbtype));
 
     } else if (kl==5 && strEQ(key, "SCALE")) {
        AV *av = newAV();
        retsv = newRV(sv_2mortal((SV*)av));
        while(--i >= 0)
-           av_store(av, i, newSViv(imp_sth->fbh[i].scale));
+           av_store(av, i, newSViv(ora2sql_type(imp_sth->fbh+i).scale));
 
     } else if (kl==9 && strEQ(key, "PRECISION")) {
        AV *av = newAV();
        retsv = newRV(sv_2mortal((SV*)av));
        while(--i >= 0)
-           av_store(av, i, newSViv(imp_sth->fbh[i].prec));
+           av_store(av, i, newSViv(ora2sql_type(imp_sth->fbh+i).prec));
 
 #ifndef OCI_V8_SYNTAX
 #ifdef XXXXX
@@ -1805,21 +1811,41 @@
 
 /* --------------------------------------- */
 
-static int
-ora2sql_type(oratype)
-   int oratype;
-{
-    switch(oratype) {  /* oracle Internal (not external) types */
-    case SQLT_CHR:  return SQL_VARCHAR;
-    case SQLT_NUM:  return SQL_DECIMAL;
-    case SQLT_LNG:  return SQL_LONGVARCHAR;    /* long */
-    case SQLT_DAT:  return SQL_DATE;
-    case SQLT_BIN:  return SQL_BINARY;         /* raw */
-    case SQLT_LBI:  return SQL_LONGVARBINARY;  /* long raw */
-    case SQLT_AFC:  return SQL_CHAR;           /* Ansi fixed char */
+static sql_fbh_t
+ora2sql_type(imp_fbh_t* fbh) {
+    sql_fbh_t sql_fbh;
+    sql_fbh.dbtype = fbh->dbtype;
+    sql_fbh.prec   = fbh->prec;
+    sql_fbh.scale  = fbh->scale;
+
+    switch(fbh->dbtype) { /* oracle Internal (not external) types */
+    case SQLT_NUM:
+        if (fbh->scale == -127) { /* FLOAT, REAL, DOUBLE_PRECISION */
+            sql_fbh.dbtype = SQL_DOUBLE;
+            sql_fbh.scale  = 0; /* better: undef */
+        }
+        else if (fbh->scale == 0) {
+            if (fbh->prec == 0) { /* NUMBER */
+                sql_fbh.dbtype = SQL_DOUBLE;
+                sql_fbh.prec   = 126;
+            }
+            else { /* INTEGER, NUMBER(p,0) */
+                sql_fbh.dbtype = SQL_DECIMAL; /* better: SQL_INTEGER */
+            }
     }
-    /* else map type into DBI reserved standard range */
-    return -9000 - oratype;
+        else { /* NUMBER(p,s) */
+            sql_fbh.dbtype = SQL_DECIMAL; /* better: SQL_NUMERIC */
+        }
+        break;
+    case SQLT_CHR:  sql_fbh.dbtype = SQL_VARCHAR;       break;
+    case SQLT_LNG:  sql_fbh.dbtype = SQL_LONGVARCHAR;   break; /* long
*/
+    case SQLT_DAT:  sql_fbh.dbtype = SQL_DATE;          break;
+    case SQLT_BIN:  sql_fbh.dbtype = SQL_BINARY;        break; /* raw
*/
+    case SQLT_LBI:  sql_fbh.dbtype = SQL_LONGVARBINARY; break; /* long
raw */
+    case SQLT_AFC:  sql_fbh.dbtype = SQL_CHAR;          break; /* Ansi
fixed char */
+    default:        sql_fbh.dbtype = -9000 - fbh->dbtype;      /* else
map type into DBI reserved standard range */
+    }
+    return sql_fbh;
 }
 
 static void
@@ -1827,7 +1853,9 @@
     FILE *fp = DBILOGFP;
     int i = 0;
     char *p;
+#ifndef __BORLANDC__
     extern char **environ;
+#endif
     fprintf(fp, "Environment variables:\n");
     do {
        p = (char*)environ[i++];
diff -ubr ./DBD-Oracle-1.06-orig/oci7.c ./DBD-Oracle-1.06/oci7.c
--- ./DBD-Oracle-1.06-orig/oci7.c       Wed May 03 00:24:40 2000
+++ ./DBD-Oracle-1.06/oci7.c    Tue Mar 27 17:08:06 2001
@@ -240,9 +240,6 @@
            fbh->dbsize *= 2;
            fbh->disize *= 2;
        }
-       else if (fbh->dbtype == 2 && fbh->prec == 0) {
-           fbh->prec = 38;
-       }
        else if ((fbh->dbtype == 1 || fbh->dbtype == 96) && fbh->prec == 0) {
            fbh->prec = fbh->dbsize;
        }
diff -ubr ./DBD-Oracle-1.06-orig/oci8.c ./DBD-Oracle-1.06/oci8.c
--- ./DBD-Oracle-1.06-orig/oci8.c       Fri Jul 14 01:42:18 2000
+++ ./DBD-Oracle-1.06/oci8.c    Tue Mar 27 17:07:53 2001
@@ -705,8 +705,6 @@
                break;
 
        case   2:                               /* NUMBER       */
-               if (!fbh->prec)   /* is 0 for FLOATing point    */
-                    fbh->prec = 38;             /* max prec    */
                fbh->disize = 130+3;    /* worst case! 1**-130  */
                avg_width = 4;     /* > approx +/- 1_000_000 ?  */
                break;

--------------------------------------------------------------------
Steffen

Reply via email to