Annotation of sql/oracle/parser3oracle.C, revision 1.40

1.1       parser      1: /** @file
                      2:        Parser Oracle driver.
                      3: 
1.29      paf         4:        Copyright(c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com)
1.1       parser      5: 
1.19      paf         6:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1       parser      7: 
                      8:        2001.07.30 using Oracle 8.1.6 [@test tested with Oracle 7.x.x]
                      9: */
1.40    ! paf        10: static const char *RCSId="$Id: parser3oracle.C,v 1.39 2003/10/28 15:41:01 paf Exp $"; 
1.1       parser     11: 
                     12: #include "config_includes.h"
                     13: 
                     14: #include "pa_sql_driver.h"
                     15: 
                     16: #include <oci.h>
                     17: 
                     18: #define MAX_COLS 500
                     19: #define MAX_IN_LOBS 5
                     20: #define MAX_LOB_NAME_LENGTH 100
                     21: #define MAX_OUT_STRING_LENGTH 4000
                     22: 
                     23: #define EMPTY_CLOB_FUNC_CALL "empty_clob()"
                     24: 
                     25: #include "ltdl.h"
                     26: 
                     27: #define MAX_STRING 0x400
                     28: #define MAX_NUMBER 20
                     29: 
                     30: #if _MSC_VER
                     31: #      define snprintf _snprintf
                     32: #      define strcasecmp _stricmp
                     33: #      define strncasecmp _strnicmp
                     34: #endif
                     35: 
                     36: #ifndef max
                     37: inline int max(int a, int b) { return a>b?a:b; }
                     38: inline int min(int a, int b){ return a<b?a:b; }
                     39: #endif
                     40: 
1.33      paf        41: /// @todo small memory leaks here
1.10      paf        42: static int pa_setenv(const char *name, const char *value, bool do_append) {
                     43:        const char *prev_value=0;
                     44:        if(do_append)
                     45:                prev_value=getenv(name);
1.4       paf        46: #ifdef HAVE_PUTENV
                     47:     // MEM_LEAK_HERE. refer to EOF man putenv
1.10      paf        48:        char *buf=(char *)::malloc(strlen(name)
                     49:                +1
                     50:                +(prev_value?strlen(prev_value):0)
                     51:                +strlen(value)
                     52:                +1);
1.4       paf        53:        strcpy(buf, name);
                     54:        strcat(buf, "=");
1.10      paf        55:        if(prev_value)
                     56:                strcat(buf, prev_value);
1.4       paf        57:        strcat(buf, value);
1.5       paf        58: /*
                     59:        if(FILE *f=fopen("f", "at")) {
                     60:                fprintf(f, "****************************%s\n", buf);
                     61: //             for (char **env = environ; env != NULL && *env != NULL; env++)
                     62: //                     fputs(*env, f);
                     63:        
                     64:                fclose(f);
                     65:        }
                     66: */     
1.4       paf        67:        return putenv(buf);
                     68: #else 
                     69:        //#ifdef HAVE_SETENV
1.10      paf        70:        if(value) {
                     71:                if(prev_value) {
                     72:                        // MEM_LEAK_HERE
1.33      paf        73:                        char *buf=(char *)::malloc(strlen(prev_value)
1.10      paf        74:                                +strlen(value)
                     75:                                +1);
                     76:                        strcpy(buf, prev_value);
                     77:                        strcat(buf, value);
1.24      paf        78:                        value=buf;
                     79:                }
1.10      paf        80: 
1.24      paf        81:                return setenv(name, value, 1/*overwrite*/); 
1.10      paf        82:        } else {
1.4       paf        83:                unsetenv(name);
                     84:                return 0;
                     85:        }
                     86: #endif
                     87: }
                     88: 
1.1       parser     89: static char *lsplit(char *string, char delim) {
                     90:     if(string) {
                     91:                char *v=strchr(string, delim);
                     92:                if(v) {
                     93:                        *v=0;
                     94:                        return v+1;
                     95:                }
                     96:     }
                     97:     return 0;
                     98: }
                     99: 
1.4       paf       100: static char *lsplit(char **string_ref, char delim) {
                    101:     char *result=*string_ref;
                    102:        char *next=lsplit(*string_ref, delim);
                    103:     *string_ref=next;
                    104:     return result;
                    105: }
                    106: 
1.39      paf       107: static const char *options2env(char *options, bool* LowerCaseColumnNames) {
1.5       paf       108:        while(options) {
                    109:                if(char *key=lsplit(&options, '&')) {
                    110:                        if(*key) {
                    111:                                if(char *value=lsplit(key, '=')) {
1.39      paf       112:                                        if( strcmp( key, "LowerCaseColumnNames" ) == 0 ) {
                    113:                                                if( LowerCaseColumnNames )
                    114:                                                        *LowerCaseColumnNames = atoi(value)!=0;
                    115:                                                continue;
                    116:                                        }
                    117: 
1.10      paf       118:                                        bool do_append=key[strlen(key)-1]=='+'; // PATH+=
                    119:                                        if(do_append)
                    120:                                                key[strlen(key)-1]=0; // remove trailing +
1.5       paf       121:                                        if(strncmp(key, "ORACLE_", 7)==0  // ORACLE_HOME & co
                    122:                                                || strncmp(key, "ORA_", 4)==0 // ORA_ENCRYPT_LOGIN & co
                    123:                                                || strncmp(key, "NLS_", 4)==0 // NLS_LANG & co
1.10      paf       124:                                                || do_append
1.5       paf       125:                                                ) {
1.10      paf       126:                                                if(pa_setenv(key, value, do_append)!=0)
1.5       paf       127:                                                        return "problem changing process environment" /*key*/;
                    128:                                        } else
1.10      paf       129:                                                return "unknown option (option must start with ORACLE_, ORA_ or NLS_)" /*key*/;
1.5       paf       130:                                } else 
1.10      paf       131:                                        return "option without =value" /*key*/;
1.5       paf       132:                        }
                    133:                }
                    134:        }
                    135:        return 0;
                    136: }
                    137: 
1.1       parser    138: #ifndef DOXYGEN
                    139: struct OracleSQL_connection_struct {
                    140:        jmp_buf mark; char error[MAX_STRING];
1.27      paf       141:        SQL_Error sql_error;
1.1       parser    142:        OCIEnv *envhp;
                    143:        OCIServer *srvhp;
                    144:        OCIError *errhp;
                    145:        OCISvcCtx *svchp;
                    146:        OCISession *usrhp;
1.39      paf       147: 
                    148:        bool bLowerCaseColumnNames;
1.1       parser    149: };
                    150: 
                    151: struct OracleSQL_query_lobs {
                    152:        struct return_rows {
                    153:                struct return_row {
                    154:                        OCILobLocator *locator; ub4 len;
                    155:                        int ind;                
                    156:                        ub2 rcode;
                    157:                } *row;
                    158:                int count;
                    159:        };
                    160:        struct cbf_context_struct {
                    161:                SQL_Driver_services *services;
                    162:                OracleSQL_connection_struct *cs;
                    163:                return_rows *rows;
                    164:        };
                    165:        struct Item {
                    166:                const char *name_ptr; size_t name_size;
                    167:                char *data_ptr; size_t data_size;
                    168:                OCILobLocator *locator;
                    169:                OCIBind *bind;
                    170:                return_rows rows;
                    171:        } items[MAX_IN_LOBS];
                    172:        int count;
                    173: };
                    174: #endif
                    175: 
                    176: // forwards
1.27      paf       177: void check(OracleSQL_connection_struct &cs, const char *step, sword status);
                    178: void check(OracleSQL_connection_struct &cs, bool error);
1.1       parser    179: static sb4 cbf_no_data(
                    180:                                           dvoid *ctxp, 
                    181:                                           OCIBind *bindp, 
                    182:                                           ub4 iter, ub4 index, 
                    183:                                           dvoid **bufpp, 
                    184:                                           ub4 *alenpp, 
                    185:                                           ub1 *piecep, 
                    186:                                           dvoid **indpp);
                    187: static sb4 cbf_get_data(dvoid *ctxp, 
                    188:                                                OCIBind *bindp, 
                    189:                                                ub4 iter, ub4 index, 
                    190:                                                dvoid **bufpp, 
                    191:                                                ub4 **alenp, 
                    192:                                                ub1 *piecep, 
                    193:                                                dvoid **indpp, 
                    194:                                                ub2 **rcodepp);
1.38      paf       195: void tolower(char *out, const char *in, size_t size);
1.1       parser    196: 
                    197: /**
                    198:        OracleSQL server driver
                    199: */
                    200: class OracleSQL_Driver : public SQL_Driver {
                    201: public:
                    202: 
                    203:        OracleSQL_Driver() : SQL_Driver() {
                    204:        }
                    205: 
                    206:        /// get api version
                    207:        int api_version() { return SQL_DRIVER_API_VERSION; }
1.6       paf       208:        /** initialize driver by loading sql dynamic link library
                    209:                @todo ?objects=1 which would turn on OCI_OBJECT init flag
                    210:        */
1.5       paf       211:        const char *initialize(char *dlopen_file_spec) {
                    212:                char *options=lsplit(dlopen_file_spec, '?');
1.1       parser    213: 
                    214:                const char *error=dlopen_file_spec?
                    215:                        dlink(dlopen_file_spec):"client library column is empty";
                    216:                if(!error) {
1.39      paf       217:                        error=options2env(options, 0);
1.1       parser    218: 
1.5       paf       219:                        if(!error)
                    220:                                OCIInitialize((ub4)OCI_THREADED/*| OCI_OBJECT*/, (dvoid *)0, 
                    221:                                        (dvoid * (*)(void *, unsigned int))0, 
                    222:                                        (dvoid * (*)(void*, void*, unsigned int))0,  
                    223:                                        (void (*)(void*, void*))0 
                    224:                                );
1.1       parser    225:                }
                    226: 
                    227:                return error;
                    228:        }
                    229: 
                    230:        /**     connect
                    231:                @param used_only_in_connect_url
1.4       paf       232:                        format: @b user:pass@service?
                    233:                           ORACLE_HOME=/u01/app/oracle/product/8.1.5&
1.5       paf       234:                           ORA_NLS33=/u01/app/oracle/product/8.1.5/ocommon/nls/admin/data&
1.4       paf       235:                           NLS_LANG=RUSSIAN_AMERICA.CL8MSWIN1251&
                    236:                           ORA_ENCRYPT_LOGIN=TRUE
                    237: 
                    238:                @todo environment manupulation doesnt look thread safe
1.1       parser    239:        */
                    240:        void connect(
                    241:                char *used_only_in_connect_url, 
                    242:                SQL_Driver_services& services, 
                    243:                void **connection ///< output: OracleSQL_connection_struct *
                    244:                ) {
                    245:                // connections are cross-request, do not use services._alloc [linked with request]
                    246:                OracleSQL_connection_struct &cs=
                    247:                        *(OracleSQL_connection_struct  *)::calloc(sizeof(OracleSQL_connection_struct), 1);
1.39      paf       248:                cs.bLowerCaseColumnNames = true;
1.1       parser    249: 
                    250:                char *user=used_only_in_connect_url;
                    251:                char *service=lsplit(user, '@');
                    252:                char *pwd=lsplit(user, ':');
1.4       paf       253:                char *options=lsplit(service, '?');
1.1       parser    254: 
                    255:                if(!(user && pwd && service))
                    256:                        services._throw("mailformed connect part, must be 'user:pass@service'");
                    257: 
1.39      paf       258:                if(const char *error=options2env(options, &cs.bLowerCaseColumnNames))
1.5       paf       259:                        services._throw(error);
1.4       paf       260: 
1.1       parser    261:                if(setjmp(cs.mark))
                    262:                        services._throw(cs.error);
                    263: 
                    264:                // Allocate and initialize OCIError handle, attempt #1
                    265:                /*
                    266:                        grabbed from sample 
                    267:                        /server.804/a58234/oci_func.htm#446192
                    268:                        but doc 
                    269:                        /server.804/a58234/oci_func.htm#446100
                    270:                        doesnt have this param listed as allowed
                    271:                        8.1.6 client library barks as OCI_INVALID_HANDLE
                    272:                        and debugging revealed that OCI_HTYPE_ENV param value is invalid
                    273:                        later in doc 
                    274:                        /server.804/a58234/oci_func.htm#446192
                    275:                        on OCIEnvInit thay say
                    276:                        "No changes are done to an already initialized handle"
                    277:                        think, this is some sort of backward compatibility wonder.
                    278:                        leaving as it is, and without check()
                    279:                */
                    280:                OCIHandleAlloc((dvoid *)NULL, (dvoid **) &cs.envhp, (ub4)OCI_HTYPE_ENV, 0, 0);
                    281:                // Initialize an environment handle, attempt #2
1.27      paf       282:                check(cs, "EnvInit", OCIEnvInit(
1.1       parser    283:                        &cs.envhp, (ub4)OCI_DEFAULT, 0, 0));            
                    284:                // Allocate and initialize OCIError handle
1.27      paf       285:                check(cs, "HandleAlloc errhp", OCIHandleAlloc( 
1.1       parser    286:                        (dvoid *)cs.envhp, (dvoid **) &cs.errhp, (ub4)OCI_HTYPE_ERROR, 0, 0));
                    287:                // Allocate and initialize OCIServer handle
1.27      paf       288:                check(cs, "HandleAlloc srvhp", OCIHandleAlloc( 
1.1       parser    289:                        (dvoid *)cs.envhp, (dvoid **) &cs.srvhp, (ub4)OCI_HTYPE_SERVER, 0, 0));         
                    290:                // Attach to a 'service'; initialize server context handle  
1.27      paf       291:                check(cs, "ServerAttach", OCIServerAttach( 
1.1       parser    292:                        cs.srvhp, cs.errhp, (text *)service, (sb4)strlen(service), (ub4)OCI_DEFAULT));
                    293:                // Allocate and initialize OCISvcCtx handle
1.27      paf       294:                check(cs, "HandleAlloc svchp", OCIHandleAlloc( 
1.1       parser    295:                        (dvoid *)cs.envhp, (dvoid **) &cs.svchp, (ub4)OCI_HTYPE_SVCCTX, 0, 0));         
                    296:                // set attribute server context in the service context
1.27      paf       297:                check(cs, "AttrSet server-service", OCIAttrSet( 
1.1       parser    298:                        (dvoid *)cs.svchp, (ub4)OCI_HTYPE_SVCCTX, 
                    299:                        (dvoid *)cs.srvhp, (ub4)0, 
                    300:                        (ub4)OCI_ATTR_SERVER, (OCIError *)cs.errhp));           
                    301:                // allocate a user context handle
1.27      paf       302:                check(cs, "HandleAlloc usrhp", OCIHandleAlloc(
1.1       parser    303:                        (dvoid *)cs.envhp, (dvoid **)&cs.usrhp, (ub4)OCI_HTYPE_SESSION, 0, 0));
                    304:                // set 'user' name
1.27      paf       305:                check(cs, "AttrSet user-session", OCIAttrSet(
1.1       parser    306:                        (dvoid *)cs.usrhp, (ub4)OCI_HTYPE_SESSION, 
                    307:                        (dvoid *)user, (ub4)strlen(user), 
                    308:                        OCI_ATTR_USERNAME, cs.errhp));          
                    309:                // set 'pwd' password
1.27      paf       310:                check(cs, "AttrSet pwd-session", OCIAttrSet(
1.1       parser    311:                        (dvoid *)cs.usrhp, (ub4)OCI_HTYPE_SESSION, 
                    312:                        (dvoid *)pwd, (ub4)strlen(pwd), 
                    313:                        OCI_ATTR_PASSWORD, cs.errhp));
                    314:                // Authenticate a user  
1.27      paf       315:                check(cs, "SessionBegin", OCISessionBegin(
1.1       parser    316:                        cs.svchp, cs.errhp, cs.usrhp, 
                    317:                        OCI_CRED_RDBMS, OCI_DEFAULT));
                    318:                // remember connection in session
1.27      paf       319:                check(cs, "AttrSet service-session", OCIAttrSet(
1.1       parser    320:                        (dvoid *)cs.svchp, (ub4)OCI_HTYPE_SVCCTX, 
                    321:                        (dvoid *)cs.usrhp, (ub4)0, 
                    322:                        OCI_ATTR_SESSION, cs.errhp));
                    323: 
                    324:                // return created connection
                    325:                *(OracleSQL_connection_struct **)connection=&cs;
                    326:        }
                    327:        void disconnect(void *connection) {
                    328:            OracleSQL_connection_struct &cs=*(OracleSQL_connection_struct *)connection;
                    329:                // Terminate a user session
                    330:                OCISessionEnd(
                    331:                        cs.svchp, cs.errhp, cs.usrhp, (ub4)OCI_DEFAULT);
                    332:                // Detach from a server; uninitialize server context handle
                    333:                OCIServerDetach(
                    334:                        cs.srvhp, cs.errhp, (ub4)OCI_DEFAULT);
                    335:                // Free a previously allocated handles
                    336:                /* 
                    337:                oci will free them up as belonging to env
                    338:                OCIHandleFree(
                    339:                        (dvoid *)cs.srvhp, (ub4)OCI_HTYPE_SERVER);
                    340:                OCIHandleFree(
                    341:                        (dvoid *)cs.svchp, (ub4)OCI_HTYPE_SVCCTX);
                    342:                OCIHandleFree(
                    343:                        (dvoid *)cs.errhp, (ub4)OCI_HTYPE_ERROR);
                    344:                */
                    345:                OCIHandleFree(
                    346:                        (dvoid *)cs.envhp, (ub4)OCI_HTYPE_ENV);
                    347: 
                    348:                // connections are cross-request, do not use services._alloc [linked with request]
                    349:                ::free(&cs);
                    350:        }
                    351:        void commit(SQL_Driver_services& services, void *connection) {
                    352:            OracleSQL_connection_struct &cs=*(OracleSQL_connection_struct *)connection;
                    353:                if(setjmp(cs.mark))
                    354:                        services._throw(cs.error);
                    355: 
1.27      paf       356:                check(cs, "commit", OCITransCommit(cs.svchp, cs.errhp, 0));
1.1       parser    357:        }
                    358:        void rollback(SQL_Driver_services& services, void *connection) {
                    359:            OracleSQL_connection_struct &cs=*(OracleSQL_connection_struct *)connection;
                    360:                if(setjmp(cs.mark))
                    361:                        services._throw(cs.error);
                    362: 
1.27      paf       363:                check(cs, "rollback", OCITransRollback(cs.svchp, cs.errhp, 0));
1.1       parser    364:        }
                    365: 
                    366:        bool ping(SQL_Driver_services&, void *connection) {
                    367:                // maybe OCIServerVersion?
1.4       paf       368:                // select 0 from dual
1.1       parser    369:                return true;
                    370:        }
                    371: 
1.32      paf       372:        const char* quote(
                    373:                SQL_Driver_services& services, void *connection,
                    374:                const char *from, unsigned int length) {
                    375:                char *result=(char*)services.malloc_atomic(length*2+1);
                    376:                char *to=result;
                    377:                while(length--) {
                    378:                        switch(*from) {
                    379:                        case '\'': // "'" -> "''"
1.35      paf       380:                                *to++='\'';
1.32      paf       381:                                break;
1.1       parser    382:                        }
1.32      paf       383:                        *to++=*from++;
                    384:                }
                    385:                *to=0;
                    386:                return result;
1.1       parser    387:        }
                    388:        void query(
                    389:                SQL_Driver_services& services, void *connection, 
                    390:                const char *astatement, unsigned long offset, unsigned long limit, 
                    391:                SQL_Driver_query_event_handlers& handlers) {
                    392:                
                    393:                OracleSQL_connection_struct &cs=*(OracleSQL_connection_struct *)connection;
                    394:                OracleSQL_query_lobs lobs={{0}, 0};
                    395:                OCIStmt *stmthp=0;
                    396: 
                    397:                bool failed=false;
                    398:                if(setjmp(cs.mark)) {
                    399:                        failed=true;
                    400:                        goto cleanup;
                    401:                } else {
                    402:                        const char *statement=preprocess_statement(services, cs, 
                    403:                                astatement, lobs);
                    404: 
1.27      paf       405:                        check(cs, "HandleAlloc STMT", OCIHandleAlloc( 
1.1       parser    406:                                (dvoid *)cs.envhp, (dvoid **) &stmthp, (ub4)OCI_HTYPE_STMT, 0, 0));
1.27      paf       407:                        check(cs, "syntax", 
1.1       parser    408:                                OCIStmtPrepare(stmthp, cs.errhp, (unsigned char *)statement, 
                    409:                                (ub4)strlen((char *)statement), 
                    410:                                (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT));
                    411:                        {
                    412:                                for(int i=0; i<lobs.count; i++) {
1.27      paf       413:                                        check(cs, "alloc output var desc", OCIDescriptorAlloc(
1.1       parser    414:                                                (dvoid *)cs.envhp, (dvoid **)&lobs.items[i].locator, (ub4)OCI_DTYPE_LOB, 0, 0));
                    415: 
1.27      paf       416:                                        check(cs, "bind output", OCIBindByPos(stmthp, 
1.1       parser    417:                                                &lobs.items[i].bind, cs.errhp, 
                    418:                                                (ub4)1+i, 
                    419:                                                (dvoid *)&lobs.items[i].locator, 
                    420:                                                (sword)sizeof (lobs.items[i].locator), SQLT_CLOB, (dvoid *)0, 
                    421:                                                (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, OCI_DATA_AT_EXEC));
                    422: 
                    423:                                        lobs.items[i].rows.count=0;
1.32      paf       424:                                        OracleSQL_query_lobs::cbf_context_struct cbf_context={
                    425:                                                &services, &cs, &lobs.items[i].rows};
1.27      paf       426:                                        check(cs, "bind dynamic", OCIBindDynamic(
1.1       parser    427:                                                lobs.items[i].bind, cs.errhp, 
                    428:                                                (dvoid *) &cbf_context, cbf_no_data, 
                    429:                                                (dvoid *) &cbf_context, cbf_get_data));
                    430:                                }
                    431:                        }
                    432: 
1.26      paf       433:                        execute_prepared(services, cs, 
                    434:                                statement, stmthp, lobs, 
                    435:                                offset, limit, handlers);
1.1       parser    436:                }
                    437: cleanup: // no check call after this point!
                    438:                {
                    439:                        for(int i=0; i<lobs.count; i++) {
                    440:                                /* free var locator */
                    441:                                if(OCILobLocator *locator=lobs.items[i].locator)
                    442:                                        OCIDescriptorFree((dvoid *)locator, (ub4)OCI_DTYPE_LOB);
                    443: 
                    444:                                /* free rows descriptors */
                    445:                                OracleSQL_query_lobs::return_rows &rows=lobs.items[i].rows;
                    446:                                for(int r=0; r<rows.count; r++)
                    447:                                        OCIDescriptorFree((dvoid *)rows.row[r].locator, (ub4)OCI_DTYPE_LOB);
                    448:                        }
                    449:                }
                    450:                if(stmthp)
                    451:                        OCIHandleFree((dvoid *)stmthp, (ub4)OCI_HTYPE_STMT);
                    452: 
1.26      paf       453:                if(failed) {
1.27      paf       454:                        if(cs.sql_error.defined())
                    455:                                services._throw(cs.sql_error);
1.1       parser    456:                        services._throw(cs.error);
1.26      paf       457:                }
1.1       parser    458:        }
                    459: 
                    460: private: // private funcs
                    461: 
                    462:        const char *preprocess_statement(SQL_Driver_services& services, OracleSQL_connection_struct &cs, 
                    463:                const char *astatement, OracleSQL_query_lobs &lobs) {
                    464:                size_t statement_size=strlen(astatement);
                    465: 
1.32      paf       466:                char *result=(char *)services.malloc_atomic(statement_size
1.1       parser    467:                        +MAX_STRING // in case of short 'strings'
                    468:                        +11/* returning */+6/* into */+(MAX_LOB_NAME_LENGTH+2/*:, */)*2/*ret into*/*MAX_IN_LOBS
                    469:                        +1);
                    470:                const char *o=astatement;
                    471: 
                    472:                // /**xxx**/'literal' -> EMPTY_CLOB_FUNC_CALL
                    473:                char *n=result;
                    474:                while(*o) {
                    475:                        if(
                    476:                                o[0]=='/' &&
                    477:                                o[1]=='*' && 
                    478:                                o[2]=='*') { // name start
1.34      paf       479:                                const char* saved_o=o;
1.1       parser    480:                                o+=3;
                    481:                                const char *name_begin=o;
                    482:                                while(*o)
                    483:                                        if(
                    484:                                                o[0]=='*' &&
                    485:                                                o[1]=='*' &&
                    486:                                                o[2]=='/' &&
                    487:                                                o[3]=='\'') { // name end
1.34      paf       488:                                                saved_o=0; // found, marking that
1.1       parser    489:                                                const char *name_end=o;
                    490:                                                o+=4;
                    491:                                                OracleSQL_query_lobs::Item &item=lobs.items[lobs.count++];
                    492:                                                item.name_ptr=name_begin; item.name_size=name_end-name_begin;
1.32      paf       493:                                                item.data_ptr=(char *)services.malloc_atomic(statement_size/*max*/); item.data_size=0;
1.1       parser    494: 
                    495:                                                const char *start=o;
                    496:                                                bool escaped=false;
                    497:                                                while(*o && !(o[0]=='\'' && o[1]!='\'' && !escaped)) {
1.14      paf       498:                                                        escaped=o[0]=='\'' && o[1]=='\'';
1.1       parser    499:                                                        if(escaped) {
                    500:                                                                // write pending, skip "\" or "'"
                    501:                                                                if(size_t size=o-start) {
                    502:                                                                        memcpy(item.data_ptr+item.data_size, start, size);
                    503:                                                                        item.data_size+=size;
                    504:                                                                }
                    505:                                                                start=++o;
                    506:                                                        } else
                    507:                                                                o++;
                    508:                                                }
                    509:                                                if(size_t size=o-start) {
                    510:                                                        memcpy(item.data_ptr+item.data_size, start, size);
                    511:                                                        item.data_size+=size;
                    512:                                                }
                    513:                                                if(*o)
                    514:                                                        o++; // skip "'"
                    515: 
                    516:                                                n+=sprintf(n, EMPTY_CLOB_FUNC_CALL);
                    517:                                                break;
                    518:                                        } else
                    519:                                                o++; // /**skip**/'xxx'
1.34      paf       520:                                if(saved_o) {
                    521:                                        o=saved_o;
                    522:                                        *n++=*o++;
                    523:                                }
1.1       parser    524:                        } else
                    525:                                *n++=*o++;
                    526:                }
                    527:                *n=0;
                    528: 
                    529:                if(lobs.count) {
                    530:                        int i;
                    531:                        n+=sprintf(n, " returning ");
                    532:                        for(i=0; i<lobs.count; i++) {
                    533:                                if(i)
                    534:                                        *n++=',';
                    535:                                n+=sprintf(n, "%.*s", lobs.items[i].name_size, lobs.items[i].name_ptr);
                    536:                                /*memcpy(n, lobs.items[i].name_ptr, lobs.items[i].name_size);
                    537:                                n+=lobs.items[i].name_size;*/
                    538:                        }
                    539:                        n+=sprintf(n, " into ");
                    540:                        for(i=0; i<lobs.count; i++) {
                    541:                                if(i)
1.32      paf       542:                                        *n++='x';
1.1       parser    543:                                n+=sprintf(n, ":%.*s", lobs.items[i].name_size, lobs.items[i].name_ptr);
                    544:                                /**n++=':';
                    545:                                memcpy(n, lobs.items[i].name_ptr, lobs.items[i].name_size);
                    546:                                n+=lobs.items[i].name_size;*/
                    547:                        }
                    548:                }
                    549: 
                    550:                return result;
                    551:        }
                    552: 
                    553:        void execute_prepared(
                    554:                SQL_Driver_services& services, OracleSQL_connection_struct &cs, 
                    555:                const char *statement, OCIStmt *stmthp, OracleSQL_query_lobs &lobs, 
                    556:                unsigned long offset, unsigned long limit, 
                    557:                SQL_Driver_query_event_handlers& handlers) {
                    558: 
                    559:                ub2 stmt_type=0; // UNKNOWN
                    560:        /*
                    561:                //gpfs on sun. paf 000818
                    562:                //Zanyway, this is needed before. 
1.27      paf       563:                check(cs, "get stmt type", OCIAttrGet(
1.1       parser    564:                        (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT, (ub1 *)&stmt_type, 
                    565:                        (ub4 *)0, OCI_ATTR_STMT_TYPE, cs.errhp));
                    566:        */
1.16      paf       567: 
1.17      paf       568:                while(isspace(*statement)) 
1.16      paf       569:                        statement++;
1.1       parser    570:                if(strncasecmp(statement, "select", 6)==0) 
                    571:                        stmt_type=OCI_STMT_SELECT;
                    572:                else if(strncasecmp(statement, "insert", 6)==0)
                    573:                        stmt_type=OCI_STMT_INSERT;
                    574:                else if(strncasecmp(statement, "update", 6)==0)
                    575:                        stmt_type=OCI_STMT_UPDATE;
                    576: 
                    577:                sword status=OCIStmtExecute(cs.svchp, stmthp, cs.errhp, 
                    578:                        (ub4)stmt_type==OCI_STMT_SELECT?0:1, (ub4)0, 
                    579:                        (OCISnapshot *)NULL, 
                    580:                        (OCISnapshot *)NULL, (ub4)OCI_DEFAULT);
                    581: 
                    582:                if(status!=OCI_NO_DATA)
1.27      paf       583:                        check(cs, "execute", status);
1.1       parser    584: 
                    585:                {
                    586:                        for(int i=0; i<lobs.count; i++) 
                    587:                                if(ub4 bytes_to_write=lobs.items[i].data_size) {
                    588:                                        OracleSQL_query_lobs::return_rows *rows=&lobs.items[i].rows;
                    589:                                        for(int r=0; r<rows->count; r++) {
                    590:                                                OCILobLocator *locator=rows->row[r].locator;
1.27      paf       591:                                                check(cs, "lobwrite", OCILobWrite (
1.1       parser    592:                                                        cs.svchp, cs.errhp, 
                    593:                                                        locator, &bytes_to_write, 1, 
                    594:                                                        (dvoid *)lobs.items[i].data_ptr, (ub4)bytes_to_write, OCI_ONE_PIECE, 
                    595:                                                        (dvoid *)0, 0, (ub2)0, 
                    596:                                                        (ub1) SQLCS_IMPLICIT));
                    597:                                        }
                    598:                                }
                    599:                }
                    600:                
                    601:                switch(stmt_type) {
                    602:                case OCI_STMT_SELECT:
                    603:                        fetch_table(services, cs,
                    604:                                stmthp, offset, limit, 
                    605:                                handlers);
                    606:                        break;
                    607:                default:
                    608:                /*
                    609:                case OCI_STMT_INSERT:
                    610:                case OCI_STMT_UPDATE:
                    611:                */
                    612:                        break;
                    613:                }
                    614:        }
                    615: 
                    616:        void fetch_table(SQL_Driver_services& services, OracleSQL_connection_struct &cs, 
                    617:                OCIStmt *stmthp, unsigned long offset, unsigned long limit, 
                    618:                SQL_Driver_query_event_handlers& handlers) {
1.12      paf       619: 
1.10      paf       620:                ub4 prefetch_rows=100;
1.27      paf       621:                check(cs, "AttrSet prefetch-rows", OCIAttrSet( 
1.9       paf       622:                        (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT, 
                    623:                        (dvoid *)&prefetch_rows, (ub4)0, 
                    624:                        (ub4)OCI_ATTR_PREFETCH_ROWS, (OCIError *)cs.errhp));
                    625: 
1.20      paf       626:                ub4 prefetch_mem_size=100*0x400;
1.27      paf       627:                check(cs, "AttrSet prefetch-memory", OCIAttrSet( 
1.9       paf       628:                        (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT, 
                    629:                        (dvoid *)&prefetch_mem_size, (ub4)0, 
                    630:                        (ub4)OCI_ATTR_PREFETCH_MEMORY, (OCIError *)cs.errhp));
1.1       parser    631: 
                    632:                OCIParam          *mypard;
                    633:                ub2                    dtype;
                    634:                text                  *col_name;
                    635: 
1.40    ! paf       636:                struct Col {
1.1       parser    637:                        ub2 type;
                    638:                        char *str;
                    639:                        OCILobLocator *var;
                    640:                        OCIDefine *def;
                    641:                        sb2 indicator;
                    642:                } cols[MAX_COLS]={0};
                    643:                int column_count=0;
                    644: 
                    645:                bool failed=false;
                    646:                jmp_buf saved_mark; memcpy(saved_mark, cs.mark, sizeof(jmp_buf));
                    647:                if(setjmp(cs.mark)) {
                    648:                        failed=true;
                    649:                        goto cleanup;
                    650:                } else {
1.27      paf       651:                        // idea of preincrementing is that at error time all handles would free up
                    652:                        while(++column_count<=MAX_COLS) {
                    653:                                /* get next descriptor, if there is one */
                    654:                                if(OCIParamGet(stmthp, OCI_HTYPE_STMT, cs.errhp, (void **)&mypard, 
                    655:                                        (ub4) column_count)!=OCI_SUCCESS) {
                    656:                                        --column_count;
                    657:                                        break;
                    658:                                }
                    659:                                
                    660:                                /* Retrieve the data type attribute */
                    661:                                check(cs, "get type", OCIAttrGet(
                    662:                                        (dvoid*) mypard, (ub4)OCI_DTYPE_PARAM, 
                    663:                                        (dvoid*) &dtype, (ub4 *)0, (ub4)OCI_ATTR_DATA_TYPE, 
                    664:                                        (OCIError *)cs.errhp));
                    665:                                
                    666:                                /* Retrieve the column name attribute */
                    667:                                ub4 col_name_len;
                    668:                                check(cs, "get name", OCIAttrGet(
                    669:                                        (dvoid*) mypard, (ub4)OCI_DTYPE_PARAM, 
                    670:                                        (dvoid**) &col_name, (ub4 *) &col_name_len, (ub4)OCI_ATTR_NAME, 
                    671:                                        (OCIError *)cs.errhp));
                    672:                                
1.40    ! paf       673:                                Col& col=cols[column_count-1];
1.27      paf       674:                                {
1.38      paf       675:                                        size_t length=(size_t)col_name_len;
                    676:                                        char *ptr=(char *)services.malloc_atomic(length+1);
1.39      paf       677:                                        if( cs.bLowerCaseColumnNames ) 
                    678:                                                tolower(ptr, (char *)col_name, length);
                    679:                                        else
                    680:                                                memcpy(ptr, col_name, length);                                          
1.38      paf       681:                                        ptr[length]=0;
                    682:                                        check(cs, handlers.add_column(cs.sql_error, ptr, length));
1.27      paf       683:                                }
                    684:                                
                    685:                                ub2 coerce_type=dtype;
                    686:                                sb4 size=0;
                    687:                                void *ptr;
                    688:                                
                    689:                                switch(dtype) {
                    690:                                case SQLT_CLOB: 
1.1       parser    691:                                        {
1.27      paf       692:                                                check(cs, "alloc output var desc", OCIDescriptorAlloc(
1.40    ! paf       693:                                                        (dvoid *)cs.envhp, (dvoid **)(ptr=&col.var), 
1.27      paf       694:                                                        (ub4)OCI_DTYPE_LOB, 
                    695:                                                        0, (dvoid **)0));
                    696:                                                
                    697:                                                size=0;
1.1       parser    698:                                                break;
                    699:                                        }
1.27      paf       700:                                default:
                    701:                                        coerce_type=SQLT_STR;
1.40    ! paf       702:                                        ptr=col.str=(char *)services.malloc_atomic(MAX_OUT_STRING_LENGTH+1);
1.27      paf       703:                                        size=MAX_OUT_STRING_LENGTH;
                    704:                                        break;
1.1       parser    705:                                }
                    706:                                
1.40    ! paf       707:                                col.type=coerce_type;
1.1       parser    708:                                
1.40    ! paf       709:                                col.def=0; check(cs, "DefineByPos", OCIDefineByPos(
        !           710:                                        stmthp, &col.def, cs.errhp, 
1.27      paf       711:                                        column_count, (ub1 *) ptr, size, 
1.40    ! paf       712:                                        coerce_type, (dvoid *) &col.indicator, 
1.27      paf       713:                                        (ub2 *)0, (ub2 *)0, OCI_DEFAULT));
                    714:                        }
                    715:                        
                    716:                        check(cs, handlers.before_rows(cs.sql_error));
                    717:                        
                    718:                        for(unsigned long row=0; !limit||row<offset+limit; row++) {
                    719:                                sword status=OCIStmtFetch(stmthp, cs.errhp, (ub4)1,  (ub4)OCI_FETCH_NEXT, 
                    720:                                        (ub4)OCI_DEFAULT);
                    721:                                if(status==OCI_NO_DATA)
                    722:                                        break;
                    723:                                check(cs, "fetch", status);
1.3       paf       724: 
1.27      paf       725:                                if(row>=offset) {
                    726:                                        check(cs, handlers.add_row(cs.sql_error));
                    727:                                        for(int i=0; i<column_count; i++) {
1.37      paf       728:                                                size_t length=0;
1.32      paf       729:                                                char* str=0;
1.27      paf       730:                                                if(!cols[i].indicator) // not NULL
                    731:                                                        switch(cols[i].type) {
                    732:                                                        case SQLT_CLOB: 
                    733:                                                                {
                    734:                                                                        ub4   amtp=4096000000UL;
                    735:                                                                        ub4   offset=1;
                    736:                                                                        ub4   loblen=0;
                    737:                                                                        OCILobLocator *var=(OCILobLocator *)cols[i].var;
                    738:                                                                        OCILobGetLength(cs.svchp, cs.errhp, var, &loblen);
                    739:                                                                        if(loblen) {
1.37      paf       740:                                                                                length=(size_t)loblen;
                    741:                                                                                str=(char*)services.malloc_atomic(length+1);
1.27      paf       742:                                                                                check(cs, "lobread", OCILobRead(cs.svchp, cs.errhp, 
1.32      paf       743:                                                                                        var, &amtp, offset, (dvoid *) str, 
1.27      paf       744:                                                                                        loblen, (dvoid *)0, 
                    745:                                                                                        0, 
                    746:                                                                                        (ub2)0, (ub1) SQLCS_IMPLICIT));
1.37      paf       747:                                                                                str[length]=0;
1.1       parser    748:                                                                        }
                    749:                                                                        break;
                    750:                                                                }
1.27      paf       751:                                                        default:
1.32      paf       752:                                                                if(const char *value=cols[i].str) {
1.37      paf       753:                                                                        length=strlen(value);
                    754:                                                                        str=(char*)services.malloc_atomic(length+1);
                    755:                                                                        memcpy(str, value, length+1);
1.27      paf       756:                                                                } else {
1.37      paf       757:                                                                        length=0;
1.32      paf       758:                                                                        str=0;
1.27      paf       759:                                                                }
                    760:                                                                break;
                    761:                                                        }
1.37      paf       762:                                                check(cs, handlers.add_row_cell(cs.sql_error, str, length));
1.1       parser    763:                                        }
                    764:                                }
                    765:                        }
                    766:                }
                    767: 
                    768: cleanup: // no check call after this point!
                    769:                for(int i=0; i<column_count; i++) {
                    770:                        switch(cols[i].type) {
                    771:                        case SQLT_CLOB:
                    772:                                /* free var locator */
                    773:                                OCIDescriptorFree((dvoid *) cols[i].var, (ub4)OCI_DTYPE_LOB);
                    774:                                break;
                    775:                        default:
                    776:                                break;
                    777:                        }
                    778:                }
                    779: 
                    780:                if(failed) // need rethrow?
                    781:                        longjmp(saved_mark, 1);
                    782:        }
                    783: 
                    784: private: // conn client library funcs
                    785:        
1.27      paf       786:        friend void check(OracleSQL_connection_struct &cs, const char *step, sword status);
1.1       parser    787:        friend sb4 cbf_get_data(dvoid *ctxp, 
                    788:                OCIBind *bindp, 
                    789:                ub4 iter, ub4 index, 
                    790:                dvoid **bufpp, 
                    791:                ub4 **alenp, 
                    792:                ub1 *piecep, 
                    793:                dvoid **indpp, 
                    794:                ub2 **rcodepp);
                    795: 
                    796: 
                    797: #define OCI_DECL(name, params) \
                    798:        typedef sword (*t_OCI##name)params; t_OCI##name OCI##name
                    799: 
                    800:        OCI_DECL(Initialize, (ub4 mode, dvoid *ctxp, 
                    801:                dvoid * (*malocfp)(dvoid *ctxp, size_t size),
                    802:                dvoid * (*ralocfp)(dvoid *ctxp, dvoid *memptr, size_t newsize),
                    803:                void (*mfreefp)(dvoid *ctxp, dvoid *memptr) ));
                    804: 
                    805:        OCI_DECL(EnvInit, (OCIEnv **envp, ub4 mode, 
                    806:                size_t xtramem_sz, dvoid **usrmempp)); 
                    807:                
                    808:        OCI_DECL(AttrGet, (CONST dvoid *trgthndlp, ub4 trghndltyp, 
                    809:                dvoid *attributep, ub4 *sizep, ub4 attrtype, 
                    810:                OCIError *errhp));
                    811:        
                    812:        OCI_DECL(AttrSet, (dvoid *trgthndlp, ub4 trghndltyp, dvoid *attributep,
                    813:                                                                ub4 size, ub4 attrtype, OCIError *errhp));
                    814: 
                    815:        OCI_DECL(BindByPos, (OCIStmt *stmtp, OCIBind **bindp, OCIError *errhp,
                    816:                ub4 position, dvoid *valuep, sb4 value_sz,
                    817:                ub2 dty, dvoid *indp, ub2 *alenp, ub2 *rcodep,
                    818:                ub4 maxarr_len, ub4 *curelep, ub4 mode));
                    819: 
                    820:        OCI_DECL(BindDynamic, (OCIBind *bindp, OCIError *errhp, dvoid *ictxp,
                    821:                OCICallbackInBind icbfp, dvoid *octxp,
                    822:                OCICallbackOutBind ocbfp));
                    823:        
                    824:        OCI_DECL(DefineByPos, (OCIStmt *stmtp, OCIDefine **defnp, OCIError *errhp,
                    825:                ub4 position, dvoid *valuep, sb4 value_sz, ub2 dty,
                    826:                dvoid *indp, ub2 *rlenp, ub2 *rcodep, ub4 mode));
                    827:        
                    828:        OCI_DECL(DescriptorAlloc, (CONST dvoid *parenth, dvoid **descpp, 
                    829:                CONST ub4 type, CONST size_t xtramem_sz, 
                    830:                dvoid **usrmempp));
                    831:        
                    832:        OCI_DECL(DescriptorFree, (dvoid *descp, CONST ub4 type));
                    833: 
                    834:        
                    835:        OCI_DECL(ErrorGet, (dvoid *hndlp, ub4 recordno, OraText *sqlstate,
                    836:                        sb4 *errcodep, OraText *bufp, ub4 bufsiz, ub4 type));
                    837: 
                    838:        OCI_DECL(HandleAlloc, (CONST dvoid *parenth, dvoid **hndlpp, CONST ub4 type, 
                    839:                        CONST size_t xtramem_sz, dvoid **usrmempp));
                    840: 
                    841:        OCI_DECL(HandleFree, (dvoid *hndlp, CONST ub4 type));
                    842:                                           
                    843:        OCI_DECL(LobGetLength, (OCISvcCtx *svchp, OCIError *errhp, 
                    844:                           OCILobLocator *locp,
                    845:                           ub4 *lenp));
                    846: 
                    847:        OCI_DECL(LobRead, (OCISvcCtx *svchp, OCIError *errhp, OCILobLocator *locp,
                    848:                      ub4 *amtp, ub4 offset, dvoid *bufp, ub4 bufl, 
                    849:                      dvoid *ctxp, sb4 (*cbfp)(dvoid *ctxp, 
                    850:                                               CONST dvoid *bufp, 
                    851:                                               ub4 len, 
                    852:                                               ub1 piece),
                    853:                      ub2 csid, ub1 csfrm));
                    854: 
                    855:        OCI_DECL(LobWrite, (OCISvcCtx *svchp, OCIError *errhp, OCILobLocator *locp,
                    856:                       ub4 *amtp, ub4 offset, dvoid *bufp, ub4 buflen, 
                    857:                       ub1 piece, dvoid *ctxp, 
                    858:                       sb4 (*cbfp)(dvoid *ctxp, 
                    859:                                   dvoid *bufp, 
                    860:                                   ub4 *len, 
                    861:                                   ub1 *piece),
                    862:                       ub2 csid, ub1 csfrm));
                    863: 
                    864:        OCI_DECL(ParamGet, (CONST dvoid *hndlp, ub4 htype, OCIError *errhp, 
                    865:                      dvoid **parmdpp, ub4 pos));
                    866: 
                    867:        OCI_DECL(ServerAttach, (OCIServer *srvhp, OCIError *errhp,
                    868:                           CONST OraText *dblink, sb4 dblink_len, ub4 mode));
                    869: 
                    870:        OCI_DECL(ServerDetach, (OCIServer *srvhp, OCIError *errhp, ub4 mode));
                    871: 
                    872:        OCI_DECL(SessionBegin, (OCISvcCtx *svchp, OCIError *errhp, OCISession *usrhp,
                    873:                           ub4 credt, ub4 mode));
                    874: 
                    875:        OCI_DECL(SessionEnd, (OCISvcCtx *svchp, OCIError *errhp, OCISession *usrhp, 
                    876:                          ub4 mode));
                    877: 
                    878:        OCI_DECL(StmtExecute, (OCISvcCtx *svchp, OCIStmt *stmtp, OCIError *errhp, 
                    879:                          ub4 iters, ub4 rowoff, CONST OCISnapshot *snap_in, 
                    880:                          OCISnapshot *snap_out, ub4 mode));
                    881: 
                    882:        OCI_DECL(StmtFetch, (OCIStmt *stmtp, OCIError *errhp, ub4 nrows, 
                    883:                         ub2 orientation, ub4 mode));
                    884: 
                    885:        OCI_DECL(StmtPrepare, (OCIStmt *stmtp, OCIError *errhp, CONST OraText *stmt,
                    886:                           ub4 stmt_len, ub4 language, ub4 mode));
                    887: 
                    888:        OCI_DECL(TransCommit, (OCISvcCtx *svchp, OCIError *errhp, ub4 flags));
                    889: 
                    890:        OCI_DECL(TransRollback, (OCISvcCtx *svchp, OCIError *errhp, ub4 flags));
                    891: 
                    892: private: // conn client library funcs linking
                    893: 
                    894:        const char *dlink(const char *dlopen_file_spec) {
                    895:                if(lt_dlinit())
                    896:                        return lt_dlerror();
                    897:         lt_dlhandle handle=lt_dlopen(dlopen_file_spec);
                    898:         if(!handle)
                    899:                        return lt_dlerror(); //"can not open the dynamic link module";
                    900: 
                    901:                #define DSLINK(name, action) \
                    902:                        name=(t_##name)lt_dlsym(handle, #name); \
                    903:                                if(!name) \
                    904:                                        action;
                    905: 
                    906:                #define OCI_LINK(name) DSLINK(OCI##name, return "function OCI" #name " was not found")
                    907:                
                    908:                OCI_LINK(Initialize);
                    909:                OCI_LINK(EnvInit);
                    910:                OCI_LINK(AttrGet);              OCI_LINK(AttrSet);
                    911:                OCI_LINK(BindByPos);            OCI_LINK(BindDynamic);
                    912:                OCI_LINK(DefineByPos);
                    913:                OCI_LINK(DescriptorAlloc);              OCI_LINK(DescriptorFree);
                    914:                OCI_LINK(ErrorGet);
                    915:                OCI_LINK(HandleAlloc);          OCI_LINK(HandleFree);
                    916:                OCI_LINK(LobGetLength);
                    917:                OCI_LINK(LobRead);              OCI_LINK(LobWrite);
                    918:                OCI_LINK(ParamGet);
                    919:                OCI_LINK(ServerAttach);         OCI_LINK(ServerDetach);
                    920:                OCI_LINK(SessionBegin);         OCI_LINK(SessionEnd);
                    921:                OCI_LINK(StmtExecute);          OCI_LINK(StmtFetch);            OCI_LINK(StmtPrepare);
                    922:                OCI_LINK(TransCommit);          OCI_LINK(TransRollback);
                    923: 
                    924:                return 0;
                    925:        }
                    926: 
                    927: } *OracleSQL_driver;
                    928: 
1.27      paf       929: void check(OracleSQL_connection_struct &cs, const char *step, sword status) {
1.1       parser    930: 
                    931:        const char *msg;
                    932:        char reason[MAX_STRING/2];
                    933: 
1.21      paf       934:        const char *prefix="ERROR";
1.1       parser    935:        switch (status) {
1.22      paf       936:        case OCI_SUCCESS: // hurrah
                    937:        case OCI_SUCCESS_WITH_INFO:             // ignoring. example: count(column) when column contains NULLs, 
                    938:                                                                                                                // count() not counting them and gives that status
                    939:                return;
1.1       parser    940:        case OCI_ERROR:
                    941:                {
                    942:                sb4 errcode;
                    943:                if(OracleSQL_driver->OCIErrorGet((dvoid *)cs.errhp, (ub4)1, (text *)NULL, &errcode, 
                    944:                        (text *)reason, (ub4)sizeof(reason), OCI_HTYPE_ERROR)==OCI_SUCCESS)
                    945:                        msg=reason;
                    946:                else
                    947:                        msg="[can not get error description]";
                    948:                break;
                    949:                }
                    950:        case OCI_NEED_DATA:
                    951:                msg="NEED_DATA"; break;
                    952:        case OCI_NO_DATA:
                    953:                msg="NODATA"; break;
                    954:        case OCI_INVALID_HANDLE:
                    955:                msg="INVALID_HANDLE"; break;
                    956:        case OCI_STILL_EXECUTING:
                    957:                msg="STILL_EXECUTE"; break;
                    958:        case OCI_CONTINUE:
                    959:                msg="CONTINUE"; break;
                    960:        default:
                    961:                msg="unknown"; break;
                    962:        }
                    963: 
1.22      paf       964:        snprintf(cs.error, sizeof(cs.error), "%s (%s, %d)", 
                    965:                msg, step, (int)status);
1.1       parser    966:        longjmp(cs.mark, 1);
                    967: }
                    968: 
1.27      paf       969: void check(OracleSQL_connection_struct &cs, bool error) {
                    970:        if(error)
                    971:                longjmp(cs.mark, 1);
                    972: }
1.1       parser    973: 
                    974: /* ----------------------------------------------------------------- */
                    975: /* Intbind callback that does not do any data input.                 */
                    976: /* ----------------------------------------------------------------- */
                    977: static sb4 cbf_no_data(
                    978:                                dvoid *ctxp, 
                    979:                                OCIBind *bindp, 
                    980:                                ub4 iter, ub4 index, 
                    981:                                dvoid **bufpp, 
                    982:                                ub4 *alenpp, 
                    983:                                ub1 *piecep, 
                    984:                                dvoid **indpp) {
                    985:        *bufpp=(dvoid *)0;
                    986:        *alenpp=0;
                    987:        static sb2 null_ind=-1;
                    988:        *indpp=(dvoid *) &null_ind;
                    989:        *piecep=OCI_ONE_PIECE;
                    990:        
                    991:        return OCI_CONTINUE;
                    992: }
                    993: 
                    994: /* ----------------------------------------------------------------- */
                    995: /* Outbind callback for returning data.                              */
                    996: /* ----------------------------------------------------------------- */
                    997: static sb4 cbf_get_data(dvoid *ctxp, 
                    998:                                 OCIBind *bindp, 
                    999:                                 ub4 iter, ub4 index, 
                   1000:                                 dvoid **bufpp, 
                   1001:                                 ub4 **alenp, 
                   1002:                                 ub1 *piecep, 
                   1003:                                 dvoid **indpp, 
                   1004:                                 ub2 **rcodepp) {
                   1005:        OracleSQL_query_lobs::cbf_context_struct &context=
                   1006:                *(OracleSQL_query_lobs::cbf_context_struct *)ctxp;
                   1007: 
                   1008:        if(index==0) {
                   1009:                static ub4  rows;
1.27      paf      1010:                check(*context.cs, "AttrGet cbf_get_data ROWS_RETURNED", 
1.1       parser   1011:                        OracleSQL_driver->OCIAttrGet(
                   1012:                                (CONST dvoid *) bindp, OCI_HTYPE_BIND, (dvoid *)&rows, 
                   1013:                                (ub4 *)sizeof(ub2), OCI_ATTR_ROWS_RETURNED, context.cs->errhp)) ;
                   1014:                context.rows->count=(ub2)rows;
                   1015:                context.rows->row=(OracleSQL_query_lobs::return_rows::return_row *)
1.32      paf      1016:                        context.services->malloc_atomic(sizeof(OracleSQL_query_lobs::return_rows::return_row)*rows);
1.1       parser   1017:        }
                   1018: 
                   1019:        OracleSQL_query_lobs::return_rows::return_row &var=context.rows->row[index];
                   1020: 
1.27      paf      1021:        check(*context.cs, "alloc output var desc dynamic", OracleSQL_driver->OCIDescriptorAlloc(
1.1       parser   1022:                (dvoid *) context.cs->envhp, (dvoid **)&var.locator, 
                   1023:                (ub4)OCI_DTYPE_LOB, 
                   1024:                0, (dvoid **)0));
                   1025: 
                   1026:        *bufpp=var.locator;
                   1027:        *alenp=&var.len;
                   1028:        *indpp=(dvoid *) &var.ind;
                   1029:        *piecep=OCI_ONE_PIECE;
                   1030:        *rcodepp=&var.rcode;
                   1031:        
                   1032:        return OCI_CONTINUE;
                   1033: }
                   1034: 
1.38      paf      1035: void tolower(char *out, const char *in, size_t size) {
                   1036:        while(size--)
                   1037:                *out++=tolower(*in++);
1.1       parser   1038: }
                   1039: 
                   1040: extern "C" SQL_Driver *SQL_DRIVER_CREATE() {
                   1041:        return OracleSQL_driver=new OracleSQL_Driver();
                   1042: }

E-mail: