]> granicus.if.org Git - postgresql/commitdiff
Update driver to official 6.30.0244 release.
authorByron Nikolaidis <byronn@insightdist.com>
Mon, 8 Jun 1998 16:15:12 +0000 (16:15 +0000)
committerByron Nikolaidis <byronn@insightdist.com>
Mon, 8 Jun 1998 16:15:12 +0000 (16:15 +0000)
src/interfaces/odbc/bind.c
src/interfaces/odbc/convert.c
src/interfaces/odbc/dlg_specific.c
src/interfaces/odbc/dlg_specific.h
src/interfaces/odbc/info.c
src/interfaces/odbc/lobj.c [new file with mode: 0644]
src/interfaces/odbc/lobj.h [new file with mode: 0644]
src/interfaces/odbc/options.c
src/interfaces/odbc/psqlodbc.h
src/interfaces/odbc/statement.c
src/interfaces/odbc/statement.h

index 945d23d64d6095347ada191fa220eafee5243723..504dbc20ebaa0816a10d5052382336fd1fc0d6f5 100644 (file)
@@ -200,7 +200,12 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
 
 //      -       -       -       -       -       -       -       -       -
 
-//      Returns the description of a parameter marker.
+//  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 SQLDescribeParam(
         HSTMT      hstmt,
@@ -223,6 +228,8 @@ StatementClass *stmt = (StatementClass *) hstmt;
 
        ipar--;
 
+       //      This implementation is not very good, since it is supposed to describe
+       //      parameter markers, not bound parameters. 
        if(pfSqlType)
                *pfSqlType = stmt->parameters[ipar].SQLType;
 
@@ -252,25 +259,50 @@ RETCODE SQL_API SQLParamOptions(
 
 //      -       -       -       -       -       -       -       -       -
 
-//      Returns the number of parameters in an SQL statement
-
+//     This function should really talk to the dbms to determine the number of 
+//     "parameter markers" (not bound parameters) in the statement.  But, since
+//     Postgres doesn't support that, the driver should just count the number of markers
+//     and return that.  The reason the driver just can't say this function is unsupported
+//     like it does for SQLDescribeParam is that some applications don't care and try 
+//     to call it anyway.
+//     If the statement does not have parameters, it should just return 0.
 RETCODE SQL_API SQLNumParams(
         HSTMT      hstmt,
         SWORD  FAR *pcpar)
 {
 StatementClass *stmt = (StatementClass *) hstmt;
+char in_quote = FALSE;
+unsigned int i;
 
 
        if(!stmt)
                return SQL_INVALID_HANDLE;
 
-       //      If the statement does not have parameters, it should just return 0.
+       if (pcpar)
+               *pcpar = 0;
+       else
+               return SQL_ERROR;
 
-       if (pcpar) {
-               *pcpar = stmt->parameters_allocated;
-       }
 
-       return SQL_SUCCESS;
+       if(!stmt->statement) {
+               // no statement has been allocated
+               stmt->errormsg = "SQLNumParams called with no statement ready.";
+               stmt->errornumber = STMT_SEQUENCE_ERROR;
+               return SQL_ERROR;
+       } else {
+
+               for(i=0; i < strlen(stmt->statement); i++) {
+
+                       if(stmt->statement[i] == '?' && !in_quote)
+                               (*pcpar)++;
+                       else {
+                               if (stmt->statement[i] == '\'')
+                                       in_quote = (in_quote ? FALSE : TRUE);
+                       }
+               }
+
+               return SQL_SUCCESS;
+       }
 }
 
 /********************************************************************
index bad3f1a9114d0fe34e4059a4c6650d8557489bb3..22da73e0814be76c4bafc678c06ab3b3bd265865 100644 (file)
@@ -365,7 +365,12 @@ struct tm *tim;
                //      truncate the data.
         // return COPY_RESULT_TRUNCATED;
 
-               *pcbValue = cbValueMax -1;
+               //      LongVarBinary types do handle truncated multiple get calls
+               //      through convert_lo().
+
+               if (pcbValue)
+                       *pcbValue = cbValueMax -1;
+
                return COPY_OK;
 
     } else {
index 558fa66926b51b457aa31dc6dff45da6e5f5a29d..e04cc8b5696b7de8b562a69dcd5e20fdf723d720 100644 (file)
@@ -623,6 +623,15 @@ char temp[128];
                globals.unknown_sizes = atoi(temp);
 
 
+       //      Lie about supported functions?
+       SQLGetPrivateProfileString(DBMS_NAME, INI_LIE, "", 
+                               temp, sizeof(temp), ODBCINST_INI);
+       if ( temp[0] == '\0') 
+               globals.lie = DEFAULT_LIE;
+       else
+               globals.lie = atoi(temp);
+
+
        //      Readonly is stored in the driver section AND per datasource
        SQLGetPrivateProfileString(DBMS_NAME, INI_READONLY, "", 
                                temp, sizeof(temp), ODBCINST_INI);
index bedf2229371596f4473aeb6cf843d385c71cdef3..3c4ac4a6004d36bc70fc9f54d93a0e51be0d8e6b 100644 (file)
@@ -56,6 +56,7 @@
 #define INI_FAKEOIDINDEX                       "FakeOidIndex"
 #define INI_SHOWOIDCOLUMN                      "ShowOidColumn"
 #define INI_SHOWSYSTEMTABLES           "ShowSystemTables"
+#define INI_LIE                                                "Lie"
 #define INI_EXTRASYSTABLEPREFIXES      "ExtraSysTablePrefixes"
 
 /*     Connection Defaults */
@@ -74,6 +75,7 @@
 #define DEFAULT_FAKEOIDINDEX                   0
 #define DEFAULT_SHOWOIDCOLUMN                  0
 #define DEFAULT_SHOWSYSTEMTABLES               0               // dont show system tables
+#define DEFAULT_LIE                                            0
 
 #define DEFAULT_EXTRASYSTABLEPREFIXES  "dd_;"
 
index ae6c6074f753d9449f758c8220ce99968538c599..c619a230a48c9c639ad0f79a6de376896db75fdd 100644 (file)
@@ -307,7 +307,7 @@ char *p;
     case SQL_LOCK_TYPES: /* ODBC 2.0 */
         // which lock types does SQLSetPos support? (bitmask)
         // SQLSetPos doesn't exist yet
-        *((DWORD *)rgbInfoValue) = 0;
+        *((DWORD *)rgbInfoValue) = globals.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : 0;
         if(pcbInfoValue) { *pcbInfoValue = 4; }
         break;
 
@@ -424,9 +424,9 @@ char *p;
         break;
 
     case SQL_MULT_RESULT_SETS: /* ODBC 1.0 */
-        // do we support multiple result sets?
+        // do we support multiple result sets?  Not really, but say yes anyway?
         if (pcbInfoValue) *pcbInfoValue = 1;
-        strncpy_null((char *)rgbInfoValue, "N", (size_t)cbInfoValueMax);
+        strncpy_null((char *)rgbInfoValue, "Y", (size_t)cbInfoValueMax);
         break;
 
     case SQL_MULTIPLE_ACTIVE_TXN: /* ODBC 1.0 */
@@ -442,9 +442,7 @@ char *p;
         break;
 
     case SQL_NON_NULLABLE_COLUMNS: /* ODBC 1.0 */
-        // I think you can have NOT NULL columns with one of dal Zotto's
-        // patches, but for now we'll say no.
-        *((WORD *)rgbInfoValue) = (WORD)SQL_NNC_NULL;
+        *((WORD *)rgbInfoValue) = (WORD)SQL_NNC_NON_NULL;
         if(pcbInfoValue) { *pcbInfoValue = 2; }
         break;
 
@@ -516,13 +514,15 @@ char *p;
     case SQL_POS_OPERATIONS: /* ODBC 2.0 */
         // what functions does SQLSetPos support? (bitmask)
         // SQLSetPos does not exist yet
-        *((DWORD *)rgbInfoValue) = 0;
+        *((DWORD *)rgbInfoValue) = globals.lie ? (SQL_POS_POSITION | SQL_POS_REFRESH | SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD) : 0;
         if(pcbInfoValue) { *pcbInfoValue = 4; }
         break;
 
     case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
         // what 'positioned' functions are supported? (bitmask)
-        *((DWORD *)rgbInfoValue) = 0;
+        *((DWORD *)rgbInfoValue) = globals.lie ? (SQL_PS_POSITIONED_DELETE | 
+                                                                                       SQL_PS_POSITIONED_UPDATE | 
+                                                                                       SQL_PS_SELECT_FOR_UPDATE) : 0;
         if(pcbInfoValue) { *pcbInfoValue = 4; }
         break;
 
@@ -577,12 +577,15 @@ char *p;
         //  Driver doesn't support keyset-driven or mixed cursors, so
                //      not much point in saying row updates are supported
         if (pcbInfoValue) *pcbInfoValue = 1;
-        strncpy_null((char *)rgbInfoValue, "N", (size_t)cbInfoValueMax);
+        strncpy_null((char *)rgbInfoValue, globals.lie ? "Y" : "N", (size_t)cbInfoValueMax);
         break;
 
     case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */
         // what concurrency options are supported BY THE CURSOR? (bitmask)
-        *((DWORD *)rgbInfoValue) = (SQL_SCCO_READ_ONLY);
+        *((DWORD *)rgbInfoValue) = globals.lie ? (SQL_SCCO_READ_ONLY | 
+                                                                       SQL_SCCO_LOCK | 
+                                                                       SQL_SCCO_OPT_ROWVER | 
+                                                                       SQL_SCCO_OPT_VALUES) : (SQL_SCCO_READ_ONLY);
         if(pcbInfoValue) { *pcbInfoValue = 4; }
         break;
 
@@ -590,7 +593,11 @@ char *p;
         // what options are supported for scrollable cursors? (bitmask)
                // for declare/fetch, only FORWARD scrolling is allowed
                // otherwise, the result set is STATIC (to SQLExtendedFetch for example)
-        *((DWORD *)rgbInfoValue) = globals.use_declarefetch ? SQL_SO_FORWARD_ONLY : (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC);
+        *((DWORD *)rgbInfoValue) = globals.lie ? (SQL_SO_FORWARD_ONLY | 
+                                                                       SQL_SO_STATIC | 
+                                                                       SQL_SO_KEYSET_DRIVEN | 
+                                                                       SQL_SO_DYNAMIC | 
+                                                                       SQL_SO_MIXED) : (globals.use_declarefetch ? SQL_SO_FORWARD_ONLY : (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC));
         if(pcbInfoValue) { *pcbInfoValue = 4; }
         break;
 
@@ -620,7 +627,7 @@ char *p;
         // can changes made inside a cursor be detected? (or something like that)
         // (bitmask)
         // only applies to SQLSetPos, which doesn't exist yet.
-        *((DWORD *)rgbInfoValue) = 0;
+        *((DWORD *)rgbInfoValue) = globals.lie ? (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES) : 0;
         if(pcbInfoValue) { *pcbInfoValue = 4; }
         break;
 
@@ -805,149 +812,152 @@ RETCODE SQL_API SQLGetFunctions(
 {
     if (fFunction == SQL_API_ALL_FUNCTIONS) {
 
+               if (globals.lie) {
+                       int i;
+                       memset(pfExists, 0, sizeof(UWORD)*100);
 
-#ifdef GETINFO_LIE
-        int i;
-        memset(pfExists, 0, sizeof(UWORD)*100);
-
-        pfExists[SQL_API_SQLALLOCENV] = TRUE;
-        pfExists[SQL_API_SQLFREEENV] = TRUE;
-        for (i = SQL_API_SQLALLOCCONNECT; i <= SQL_NUM_FUNCTIONS; i++)
-            pfExists[i] = TRUE;
-        for (i = SQL_EXT_API_START; i <= SQL_EXT_API_LAST; i++)
-            pfExists[i] = TRUE;
-#else
-        memset(pfExists, 0, sizeof(UWORD)*100);
-
-        // ODBC core functions
-        pfExists[SQL_API_SQLALLOCCONNECT]     = TRUE;
-        pfExists[SQL_API_SQLALLOCENV]         = TRUE;
-        pfExists[SQL_API_SQLALLOCSTMT]        = TRUE;
-        pfExists[SQL_API_SQLBINDCOL]          = TRUE;  
-        pfExists[SQL_API_SQLCANCEL]           = TRUE;
-        pfExists[SQL_API_SQLCOLATTRIBUTES]    = TRUE;
-        pfExists[SQL_API_SQLCONNECT]          = TRUE;
-        pfExists[SQL_API_SQLDESCRIBECOL]      = TRUE;  // partial
-        pfExists[SQL_API_SQLDISCONNECT]       = TRUE;
-        pfExists[SQL_API_SQLERROR]            = TRUE;
-        pfExists[SQL_API_SQLEXECDIRECT]       = TRUE;
-        pfExists[SQL_API_SQLEXECUTE]          = TRUE;
-        pfExists[SQL_API_SQLFETCH]            = TRUE;
-        pfExists[SQL_API_SQLFREECONNECT]      = TRUE;
-        pfExists[SQL_API_SQLFREEENV]          = TRUE;
-        pfExists[SQL_API_SQLFREESTMT]         = TRUE;
-        pfExists[SQL_API_SQLGETCURSORNAME]    = TRUE;
-        pfExists[SQL_API_SQLNUMRESULTCOLS]    = TRUE;
-        pfExists[SQL_API_SQLPREPARE]          = TRUE;  // complete?
-        pfExists[SQL_API_SQLROWCOUNT]         = TRUE;
-        pfExists[SQL_API_SQLSETCURSORNAME]    = TRUE;
-        pfExists[SQL_API_SQLSETPARAM]         = FALSE; // odbc 1.0
-        pfExists[SQL_API_SQLTRANSACT]         = TRUE;
-
-        // ODBC level 1 functions
-        pfExists[SQL_API_SQLBINDPARAMETER]    = TRUE;
-        pfExists[SQL_API_SQLCOLUMNS]          = TRUE;
-        pfExists[SQL_API_SQLDRIVERCONNECT]    = TRUE;
-        pfExists[SQL_API_SQLGETCONNECTOPTION] = TRUE;  // partial
-        pfExists[SQL_API_SQLGETDATA]          = TRUE;
-        pfExists[SQL_API_SQLGETFUNCTIONS]     = TRUE;                                                       
-        pfExists[SQL_API_SQLGETINFO]          = TRUE;
-        pfExists[SQL_API_SQLGETSTMTOPTION]    = TRUE;  // partial
-        pfExists[SQL_API_SQLGETTYPEINFO]      = TRUE;
-        pfExists[SQL_API_SQLPARAMDATA]        = TRUE;
-        pfExists[SQL_API_SQLPUTDATA]          = TRUE;
-        pfExists[SQL_API_SQLSETCONNECTOPTION] = TRUE;  // partial
-        pfExists[SQL_API_SQLSETSTMTOPTION]    = TRUE;
-        pfExists[SQL_API_SQLSPECIALCOLUMNS]   = TRUE;
-        pfExists[SQL_API_SQLSTATISTICS]       = TRUE;
-        pfExists[SQL_API_SQLTABLES]           = TRUE;
-
-        // ODBC level 2 functions
-        pfExists[SQL_API_SQLBROWSECONNECT]    = FALSE;
-        pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE;
-        pfExists[SQL_API_SQLDATASOURCES]      = FALSE;  // only implemented by DM
-        pfExists[SQL_API_SQLDESCRIBEPARAM]    = TRUE;
-        pfExists[SQL_API_SQLDRIVERS]          = FALSE;  // only implemented by DM
-        pfExists[SQL_API_SQLEXTENDEDFETCH]    = globals.use_declarefetch ? FALSE : TRUE;
-        pfExists[SQL_API_SQLFOREIGNKEYS]      = TRUE;
-        pfExists[SQL_API_SQLMORERESULTS]      = FALSE;
-        pfExists[SQL_API_SQLNATIVESQL]        = TRUE;
-        pfExists[SQL_API_SQLNUMPARAMS]        = TRUE;
-        pfExists[SQL_API_SQLPARAMOPTIONS]     = FALSE;
-        pfExists[SQL_API_SQLPRIMARYKEYS]      = TRUE;
-        pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
-        pfExists[SQL_API_SQLPROCEDURES]       = FALSE;
-        pfExists[SQL_API_SQLSETPOS]           = FALSE;
-        pfExists[SQL_API_SQLSETSCROLLOPTIONS] = FALSE; // odbc 1.0
-        pfExists[SQL_API_SQLTABLEPRIVILEGES]  = FALSE;
-#endif
+                       pfExists[SQL_API_SQLALLOCENV] = TRUE;
+                       pfExists[SQL_API_SQLFREEENV] = TRUE;
+                       for (i = SQL_API_SQLALLOCCONNECT; i <= SQL_NUM_FUNCTIONS; i++)
+                               pfExists[i] = TRUE;
+                       for (i = SQL_EXT_API_START; i <= SQL_EXT_API_LAST; i++)
+                               pfExists[i] = TRUE;
+               }
+               else {
+                       memset(pfExists, 0, sizeof(UWORD)*100);
+
+                       // ODBC core functions
+                       pfExists[SQL_API_SQLALLOCCONNECT]     = TRUE;
+                       pfExists[SQL_API_SQLALLOCENV]         = TRUE;
+                       pfExists[SQL_API_SQLALLOCSTMT]        = TRUE;
+                       pfExists[SQL_API_SQLBINDCOL]          = TRUE;  
+                       pfExists[SQL_API_SQLCANCEL]           = TRUE;
+                       pfExists[SQL_API_SQLCOLATTRIBUTES]    = TRUE;
+                       pfExists[SQL_API_SQLCONNECT]          = TRUE;
+                       pfExists[SQL_API_SQLDESCRIBECOL]      = TRUE;  // partial
+                       pfExists[SQL_API_SQLDISCONNECT]       = TRUE;
+                       pfExists[SQL_API_SQLERROR]            = TRUE;
+                       pfExists[SQL_API_SQLEXECDIRECT]       = TRUE;
+                       pfExists[SQL_API_SQLEXECUTE]          = TRUE;
+                       pfExists[SQL_API_SQLFETCH]            = TRUE;
+                       pfExists[SQL_API_SQLFREECONNECT]      = TRUE;
+                       pfExists[SQL_API_SQLFREEENV]          = TRUE;
+                       pfExists[SQL_API_SQLFREESTMT]         = TRUE;
+                       pfExists[SQL_API_SQLGETCURSORNAME]    = TRUE;
+                       pfExists[SQL_API_SQLNUMRESULTCOLS]    = TRUE;
+                       pfExists[SQL_API_SQLPREPARE]          = TRUE;  // complete?
+                       pfExists[SQL_API_SQLROWCOUNT]         = TRUE;
+                       pfExists[SQL_API_SQLSETCURSORNAME]    = TRUE;
+                       pfExists[SQL_API_SQLSETPARAM]         = FALSE; // odbc 1.0
+                       pfExists[SQL_API_SQLTRANSACT]         = TRUE;
+
+                       // ODBC level 1 functions
+                       pfExists[SQL_API_SQLBINDPARAMETER]    = TRUE;
+                       pfExists[SQL_API_SQLCOLUMNS]          = TRUE;
+                       pfExists[SQL_API_SQLDRIVERCONNECT]    = TRUE;
+                       pfExists[SQL_API_SQLGETCONNECTOPTION] = TRUE;  // partial
+                       pfExists[SQL_API_SQLGETDATA]          = TRUE;
+                       pfExists[SQL_API_SQLGETFUNCTIONS]     = TRUE;                                                       
+                       pfExists[SQL_API_SQLGETINFO]          = TRUE;
+                       pfExists[SQL_API_SQLGETSTMTOPTION]    = TRUE;  // partial
+                       pfExists[SQL_API_SQLGETTYPEINFO]      = TRUE;
+                       pfExists[SQL_API_SQLPARAMDATA]        = TRUE;
+                       pfExists[SQL_API_SQLPUTDATA]          = TRUE;
+                       pfExists[SQL_API_SQLSETCONNECTOPTION] = TRUE;  // partial
+                       pfExists[SQL_API_SQLSETSTMTOPTION]    = TRUE;
+                       pfExists[SQL_API_SQLSPECIALCOLUMNS]   = TRUE;
+                       pfExists[SQL_API_SQLSTATISTICS]       = TRUE;
+                       pfExists[SQL_API_SQLTABLES]           = TRUE;
+
+                       // ODBC level 2 functions
+                       pfExists[SQL_API_SQLBROWSECONNECT]    = FALSE;
+                       pfExists[SQL_API_SQLCOLUMNPRIVILEGES] = FALSE;
+                       pfExists[SQL_API_SQLDATASOURCES]      = FALSE;  // only implemented by DM
+                       pfExists[SQL_API_SQLDESCRIBEPARAM]    = FALSE;  // not properly implemented
+                       pfExists[SQL_API_SQLDRIVERS]          = FALSE;  // only implemented by DM
+                       pfExists[SQL_API_SQLEXTENDEDFETCH]    = globals.use_declarefetch ? FALSE : TRUE;
+                       pfExists[SQL_API_SQLFOREIGNKEYS]      = TRUE;
+                       pfExists[SQL_API_SQLMORERESULTS]      = TRUE;
+                       pfExists[SQL_API_SQLNATIVESQL]        = TRUE;
+                       pfExists[SQL_API_SQLNUMPARAMS]        = TRUE;
+                       pfExists[SQL_API_SQLPARAMOPTIONS]     = FALSE;
+                       pfExists[SQL_API_SQLPRIMARYKEYS]      = TRUE;
+                       pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
+                       pfExists[SQL_API_SQLPROCEDURES]       = FALSE;
+                       pfExists[SQL_API_SQLSETPOS]           = FALSE;
+                       pfExists[SQL_API_SQLSETSCROLLOPTIONS] = FALSE;  // odbc 1.0
+                       pfExists[SQL_API_SQLTABLEPRIVILEGES]  = FALSE;
+               }
     } else {
-#ifdef GETINFO_LIE
-        *pfExists = TRUE;
-#else
-        switch(fFunction) {
-        case SQL_API_SQLALLOCCONNECT:     *pfExists = TRUE; break;
-        case SQL_API_SQLALLOCENV:         *pfExists = TRUE; break;
-        case SQL_API_SQLALLOCSTMT:        *pfExists = TRUE; break;
-        case SQL_API_SQLBINDCOL:          *pfExists = TRUE; break;
-        case SQL_API_SQLCANCEL:           *pfExists = TRUE; break;
-        case SQL_API_SQLCOLATTRIBUTES:    *pfExists = TRUE; break;
-        case SQL_API_SQLCONNECT:          *pfExists = TRUE; break;
-        case SQL_API_SQLDESCRIBECOL:      *pfExists = TRUE; break;  // partial
-        case SQL_API_SQLDISCONNECT:       *pfExists = TRUE; break;
-        case SQL_API_SQLERROR:            *pfExists = TRUE; break;
-        case SQL_API_SQLEXECDIRECT:       *pfExists = TRUE; break;
-        case SQL_API_SQLEXECUTE:          *pfExists = TRUE; break;
-        case SQL_API_SQLFETCH:            *pfExists = TRUE; break;
-        case SQL_API_SQLFREECONNECT:      *pfExists = TRUE; break;
-        case SQL_API_SQLFREEENV:          *pfExists = TRUE; break;
-        case SQL_API_SQLFREESTMT:         *pfExists = TRUE; break;
-        case SQL_API_SQLGETCURSORNAME:    *pfExists = TRUE; break;
-        case SQL_API_SQLNUMRESULTCOLS:    *pfExists = TRUE; break;
-        case SQL_API_SQLPREPARE:          *pfExists = TRUE; break;
-        case SQL_API_SQLROWCOUNT:         *pfExists = TRUE; break;
-        case SQL_API_SQLSETCURSORNAME:    *pfExists = TRUE; break;
-        case SQL_API_SQLSETPARAM:         *pfExists = FALSE; break; // odbc 1.0
-        case SQL_API_SQLTRANSACT:         *pfExists = TRUE; break;
-
-            // ODBC level 1 functions
-        case SQL_API_SQLBINDPARAMETER:    *pfExists = TRUE; break;
-        case SQL_API_SQLCOLUMNS:          *pfExists = TRUE; break;
-        case SQL_API_SQLDRIVERCONNECT:    *pfExists = TRUE; break;
-        case SQL_API_SQLGETCONNECTOPTION: *pfExists = TRUE; break;  // partial
-        case SQL_API_SQLGETDATA:          *pfExists = TRUE; break;
-        case SQL_API_SQLGETFUNCTIONS:     *pfExists = TRUE; break;
-        case SQL_API_SQLGETINFO:          *pfExists = TRUE; break;
-        case SQL_API_SQLGETSTMTOPTION:    *pfExists = TRUE; break;  // partial
-        case SQL_API_SQLGETTYPEINFO:      *pfExists = TRUE; break;
-        case SQL_API_SQLPARAMDATA:        *pfExists = TRUE; break;
-        case SQL_API_SQLPUTDATA:          *pfExists = TRUE; break;
-        case SQL_API_SQLSETCONNECTOPTION: *pfExists = TRUE; break;  // partial
-        case SQL_API_SQLSETSTMTOPTION:    *pfExists = TRUE; break;
-        case SQL_API_SQLSPECIALCOLUMNS:   *pfExists = TRUE; break;
-        case SQL_API_SQLSTATISTICS:       *pfExists = TRUE; break;
-        case SQL_API_SQLTABLES:           *pfExists = TRUE; break;
-
-            // ODBC level 2 functions
-        case SQL_API_SQLBROWSECONNECT:    *pfExists = FALSE; break;
-        case SQL_API_SQLCOLUMNPRIVILEGES: *pfExists = FALSE; break;
-        case SQL_API_SQLDATASOURCES:      *pfExists = FALSE; break;  // only implemented by DM
-        case SQL_API_SQLDESCRIBEPARAM:    *pfExists = TRUE; break;
-        case SQL_API_SQLDRIVERS:          *pfExists = FALSE; break;  // only implemented by DM
-        case SQL_API_SQLEXTENDEDFETCH:    *pfExists = globals.use_declarefetch ? FALSE : TRUE; break;
-        case SQL_API_SQLFOREIGNKEYS:      *pfExists = TRUE; break;
-        case SQL_API_SQLMORERESULTS:      *pfExists = FALSE; break;
-        case SQL_API_SQLNATIVESQL:        *pfExists = TRUE; break;
-        case SQL_API_SQLNUMPARAMS:        *pfExists = TRUE; break;
-        case SQL_API_SQLPARAMOPTIONS:     *pfExists = FALSE; break;
-        case SQL_API_SQLPRIMARYKEYS:      *pfExists = TRUE; break;
-        case SQL_API_SQLPROCEDURECOLUMNS: *pfExists = FALSE; break;
-        case SQL_API_SQLPROCEDURES:       *pfExists = FALSE; break;
-        case SQL_API_SQLSETPOS:           *pfExists = FALSE; break;
-        case SQL_API_SQLSETSCROLLOPTIONS: *pfExists = FALSE; break;    // odbc 1.0
-        case SQL_API_SQLTABLEPRIVILEGES:  *pfExists = FALSE; break;
-        }
-#endif
+
+               if (globals.lie)
+                       *pfExists = TRUE;
+
+               else {
+
+                       switch(fFunction) {
+                       case SQL_API_SQLALLOCCONNECT:     *pfExists = TRUE; break;
+                       case SQL_API_SQLALLOCENV:         *pfExists = TRUE; break;
+                       case SQL_API_SQLALLOCSTMT:        *pfExists = TRUE; break;
+                       case SQL_API_SQLBINDCOL:          *pfExists = TRUE; break;
+                       case SQL_API_SQLCANCEL:           *pfExists = TRUE; break;
+                       case SQL_API_SQLCOLATTRIBUTES:    *pfExists = TRUE; break;
+                       case SQL_API_SQLCONNECT:          *pfExists = TRUE; break;
+                       case SQL_API_SQLDESCRIBECOL:      *pfExists = TRUE; break;  // partial
+                       case SQL_API_SQLDISCONNECT:       *pfExists = TRUE; break;
+                       case SQL_API_SQLERROR:            *pfExists = TRUE; break;
+                       case SQL_API_SQLEXECDIRECT:       *pfExists = TRUE; break;
+                       case SQL_API_SQLEXECUTE:          *pfExists = TRUE; break;
+                       case SQL_API_SQLFETCH:            *pfExists = TRUE; break;
+                       case SQL_API_SQLFREECONNECT:      *pfExists = TRUE; break;
+                       case SQL_API_SQLFREEENV:          *pfExists = TRUE; break;
+                       case SQL_API_SQLFREESTMT:         *pfExists = TRUE; break;
+                       case SQL_API_SQLGETCURSORNAME:    *pfExists = TRUE; break;
+                       case SQL_API_SQLNUMRESULTCOLS:    *pfExists = TRUE; break;
+                       case SQL_API_SQLPREPARE:          *pfExists = TRUE; break;
+                       case SQL_API_SQLROWCOUNT:         *pfExists = TRUE; break;
+                       case SQL_API_SQLSETCURSORNAME:    *pfExists = TRUE; break;
+                       case SQL_API_SQLSETPARAM:         *pfExists = FALSE; break; // odbc 1.0
+                       case SQL_API_SQLTRANSACT:         *pfExists = TRUE; break;
+
+                               // ODBC level 1 functions
+                       case SQL_API_SQLBINDPARAMETER:    *pfExists = TRUE; break;
+                       case SQL_API_SQLCOLUMNS:          *pfExists = TRUE; break;
+                       case SQL_API_SQLDRIVERCONNECT:    *pfExists = TRUE; break;
+                       case SQL_API_SQLGETCONNECTOPTION: *pfExists = TRUE; break;  // partial
+                       case SQL_API_SQLGETDATA:          *pfExists = TRUE; break;
+                       case SQL_API_SQLGETFUNCTIONS:     *pfExists = TRUE; break;
+                       case SQL_API_SQLGETINFO:          *pfExists = TRUE; break;
+                       case SQL_API_SQLGETSTMTOPTION:    *pfExists = TRUE; break;  // partial
+                       case SQL_API_SQLGETTYPEINFO:      *pfExists = TRUE; break;
+                       case SQL_API_SQLPARAMDATA:        *pfExists = TRUE; break;
+                       case SQL_API_SQLPUTDATA:          *pfExists = TRUE; break;
+                       case SQL_API_SQLSETCONNECTOPTION: *pfExists = TRUE; break;  // partial
+                       case SQL_API_SQLSETSTMTOPTION:    *pfExists = TRUE; break;
+                       case SQL_API_SQLSPECIALCOLUMNS:   *pfExists = TRUE; break;
+                       case SQL_API_SQLSTATISTICS:       *pfExists = TRUE; break;
+                       case SQL_API_SQLTABLES:           *pfExists = TRUE; break;
+
+                               // ODBC level 2 functions
+                       case SQL_API_SQLBROWSECONNECT:    *pfExists = FALSE; break;
+                       case SQL_API_SQLCOLUMNPRIVILEGES: *pfExists = FALSE; break;
+                       case SQL_API_SQLDATASOURCES:      *pfExists = FALSE; break;  // only implemented by DM
+                       case SQL_API_SQLDESCRIBEPARAM:    *pfExists = FALSE; break;  // not properly implemented
+                       case SQL_API_SQLDRIVERS:          *pfExists = FALSE; break;  // only implemented by DM
+                       case SQL_API_SQLEXTENDEDFETCH:    *pfExists = globals.use_declarefetch ? FALSE : TRUE; break;
+                       case SQL_API_SQLFOREIGNKEYS:      *pfExists = TRUE; break;
+                       case SQL_API_SQLMORERESULTS:      *pfExists = TRUE; break;
+                       case SQL_API_SQLNATIVESQL:        *pfExists = TRUE; break;
+                       case SQL_API_SQLNUMPARAMS:        *pfExists = TRUE; break;
+                       case SQL_API_SQLPARAMOPTIONS:     *pfExists = FALSE; break;
+                       case SQL_API_SQLPRIMARYKEYS:      *pfExists = TRUE; break;
+                       case SQL_API_SQLPROCEDURECOLUMNS: *pfExists = FALSE; break;
+                       case SQL_API_SQLPROCEDURES:       *pfExists = FALSE; break;
+                       case SQL_API_SQLSETPOS:           *pfExists = FALSE; break;
+                       case SQL_API_SQLSETSCROLLOPTIONS: *pfExists = FALSE; break;     // odbc 1.0
+                       case SQL_API_SQLTABLEPRIVILEGES:  *pfExists = FALSE; break;
+                       }
+               }
     }
 
     return SQL_SUCCESS;
@@ -974,7 +984,7 @@ RETCODE result;
 char *tableType;
 char tables_query[MAX_STATEMENT_LEN];
 char table_name[MAX_INFO_STRING], table_owner[MAX_INFO_STRING], relhasrules[MAX_INFO_STRING];
-SDWORD table_name_len, table_owner_len, relhasrules_len;
+// SDWORD table_name_len, table_owner_len, relhasrules_len;
 ConnInfo *ci;
 char *prefix[32], prefixes[MEDIUM_REGISTRY_LEN];
 char *table_type[32], table_types[MAX_INFO_STRING];
@@ -1082,7 +1092,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
        }
 
     result = SQLBindCol(htbl_stmt, 1, SQL_C_CHAR,
-                        table_name, MAX_INFO_STRING, &table_name_len);
+                        table_name, MAX_INFO_STRING, NULL /* &table_name_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = tbl_stmt->errormsg;
                stmt->errornumber = tbl_stmt->errornumber;
@@ -1091,7 +1101,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
     }
 
     result = SQLBindCol(htbl_stmt, 2, SQL_C_CHAR,
-                        table_owner, MAX_INFO_STRING, &table_owner_len);
+                        table_owner, MAX_INFO_STRING, NULL /* &table_owner_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = tbl_stmt->errormsg;
                stmt->errornumber = tbl_stmt->errornumber;
@@ -1099,7 +1109,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
         return SQL_ERROR;
     }
     result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR,
-                        relhasrules, MAX_INFO_STRING, &relhasrules_len);
+                        relhasrules, MAX_INFO_STRING, NULL /* &relhasrules_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = tbl_stmt->errormsg;
                stmt->errornumber = tbl_stmt->errornumber;
@@ -1229,9 +1239,11 @@ 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, field_length, mod_length;
 Int4 field_type;
-SDWORD table_owner_len, table_name_len, field_name_len,
+char not_null[2];
+/* SDWORD table_owner_len, table_name_len, field_name_len,
     field_type_len, field_type_name_len, field_number_len,
-       field_length_len, mod_length_len;
+       field_length_len, mod_length_len, not_null_len;
+*/
 ConnInfo *ci;
 
 
@@ -1249,7 +1261,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
        // **********************************************************************
        //      Create the query to find out the columns (Note: pre 6.3 did not have the atttypmod field)
        // **********************************************************************
-       sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid,t.typname, a.attnum, a.attlen, %s from pg_user u, pg_class c, pg_attribute a, pg_type t where "
+       sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid,t.typname, a.attnum, a.attlen, %s, a.attnotnull from pg_user u, pg_class c, pg_attribute a, pg_type t where "
                "int4out(u.usesysid) = int4out(c.relowner) and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
                PROTOCOL_62(ci) ? "a.attlen" : "a.atttypmod");
 
@@ -1280,7 +1292,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
     }
 
     result = SQLBindCol(hcol_stmt, 1, SQL_C_CHAR,
-                        table_owner, MAX_INFO_STRING, &table_owner_len);
+                        table_owner, MAX_INFO_STRING, NULL /* &table_owner_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = col_stmt->errormsg;
                stmt->errornumber = col_stmt->errornumber;
@@ -1289,7 +1301,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
     }
 
     result = SQLBindCol(hcol_stmt, 2, SQL_C_CHAR,
-                        table_name, MAX_INFO_STRING, &table_name_len);
+                        table_name, MAX_INFO_STRING, NULL /* &table_name_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = col_stmt->errormsg;
                stmt->errornumber = col_stmt->errornumber;
@@ -1298,7 +1310,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
     }
 
     result = SQLBindCol(hcol_stmt, 3, SQL_C_CHAR,
-                        field_name, MAX_INFO_STRING, &field_name_len);
+                        field_name, MAX_INFO_STRING, NULL /* &field_name_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = col_stmt->errormsg;
                stmt->errornumber = col_stmt->errornumber;
@@ -1307,7 +1319,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
     }
 
     result = SQLBindCol(hcol_stmt, 4, SQL_C_DEFAULT,
-                        &field_type, 4, &field_type_len);
+                        &field_type, 4, NULL /* &field_type_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = col_stmt->errormsg;
                stmt->errornumber = col_stmt->errornumber;
@@ -1316,7 +1328,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
     }
 
     result = SQLBindCol(hcol_stmt, 5, SQL_C_CHAR,
-                        field_type_name, MAX_INFO_STRING, &field_type_name_len);
+                        field_type_name, MAX_INFO_STRING, NULL /* &field_type_name_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = col_stmt->errormsg;
                stmt->errornumber = col_stmt->errornumber;
@@ -1325,7 +1337,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
     }
 
     result = SQLBindCol(hcol_stmt, 6, SQL_C_DEFAULT,
-                        &field_number, MAX_INFO_STRING, &field_number_len);
+                        &field_number, MAX_INFO_STRING, NULL /* &field_number_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = col_stmt->errormsg;
                stmt->errornumber = col_stmt->errornumber;
@@ -1334,7 +1346,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
     }
 
     result = SQLBindCol(hcol_stmt, 7, SQL_C_DEFAULT,
-                        &field_length, MAX_INFO_STRING, &field_length_len);
+                        &field_length, MAX_INFO_STRING, NULL /* &field_length_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = col_stmt->errormsg;
                stmt->errornumber = col_stmt->errornumber;
@@ -1343,7 +1355,16 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
     }
 
     result = SQLBindCol(hcol_stmt, 8, SQL_C_DEFAULT,
-                        &mod_length, MAX_INFO_STRING, &mod_length_len);
+                        &mod_length, MAX_INFO_STRING, NULL /* &mod_length_len */);
+    if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+               stmt->errormsg = col_stmt->errormsg;
+               stmt->errornumber = col_stmt->errornumber;
+               SQLFreeStmt(hcol_stmt, SQL_DROP);
+        return SQL_ERROR;
+    }
+
+    result = SQLBindCol(hcol_stmt, 9, SQL_C_CHAR,
+                        &not_null, MAX_INFO_STRING, NULL /* &not_null_len */);
     if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
                stmt->errormsg = col_stmt->errormsg;
                stmt->errornumber = col_stmt->errornumber;
@@ -1458,7 +1479,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
 
                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], pgtype_nullable(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], "");
 
         QR_add_tuple(stmt->result, row);
diff --git a/src/interfaces/odbc/lobj.c b/src/interfaces/odbc/lobj.c
new file mode 100644 (file)
index 0000000..29cdd2e
--- /dev/null
@@ -0,0 +1,197 @@
+
+/* Module:          lobj.c
+ *
+ * Description:     This module contains routines related to manipulating
+ *                  large objects.
+ *
+ * Classes:         none
+ *
+ * API functions:   none
+ *
+ * Comments:        See "notice.txt" for copyright and license information.
+ *
+ */
+
+#include "lobj.h"
+#include "psqlodbc.h"
+#include "connection.h"
+
+Oid
+lo_creat(ConnectionClass *conn, int mode)
+{
+LO_ARG argv[1];
+int retval, result_len;
+
+       argv[0].isint = 1;
+       argv[0].len = 4;
+       argv[0].u.integer = mode;
+
+       if ( ! CC_send_function(conn, LO_CREAT, &retval, &result_len, 1, argv, 1))
+               return 0;       // invalid oid
+       else
+               return retval;
+
+
+}
+
+int
+lo_open(ConnectionClass *conn, int lobjId, int mode)
+{
+int fd;
+int result_len;
+LO_ARG argv[2];
+
+
+       argv[0].isint = 1;
+       argv[0].len = 4;
+       argv[0].u.integer = lobjId;
+
+       argv[1].isint = 1;
+       argv[1].len = 4;
+       argv[1].u.integer = mode;
+
+       if ( ! CC_send_function(conn, LO_OPEN, &fd, &result_len, 1, argv, 2))
+               return -1;
+
+       if (fd >= 0 && lo_lseek(conn, fd, 0L, SEEK_SET) < 0)
+               return -1;
+
+       return fd;
+}
+
+int 
+lo_close(ConnectionClass *conn, int fd)
+{
+LO_ARG argv[1];
+int retval, result_len;
+
+
+       argv[0].isint = 1;
+       argv[0].len = 4;
+       argv[0].u.integer = fd;
+
+       if ( ! CC_send_function(conn, LO_CLOSE, &retval, &result_len, 1, argv, 1))
+               return -1;
+
+       else
+               return retval;
+
+}
+
+
+int
+lo_read(ConnectionClass *conn, int fd, char *buf, int len)
+{
+LO_ARG argv[2];
+int result_len;
+
+
+       argv[0].isint = 1;
+       argv[0].len = 4;
+       argv[0].u.integer = fd;
+
+       argv[1].isint = 1;
+       argv[1].len = 4;
+       argv[1].u.integer = len;
+
+       if ( ! CC_send_function(conn, LO_READ, (int *) buf, &result_len, 0, argv, 2))
+               return -1;
+
+       else
+               return result_len;
+}
+
+int
+lo_write(ConnectionClass *conn, int fd, char *buf, int len)
+{
+LO_ARG argv[2];
+int retval, result_len;
+
+
+       if (len <= 0)
+               return 0;
+
+       argv[0].isint = 1;
+       argv[0].len = 4;
+       argv[0].u.integer = fd;
+
+       argv[1].isint = 0;
+       argv[1].len = len;
+       argv[1].u.ptr = (char *) buf;
+
+       if ( ! CC_send_function(conn, LO_WRITE, &retval, &result_len, 1, argv, 2))
+               return -1;
+
+       else
+               return retval;
+}
+
+int
+lo_lseek(ConnectionClass *conn, int fd, int offset, int whence)
+{
+LO_ARG argv[3];
+int retval, result_len;
+
+
+       argv[0].isint = 1;
+       argv[0].len = 4;
+       argv[0].u.integer = fd;
+
+       argv[1].isint = 1;
+       argv[1].len = 4;
+       argv[1].u.integer = offset;
+
+       argv[2].isint = 1;
+       argv[2].len = 4;
+       argv[2].u.integer = whence;
+
+       if ( ! CC_send_function(conn, LO_LSEEK, &retval, &result_len, 1, argv, 3))
+               return -1;
+
+       else
+               return retval;
+}
+
+int
+lo_tell(ConnectionClass *conn, int fd)
+{
+LO_ARG argv[1];
+int retval, result_len;
+
+
+       argv[0].isint = 1;
+       argv[0].len = 4;
+       argv[0].u.integer = fd;
+
+       if ( ! CC_send_function(conn, LO_TELL, &retval, &result_len, 1, argv, 1))
+               return -1;
+
+       else
+               return retval;
+}
+
+int 
+lo_unlink(ConnectionClass *conn, Oid lobjId)
+{
+LO_ARG argv[1];
+int retval, result_len;
+
+
+       argv[0].isint = 1;
+       argv[0].len = 4;
+       argv[0].u.integer = lobjId;
+
+       if ( ! CC_send_function(conn, LO_UNLINK, &retval, &result_len, 1, argv, 1))
+               return -1;
+
+       else
+               return retval;
+}
+
+
+
+
+
+
+
+
diff --git a/src/interfaces/odbc/lobj.h b/src/interfaces/odbc/lobj.h
new file mode 100644 (file)
index 0000000..b5ff7e3
--- /dev/null
@@ -0,0 +1,48 @@
+
+/* File:            lobj.h
+ *
+ * Description:     See "lobj.c"
+ *
+ * Comments:        See "notice.txt" for copyright and license information.
+ *
+ */
+
+#ifndef __LOBJ_H__
+#define __LOBJ_H__
+
+
+#include "psqlodbc.h"
+
+typedef struct lo_arg {
+       int             isint;
+       int             len;
+       union
+       {
+               int             integer;
+               char    *ptr;
+       } u;
+};
+
+#define LO_CREAT               957
+#define LO_OPEN                        952
+#define LO_CLOSE               953
+#define LO_READ                        954
+#define LO_WRITE               955
+#define LO_LSEEK               956
+#define LO_TELL                        958
+#define LO_UNLINK              964
+
+#define INV_WRITE              0x00020000
+#define INV_READ               0x00040000
+
+Oid lo_creat(ConnectionClass *conn, int mode);
+int lo_open(ConnectionClass *conn, int lobjId, int mode);
+int lo_close(ConnectionClass *conn, int fd);
+int lo_read(ConnectionClass *conn, int fd, char *buf, int len);
+int lo_write(ConnectionClass *conn, int fd, char *buf, int len);
+int lo_lseek(ConnectionClass *conn, int fd, int offset, int len);
+int lo_tell(ConnectionClass *conn, int fd);
+int lo_unlink(ConnectionClass *conn, Oid lobjId);
+
+#endif
+
index 716cfcdfdf3e386520e9bd90dd3681d933154f84..ff9c53200c09e56883fa9c90409abf38f417055f 100644 (file)
@@ -163,14 +163,28 @@ char changed = FALSE;
 
                break;
 
+       case SQL_KEYSET_SIZE:
+               mylog("SetStmtOption(): SQL_KEYSET_SIZE = %d\n", vParam);
+               if (globals.lie)
+                       stmt->keyset_size = vParam;
+               else {
+                       stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
+                       stmt->errormsg = "Driver does not support keyset size option";
+                       return SQL_ERROR;
+               }
+               break;
+
        case SQL_CONCURRENCY:
                //      positioned update isn't supported so cursor concurrency is read-only
                mylog("SetStmtOption(): SQL_CONCURRENCY = %d\n", vParam);
 
-               stmt->scroll_concurrency = SQL_CONCUR_READ_ONLY;
-               if (vParam != SQL_CONCUR_READ_ONLY)
-                       changed = TRUE;
-
+               if (globals.lie)
+                       stmt->scroll_concurrency = vParam;
+               else {
+                       stmt->scroll_concurrency = SQL_CONCUR_READ_ONLY;
+                       if (vParam != SQL_CONCUR_READ_ONLY)
+                               changed = TRUE;
+               }
                break;
                
        case SQL_CURSOR_TYPE:
@@ -178,25 +192,28 @@ char changed = FALSE;
                //      otherwise, it can only be forward or static.
                mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam);
 
-               if (globals.use_declarefetch) {
-                       stmt->cursor_type = SQL_CURSOR_FORWARD_ONLY;
-                       if (vParam != SQL_CURSOR_FORWARD_ONLY) 
-                               changed = TRUE;
-               }
+               if (globals.lie)
+                       stmt->cursor_type = vParam;
                else {
-                       if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
-                               stmt->cursor_type = vParam;             // valid type
+                       if (globals.use_declarefetch) {
+                               stmt->cursor_type = SQL_CURSOR_FORWARD_ONLY;
+                               if (vParam != SQL_CURSOR_FORWARD_ONLY) 
+                                       changed = TRUE;
+                       }
                        else {
-                               stmt->cursor_type = SQL_CURSOR_STATIC;
-                               changed = TRUE;
+                               if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
+                                       stmt->cursor_type = vParam;             // valid type
+                               else {
+                                       stmt->cursor_type = SQL_CURSOR_STATIC;
+                                       changed = TRUE;
+                               }
                        }
                }
-
                break;
 
        case SQL_SIMULATE_CURSOR:
                stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-               stmt->errormsg = "Simulated positioned update/delete not supported";
+               stmt->errormsg = "Simulated positioned update/delete not supported.  Use the cursor library.";
                return SQL_ERROR;
 
     default:
@@ -254,6 +271,11 @@ StatementClass *stmt = (StatementClass *) hstmt;
                *((SDWORD *)pvParam) = stmt->rowset_size;
                break;
 
+       case SQL_KEYSET_SIZE:
+               mylog("GetStmtOption(): SQL_KEYSET_SIZE\n");
+               *((SDWORD *)pvParam) = stmt->keyset_size;
+               break;
+
        case SQL_CONCURRENCY:
                mylog("GetStmtOption(): SQL_CONCURRENCY\n");
                *((SDWORD *)pvParam) = stmt->scroll_concurrency;
@@ -266,7 +288,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
 
        case SQL_SIMULATE_CURSOR:
                stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-               stmt->errormsg = "Simulated positioned update/delete not supported";
+               stmt->errormsg = "Simulated positioned update/delete not supported. Use the cursor library.";
                return SQL_ERROR;
 
        default:
index 386e369600329da094941cdc4be637464407b0d4..07b7ec7b454932e7c797ae354496fa487560a997 100644 (file)
@@ -88,6 +88,7 @@ typedef struct GlobalValues_
        char                            text_as_longvarchar;
        char                            unknowns_as_longvarchar;
        char                            bools_as_char;
+       char                            lie;
        char                            extra_systable_prefixes[MEDIUM_REGISTRY_LEN];
        char                            conn_settings[LARGE_REGISTRY_LEN];
 } GLOBAL_VALUES;
index 7a5b0d886bd9b1c06097a38166e523ad3dffed3a..bbf1d978185ddb33d13a7cac5a7b14f8690be788 100644 (file)
@@ -151,6 +151,7 @@ StatementClass *rv;
                rv->status = STMT_ALLOCATED;
                rv->maxRows = 0;                        // driver returns all rows
                rv->rowset_size = 1;
+               rv->keyset_size = 0;            // fully keyset driven is the default
                rv->scroll_concurrency = SQL_CONCUR_READ_ONLY;
                rv->cursor_type = SQL_CURSOR_FORWARD_ONLY;
                rv->errormsg = NULL;
index 24f58bf050619147ba2a198d4aa290ea8a10415c..53ad3894c96cd0dfb3db4597338d14bf750645a9 100644 (file)
@@ -77,6 +77,7 @@ struct StatementClass_ {
     int errornumber;
        int maxRows;
        int rowset_size;
+       int keyset_size;
        int cursor_type;
        int scroll_concurrency;