~ubuntu-branches/ubuntu/hardy/psqlodbc/hardy

« back to all changes in this revision

Viewing changes to statement.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2007-03-05 22:28:19 UTC
  • mfrom: (3.1.4 edgy)
  • Revision ID: james.westby@ubuntu.com-20070305222819-95d0rzmt2ah6dwwc
Tags: 1:08.01.0200-2.1
* Non-maintainer upload.
* High-urgency upload for RC bugfix.
* Fix the signature of SQLGetData on 64-bit architectures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
 */
14
14
 
15
15
#include "statement.h"
16
 
 
17
16
#include "bind.h"
18
17
#include "connection.h"
19
18
#include "qresult.h"
72
71
                STMT_TYPE_LOCK, "LOCK"
73
72
        },
74
73
        {
 
74
                STMT_TYPE_BEGIN, "BEGIN"
 
75
        },
 
76
        {
75
77
                0, NULL
76
78
        }
77
79
};
84
86
        CSTR func = "PGAPI_AllocStmt";
85
87
        ConnectionClass *conn = (ConnectionClass *) hdbc;
86
88
        StatementClass *stmt;
 
89
        ARDFields       *ardopts;
 
90
        BindInfoClass   *bookmark;
87
91
 
88
92
        mylog("%s: entering...\n", func);
89
93
 
118
122
 
119
123
        /* Copy default statement options based from Connection options */
120
124
        stmt->options = stmt->options_orig = conn->stmtOptions;
121
 
        stmt->ardopts = conn->ardOptions;
122
 
        stmt->ardopts.bookmark = (BindInfoClass *) malloc(sizeof(BindInfoClass));
123
 
        stmt->ardopts.bookmark->buffer = NULL;
124
 
        stmt->ardopts.bookmark->used = NULL;
 
125
        stmt->ardi.ardopts = conn->ardOptions;
 
126
        ardopts = SC_get_ARDF(stmt);
 
127
        bookmark = ARD_AllocBookmark(ardopts);
125
128
 
126
129
        stmt->stmt_size_limit = CC_get_max_query_len(conn);
127
130
        /* Save the handle for later */
167
170
                        /* Free any cursors and discard any result info */
168
171
                        if (res = SC_get_Result(stmt), res)
169
172
                        {
 
173
                                if(SC_is_fetchcursor(stmt))
 
174
                                        SC_set_handle(stmt,res);
170
175
                                QR_Destructor(res);
171
176
                                SC_set_Result(stmt,  NULL);
172
177
                        }
205
210
 
206
211
 
207
212
/*
 
213
 * For Declare/Fetch, setting the parameters to close the cursor.
 
214
 */
 
215
void 
 
216
SC_set_handle(StatementClass *self,QResultClass *res)
 
217
{
 
218
        res->conn = self->hdbc;
 
219
        if(!res->cursor)
 
220
                res->cursor = malloc(sizeof(self->cursor_name));
 
221
        strcpy(res->cursor,self->cursor_name);
 
222
}
 
223
 
 
224
 
 
225
/*
208
226
 * StatementClass implementation
209
227
 */
210
228
void
218
236
        opt->cursor_type = SQL_CURSOR_FORWARD_ONLY;
219
237
        opt->retrieve_data = SQL_RD_ON;
220
238
        opt->use_bookmarks = SQL_UB_OFF;
221
 
#if (ODBCVER >= 0x0300)
222
239
        opt->metadata_id = SQL_FALSE;
223
 
#endif /* ODBCVER */
224
 
}
225
 
 
226
 
 
227
 
/*
228
 
 * ARDFields initialize
229
 
 */
230
 
void
231
 
InitializeARDFields(ARDFields *opt)
232
 
{
233
 
        memset(opt, 0, sizeof(ARDFields));
234
 
#if (ODBCVER >= 0x0300)
235
 
        opt->size_of_rowset = 1;
236
 
#endif /* ODBCVER */
237
 
        opt->bind_size = 0;             /* default is to bind by column */
238
 
        opt->size_of_rowset_odbc2 = 1;
239
 
}
240
 
/*
241
 
 * APDFields initialize
242
 
 */
243
 
void
244
 
InitializeAPDFields(APDFields *opt)
245
 
{
246
 
        memset(opt, 0, sizeof(APDFields));
247
 
        opt->paramset_size = 1;
248
 
        opt->param_bind_type = 0;       /* default is to bind by column */
249
240
}
250
241
 
251
242
 
254
245
{
255
246
        StatementClass *rv;
256
247
 
 
248
        mylog("SC_Constructor: entering ...\n");
257
249
        rv = (StatementClass *) malloc(sizeof(StatementClass));
258
250
        if (rv)
259
251
        {
 
252
                mylog("SC_Constructor: created stmt = %u\n",rv);
260
253
                rv->hdbc = NULL;                /* no connection associated yet */
261
254
                rv->phstmt = NULL;
262
255
                rv->result = NULL;
263
256
                rv->curres = NULL;
264
 
                rv->manual_result = FALSE;
 
257
                rv->manual_result = TRUE;
265
258
                rv->prepare = FALSE;
266
259
                rv->prepared = FALSE;
267
260
                rv->status = STMT_ALLOCATED;
268
261
                rv->internal = FALSE;
269
262
                rv->transition_status = 0;
 
263
                rv->num_params = -1; /* unknown */
270
264
 
271
265
                rv->__error_message = NULL;
272
266
                rv->__error_number = 0;
273
267
                rv->errormsg_created = FALSE;
 
268
                rv->__sqlstate[0] = '\0';
274
269
 
275
270
                rv->statement = NULL;
276
271
                rv->stmt_with_params = NULL;
303
298
 
304
299
                /* Clear Statement Options -- defaults will be set in AllocStmt */
305
300
                memset(&rv->options, 0, sizeof(StatementOptions));
306
 
                memset(&rv->ardopts, 0, sizeof(ARDFields));
307
 
                memset(&rv->apdopts, 0, sizeof(APDFields));
308
 
                memset(&rv->irdopts, 0, sizeof(IRDFields));
309
 
                memset(&rv->ipdopts, 0, sizeof(IPDFields));
 
301
                InitializeEmbeddedDescriptor((DescriptorClass *)&(rv->ardi),
 
302
                                rv, SQL_ATTR_APP_ROW_DESC);
 
303
                InitializeEmbeddedDescriptor((DescriptorClass *)&(rv->apdi),
 
304
                                rv, SQL_ATTR_APP_PARAM_DESC);
 
305
                InitializeEmbeddedDescriptor((DescriptorClass *)&(rv->irdi),
 
306
                                rv, SQL_ATTR_IMP_ROW_DESC);
 
307
                InitializeEmbeddedDescriptor((DescriptorClass *)&(rv->ipdi),
 
308
                                rv, SQL_ATTR_IMP_PARAM_DESC);
310
309
 
311
310
                rv->pre_executing = FALSE;
312
311
                rv->inaccurate_result = FALSE;
315
314
                rv->error_recsize = -1;
316
315
                rv->diag_row_count = 0;
317
316
                rv->stmt_time = 0;
 
317
                rv->execute_delegate = NULL;
 
318
                rv->allocated_callbacks = 0;
 
319
                rv->num_callbacks = 0;
 
320
                rv->callbacks = NULL;
 
321
                GetDataInfoInitialize(SC_get_GDTI(rv));
 
322
                PutDataInfoInitialize(SC_get_PDTI(rv));
318
323
                INIT_STMT_CS(rv);
319
324
        }
320
325
        return rv;
321
326
}
322
327
 
323
 
 
324
 
void ARDFields_free(ARDFields * self)
325
 
{
326
 
        if (self->bookmark)
327
 
        {
328
 
                free(self->bookmark);
329
 
                self->bookmark = NULL;
330
 
        }
331
 
        /*
332
 
         * the memory pointed to by the bindings is not deallocated by the
333
 
         * driver but by the application that uses that driver, so we don't
334
 
         * have to care
335
 
         */
336
 
        ARD_unbind_cols(self, TRUE);
337
 
}
338
 
 
339
 
void APDFields_free(APDFields * self)
340
 
{
341
 
        /* param bindings */
342
 
        APD_free_params(self, STMT_FREE_PARAMS_ALL);
343
 
}
344
 
 
345
 
void IRDFields_free(IRDFields * self)
346
 
{
347
 
        /* Free the parsed field information */
348
 
        if (self->fi)
349
 
        {
350
 
                int                     i;
351
 
 
352
 
                for (i = 0; i < (int) self->nfields; i++)
353
 
                {
354
 
                        if (self->fi[i])
355
 
                        {
356
 
                                if (self->fi[i]->schema)
357
 
                                        free(self->fi[i]->schema);
358
 
                                free(self->fi[i]);
359
 
                        }
360
 
                }
361
 
                free(self->fi);
362
 
                self->fi = NULL;
363
 
        }
364
 
}
365
 
 
366
 
void IPDFields_free(IPDFields * self)
367
 
{
368
 
        /* param bindings */
369
 
        IPD_free_params(self, STMT_FREE_PARAMS_ALL);
370
 
}
371
 
 
372
328
char
373
329
SC_Destructor(StatementClass *self)
374
330
{
392
348
        }
393
349
 
394
350
        SC_initialize_stmts(self, TRUE);
 
351
        SC_free_params(self, STMT_FREE_PARAMS_ALL);
395
352
 
396
353
        /* Free the parsed table information */
397
354
        if (self->ti)
407
364
        }
408
365
 
409
366
        /* Free the parsed field information */
410
 
        ARDFields_free(&(self->ardopts));
411
 
        APDFields_free(&(self->apdopts));
412
 
        IRDFields_free(&(self->irdopts));
413
 
        IPDFields_free(&(self->ipdopts));
 
367
        DC_Destructor((DescriptorClass *) SC_get_ARDi(self));
 
368
        DC_Destructor((DescriptorClass *) SC_get_APDi(self));
 
369
        DC_Destructor((DescriptorClass *) SC_get_IRDi(self));
 
370
        DC_Destructor((DescriptorClass *) SC_get_IPDi(self));
414
371
        
415
372
        if (self->__error_message)
416
373
                free(self->__error_message);
 
374
        cancelNeedDataState(self);
 
375
        if (self->callbacks)
 
376
                free(self->callbacks);
 
377
    
 
378
        GDATA_unbind_cols(SC_get_GDTI(self), TRUE);
 
379
 
417
380
        DELETE_STMT_CS(self);
 
381
        if (self->pdata_info.pdata != 0)
 
382
                free(self->pdata_info.pdata);
418
383
        free(self);
419
384
 
420
385
        mylog("SC_Destructor: EXIT\n");
430
395
void
431
396
SC_free_params(StatementClass *self, char option)
432
397
{
433
 
        APD_free_params(SC_get_APD(self), option);
434
 
        IPD_free_params(SC_get_IPD(self), option);
 
398
        if (option != STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY)
 
399
        {
 
400
                APD_free_params(SC_get_APDF(self), option);
 
401
                IPD_free_params(SC_get_IPDF(self), option);
 
402
        }
 
403
        PDATA_free_params(SC_get_PDTI(self), option);
435
404
        self->data_at_exec = -1;
436
405
        self->current_exec_param = -1;
437
406
        self->put_data = FALSE;
450
419
        int                     i;
451
420
 
452
421
        /* ignore leading whitespace in query string */
453
 
        while (*statement && (isspace((unsigned char) *statement) || *statement == '('))
 
422
        while (*statement && (isspace((UCHAR) *statement) || *statement == '('))
454
423
                statement++;
455
424
 
456
425
        for (i = 0; Statement_Type[i].s; i++)
457
426
                if (!strnicmp(statement, Statement_Type[i].s, strlen(Statement_Type[i].s)))
458
427
                        return Statement_Type[i].type;
459
428
 
 
429
        /* determine START TRANSACTION */
 
430
        if (!strnicmp(statement, "START", 5))
 
431
        {
 
432
                statement += 5;
 
433
                /* ignore whitespace in query string */
 
434
                while (*statement && isspace((UCHAR) *statement))
 
435
                        statement++;
 
436
                if (!strnicmp(statement, "TRANSACTION", 11))
 
437
                        return STMT_TYPE_BEGIN;
 
438
        }
460
439
        return STMT_TYPE_OTHER;
461
440
}
462
441
 
 
442
int
 
443
SC_set_current_col(StatementClass *stmt, int col)
 
444
{
 
445
        if (col == stmt->current_col)
 
446
                return col;
 
447
        if (col >= 0)
 
448
                reset_a_getdata_info(SC_get_GDTI(stmt), col + 1);
 
449
        stmt->current_col = col;
 
450
 
 
451
        return stmt->current_col;
 
452
}
 
453
 
463
454
void
464
455
SC_set_prepared(StatementClass *stmt, BOOL prepared)
465
456
{
468
459
        if (!prepared)
469
460
        {
470
461
                ConnectionClass *conn = SC_get_conn(stmt);
471
 
                if (CONN_CONNECTED == conn->status)
 
462
 
 
463
                if (conn && CONN_CONNECTED == conn->status)
472
464
                {
473
 
                        QResultClass    *res;
474
 
                        char dealloc_stmt[128];
475
 
 
476
 
                        sprintf(dealloc_stmt, "DEALLOCATE _PLAN%0x", stmt);
477
 
                        res = CC_send_query(conn, dealloc_stmt, NULL, 0);
478
 
                        if (res)
479
 
                                QR_Destructor(res); 
 
465
                        char    plannm[32];
 
466
 
 
467
                        sprintf(plannm, "_PLAN%p", stmt);
 
468
                        if (CC_is_in_error_trans(conn))
 
469
                        {
 
470
                                CC_mark_a_plan_to_discard(conn, plannm);
 
471
                        }
 
472
                        else
 
473
                        {
 
474
                                QResultClass    *res;
 
475
                                char dealloc_stmt[128];
 
476
 
 
477
                                sprintf(dealloc_stmt, "DEALLOCATE \"%s\"", plannm);
 
478
                                res = CC_send_query(conn, dealloc_stmt, NULL, 0);
 
479
                                if (res)
 
480
                                        QR_Destructor(res);
 
481
                        } 
480
482
                }
481
483
        }
482
484
        stmt->prepared = prepared;
502
504
                        free(self->execute_statement);
503
505
                        self->execute_statement = NULL;
504
506
                }
505
 
                SC_set_prepared(self,FALSE);
 
507
                self->prepare = FALSE;
 
508
                SC_set_prepared(self, FALSE);
 
509
                self->statement_type = STMT_TYPE_UNKNOWN; /* unknown */
 
510
                self->status = STMT_READY;
 
511
                self->num_params = -1; /* unknown */
506
512
        }
507
513
        if (self->stmt_with_params)
508
514
        {
518
524
        return 0;
519
525
}
520
526
 
 
527
BOOL    SC_opencheck(StatementClass *self, const char *func)
 
528
{
 
529
        QResultClass    *res;
 
530
 
 
531
        if (self->status == STMT_EXECUTING)
 
532
        {
 
533
                SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.");
 
534
                return TRUE;
 
535
        }
 
536
        /*
 
537
         * We get here if a statement is prepared and executed to get the metadata.
 
538
         */
 
539
        if (self->prepare && self->status == STMT_PREMATURE)
 
540
        {
 
541
                mylog("SC_opencheck: self->prepare && self->status == STMT_PREMATURE\n");
 
542
                return FALSE;
 
543
        }
 
544
        
 
545
        if (res = SC_get_Curres(self), NULL != res)
 
546
        {
 
547
                if (res->backend_tuples)
 
548
                {
 
549
                        SC_set_error(self, STMT_SEQUENCE_ERROR, "The cursor is open.");
 
550
                        SC_log_error(func, "", self);
 
551
                        return TRUE;
 
552
                }
 
553
        }
 
554
 
 
555
        return  FALSE;
 
556
}
 
557
 
 
558
RETCODE
 
559
SC_initialize_and_recycle(StatementClass *self)
 
560
{
 
561
        SC_initialize_stmts(self, TRUE);
 
562
        if (!SC_recycle_statement(self))
 
563
                return SQL_ERROR;
 
564
 
 
565
        return SQL_SUCCESS;
 
566
}
 
567
 
521
568
/*
522
569
 *      Called from SQLPrepare if STMT_PREMATURE, or
523
570
 *      from SQLExecute if STMT_FINISHED, or
556
603
                         * transaction.
557
604
                         */
558
605
                        conn = SC_get_conn(self);
559
 
                        if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
 
606
                        if (CC_is_in_trans(conn) && !CC_is_in_autocommit(conn) && 
 
607
                            !CC_is_in_manual_trans(conn))
560
608
                        {
561
609
                                if (SC_is_pre_executable(self) && !conn->connInfo.disallow_premature)
562
610
                                        CC_abort(conn);
583
631
                self->ntab = 0;
584
632
        }
585
633
        /* Free the parsed field information */
586
 
        IRDFields_free(SC_get_IRD(self));
 
634
        DC_Destructor((DescriptorClass *) SC_get_IRD(self));
587
635
 
588
636
        self->parse_status = STMT_PARSE_NONE;
589
637
        self->updatable = FALSE;
591
639
        /* Free any cursors */
592
640
        if (res = SC_get_Result(self), res)
593
641
        {
 
642
                if(SC_is_fetchcursor(self))
 
643
                        SC_set_handle(self,res);
594
644
                QR_Destructor(res);
595
645
                SC_set_Result(self, NULL);
596
646
        }
600
650
         * Reset only parameters that have anything to do with results
601
651
         */
602
652
        self->status = STMT_READY;
603
 
        self->manual_result = FALSE;    /* very important */
604
 
 
 
653
        self->manual_result = TRUE;             /* very important */
605
654
        self->currTuple = -1;
606
655
        self->rowset_start = -1;
607
 
        self->current_col = -1;
 
656
        SC_set_current_col(self, -1);
608
657
        self->bind_row = 0;
609
658
        self->last_fetch_count = self->last_fetch_count_include_ommitted = 0;
610
659
 
621
670
         */
622
671
        SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
623
672
        SC_initialize_stmts(self, FALSE);
 
673
        cancelNeedDataState(self);
624
674
        /*
625
675
         *      reset the current attr setting to the original one.
626
676
         */
648
698
                if (self->statement_type == STMT_TYPE_SELECT)
649
699
                {
650
700
                        char            old_pre_executing = self->pre_executing;
 
701
                        RETCODE         ret;
651
702
 
652
703
                        self->pre_executing = TRUE;
653
704
                        self->inaccurate_result = FALSE;
654
705
 
655
 
                        PGAPI_Execute(self);
 
706
                        ret = PGAPI_Execute(self, 0);
656
707
 
657
708
                        self->pre_executing = old_pre_executing;
658
709
 
659
 
                        if (self->status == STMT_FINISHED)
 
710
                        if (self->status == STMT_FINISHED &&
 
711
                            (SQL_SUCCESS == ret ||
 
712
                             SQL_SUCCESS_WITH_INFO == ret))
660
713
                        {
661
714
                                mylog("              preprocess: after status = FINISHED, so set PREMATURE\n");
662
715
                                self->status = STMT_PREMATURE;
677
730
char
678
731
SC_unbind_cols(StatementClass *self)
679
732
{
680
 
        ARDFields       *opts = SC_get_ARD(self);
 
733
        ARDFields       *opts = SC_get_ARDF(self);
 
734
        GetDataInfo     *gdata = SC_get_GDTI(self);
 
735
        BindInfoClass   *bookmark;
681
736
 
682
737
        ARD_unbind_cols(opts, FALSE);
683
 
        opts->bookmark->buffer = NULL;
684
 
        opts->bookmark->used = NULL;
 
738
        GDATA_unbind_cols(gdata, FALSE);
 
739
        if (bookmark = opts->bookmark, bookmark != NULL)
 
740
        {
 
741
                bookmark->buffer = NULL;
 
742
                bookmark->used = NULL;
 
743
        }
685
744
 
686
745
        return 1;
687
746
}
738
797
        }
739
798
        if (conn)
740
799
        {
741
 
                SocketClass *sock = conn->sock;
742
 
 
743
800
                if (!detailmsg && CC_get_errormsg(conn) && (CC_get_errormsg(conn))[0] != '\0')
744
801
                {
745
802
                        pos = strlen(msg);
746
803
                        sprintf(&msg[pos], ";\n%s", CC_get_errormsg(conn));
747
804
                }
748
805
 
749
 
                if (sock && sock->errormsg && sock->errormsg[0] != '\0')
750
 
                {
751
 
                        pos = strlen(msg);
752
 
                        sprintf(&msg[pos], ";\n%s", sock->errormsg);
753
 
                }
754
806
        }
 
807
 
755
808
        return msg[0] ? strdup(msg) : NULL;
756
809
}
757
810
 
823
876
        return rv;
824
877
}
825
878
 
 
879
void
 
880
SC_set_sqlstate(StatementClass *self, const char *sqlstate)
 
881
{
 
882
    if (sqlstate)
 
883
        snprintf(self->__sqlstate, SQLSTATE_LENGTH, "%s", sqlstate);
 
884
    else
 
885
        self->__sqlstate[0] = '\0';
 
886
}
 
887
 
 
888
char *
 
889
SC_get_sqlstate(StatementClass *self)
 
890
{
 
891
    return self->__sqlstate;
 
892
}
 
893
 
826
894
 
827
895
time_t
828
896
SC_get_time(StatementClass *stmt)
838
906
 *      just the current row number.  But it could be more sophisticated
839
907
 *      someday, such as mapping a key to a 32 bit value
840
908
 */
841
 
unsigned long
 
909
UInt4
842
910
SC_get_bookmark(StatementClass *self)
843
911
{
844
912
        return (self->currTuple + 1);
851
919
        CSTR func = "SC_fetch";
852
920
        QResultClass *res = SC_get_Curres(self);
853
921
        ARDFields       *opts;
 
922
        GetDataInfo     *gdata;
854
923
        int                     retval,
855
924
                                result;
856
925
 
858
927
                                lf;
859
928
        Oid                     type;
860
929
        char       *value;
 
930
        char            fetch[128];
 
931
 
 
932
        QueryInfo       qi;
 
933
        UDWORD          qflag = 0;
861
934
        ColumnInfoClass *coli;
 
935
        BindInfoClass   *bookmark;
862
936
 
863
937
        /* TupleField *tupleField; */
864
938
        ConnInfo   *ci = &(SC_get_conn(self)->connInfo);
865
939
 
866
940
        self->last_fetch_count = self->last_fetch_count_include_ommitted = 0;
 
941
 
 
942
        /* Issue the fetch query here in case of declare fetch for subsequent rows */
 
943
        if (SC_is_fetchcursor(self) && ((self->currTuple % ci->drivers.fetch_max) >= QR_get_num_total_tuples(res) - 1))
 
944
        {
 
945
                qi.result_in = NULL;
 
946
                qi.cursor = self->cursor_name;
 
947
                qi.row_size = ci->drivers.fetch_max;
 
948
                sprintf(fetch, "fetch %d in %s",ci->drivers.fetch_max ,self->cursor_name);
 
949
 
 
950
        /* Cleanup the QR. We need to kill off the cursor first, or this willcrash */
 
951
 
 
952
        if (self->result->cursor)
 
953
        {
 
954
            free(self->result->cursor);
 
955
            self->result->cursor = NULL;
 
956
        }
 
957
 
 
958
        if (self->result)
 
959
        {
 
960
            QR_Destructor(self->result);
 
961
            self->result = NULL;
 
962
        }
 
963
 
 
964
        /* Finished cleanup */
 
965
 
 
966
        res = CC_send_query(self->hdbc, fetch, &qi, qflag);
 
967
                SC_set_Result(self,res);
 
968
        }
 
969
 
867
970
        coli = QR_get_fields(res);      /* the column info */
868
 
 
869
971
        mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, ci->drivers.use_declarefetch);
870
972
 
871
 
        if (self->manual_result || !SC_is_fetchcursor(self))
 
973
        if (self->manual_result)
872
974
        {
873
 
                if (self->currTuple >= QR_get_num_total_tuples(res) - 1 ||
874
 
                        (self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1))
875
 
                {
876
 
                        /*
877
 
                         * if at the end of the tuples, return "no data found" and set
878
 
                         * the cursor past the end of the result set
879
 
                         */
880
 
                        self->currTuple = QR_get_num_total_tuples(res);
881
 
                        return SQL_NO_DATA_FOUND;
 
975
                if(!SC_is_fetchcursor(self))
 
976
                {
 
977
                        if (self->currTuple >= QR_get_num_total_tuples(res) - 1 ||
 
978
                                (self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1))
 
979
                        {
 
980
                                /*
 
981
                                 * if at the end of the tuples, return "no data found" and set
 
982
                                 * the cursor past the end of the result set
 
983
                                 */
 
984
                                self->currTuple = QR_get_num_total_tuples(res);
 
985
                                return SQL_NO_DATA_FOUND;
 
986
                        }
 
987
                }
 
988
                else
 
989
                {
 
990
                        if ((((self->currTuple + 1) % ci->drivers.fetch_max) >= QR_get_num_total_tuples(res)) &&
 
991
                                QR_get_num_total_tuples(res) < ci->drivers.fetch_max)
 
992
                        {
 
993
                                SC_no_fetchcursor(self);
 
994
                                self->currTuple = QR_get_num_total_tuples(res);
 
995
                                return SQL_NO_DATA_FOUND;
 
996
                        }
882
997
                }
883
998
 
884
999
                mylog("**** SC_fetch: manual_result\n");
903
1018
                        return SQL_ERROR;
904
1019
                }
905
1020
        }
 
1021
 
906
1022
#ifdef  DRIVER_CURSOR_IMPLEMENT
907
1023
        if (res->haskeyset)
908
1024
        {
921
1037
        self->last_fetch_count++;
922
1038
        self->last_fetch_count_include_ommitted++;
923
1039
 
924
 
        opts = SC_get_ARD(self);
 
1040
        opts = SC_get_ARDF(self);
925
1041
        /*
926
1042
         * If the bookmark column was bound then return a bookmark. Since this
927
1043
         * is used with SQLExtendedFetch, and the rowset size may be greater
928
1044
         * than 1, and an application can use row or column wise binding, use
929
1045
         * the code in copy_and_convert_field() to handle that.
930
1046
         */
931
 
        if (opts->bookmark->buffer)
 
1047
        if ((bookmark = opts->bookmark) && bookmark->buffer)
932
1048
        {
933
1049
                char            buf[32];
934
1050
                UInt4   offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
935
1051
 
936
 
                sprintf(buf, "%ld", SC_get_bookmark(self));
937
 
                result = copy_and_convert_field(self, 0, buf,
938
 
                         SQL_C_ULONG, opts->bookmark->buffer + offset, 0,
939
 
                        opts->bookmark->used ? opts->bookmark->used + (offset >> 2) : NULL);
 
1052
                sprintf(buf, "%ld", (long int) SC_get_bookmark(self));
 
1053
                SC_set_current_col(self, -1);
 
1054
                result = copy_and_convert_field(self, 0, buf, SQL_C_ULONG,
 
1055
                                                bookmark->buffer + offset, 0,
 
1056
                                                (SDWORD *) (bookmark->used ? bookmark->used + (offset >> 2) : NULL));
940
1057
        }
941
1058
 
942
1059
        if (self->options.retrieve_data == SQL_RD_OFF)          /* data isn't required */
943
1060
                return SQL_SUCCESS;
 
1061
        gdata = SC_get_GDTI(self);
 
1062
        if (gdata->allocated != opts->allocated)
 
1063
                extend_getdata_info(gdata, opts->allocated, TRUE);
944
1064
        for (lf = 0; lf < num_cols; lf++)
945
1065
        {
946
1066
                mylog("fetch: cols=%d, lf=%d, opts = %u, opts->bindings = %u, buffer[] = %u\n", num_cols, lf, opts, opts->bindings, opts->bindings[lf].buffer);
947
1067
 
948
1068
                /* reset for SQLGetData */
949
 
                opts->bindings[lf].data_left = -1;
 
1069
                gdata->gdata[lf].data_left = -1;
950
1070
 
951
1071
                if (opts->bindings[lf].buffer != NULL)
952
1072
                {
959
1079
 
960
1080
                        if (self->manual_result)
961
1081
                        {
962
 
                                value = QR_get_value_manual(res, self->currTuple, lf);
 
1082
                                if ((ci->drivers.use_declarefetch) && (self->currTuple >= QR_get_num_total_tuples(res)))
 
1083
                                        value = QR_get_value_manual(res, (self->currTuple >= ci->drivers.fetch_max) ? (self->currTuple % ci->drivers.fetch_max) : self->currTuple, lf);
 
1084
                                else
 
1085
                                        value = QR_get_value_manual(res, self->currTuple, lf);
963
1086
                                mylog("manual_result\n");
964
1087
                        }
965
1088
                        else if (SC_is_fetchcursor(self))
1023
1146
        return result;
1024
1147
}
1025
1148
 
 
1149
#define return  DONT_CALL_RETURN_FROM_HERE???
1026
1150
 
1027
1151
RETCODE
1028
1152
SC_execute(StatementClass *self)
1029
1153
{
1030
1154
        CSTR func = "SC_execute";
1031
1155
        ConnectionClass *conn;
1032
 
        APDFields       *apdopts;
1033
 
        char            was_ok, was_nonfatal, was_rows_affected = 1;
1034
 
        /* was_rows_affected is set to 0 iff an UPDATE or DELETE affects 
1035
 
         * no rows. In this instance the driver should return
1036
 
         * SQL_NO_DATA_FOUND instead of SQL_SUCCESS.
1037
 
         */
1038
 
 
 
1156
        IPDFields       *ipdopts;
 
1157
        char            was_ok, was_nonfatal;
1039
1158
        QResultClass    *res = NULL;
1040
1159
        Int2            oldstatus,
1041
1160
                                numcols;
1042
1161
        QueryInfo       qi;
1043
1162
        ConnInfo   *ci;
1044
1163
        UDWORD          qflag = 0;
1045
 
        BOOL            auto_begin = FALSE, is_in_trans;
 
1164
        BOOL            is_in_trans;
 
1165
        int             func_cs_count = 0;
1046
1166
 
1047
1167
 
1048
1168
        conn = SC_get_conn(self);
1058
1178
         * 2) we are in autocommit off state and the statement isn't of type
1059
1179
         * OTHER.
1060
1180
         */
1061
 
        ENTER_CONN_CS(conn);
 
1181
        ENTER_INNER_CONN_CS(conn, func_cs_count);
1062
1182
        if (CONN_EXECUTING == conn->status)
1063
1183
        {
1064
 
                LEAVE_CONN_CS(conn);
1065
1184
                SC_set_error(self, STMT_SEQUENCE_ERROR, "Connection is already in use.");
1066
 
                SC_log_error(func, "", self);
1067
1185
                mylog("%s: problem with connection\n", func);
1068
 
                return SQL_ERROR;
 
1186
                goto cleanup;
1069
1187
        }
1070
1188
        is_in_trans = CC_is_in_trans(conn);
1071
1189
        if (!self->internal && !is_in_trans &&
1072
1190
                (SC_is_fetchcursor(self) ||
1073
 
                 (!CC_is_in_autocommit(conn) && self->statement_type != STMT_TYPE_OTHER)))
 
1191
                 (!CC_is_in_autocommit(conn) && self->statement_type != STMT_TYPE_BEGIN)))
1074
1192
        {
1075
1193
                mylog("   about to begin a transaction on statement = %u\n", self);
1076
 
                auto_begin = TRUE;
1077
1194
                if (PG_VERSION_GE(conn, 7.1))
1078
1195
                        qflag |= GO_INTO_TRANSACTION;
1079
 
                else if (!CC_begin(conn))
1080
 
                {
1081
 
                        LEAVE_CONN_CS(conn);
 
1196
                else if (!CC_begin(conn))
 
1197
                {
1082
1198
                        SC_set_error(self, STMT_EXEC_ERROR, "Could not begin a transaction");
1083
 
                        SC_log_error(func, "", self);
1084
 
                        return SQL_ERROR;
1085
 
                }
 
1199
                        goto cleanup;
 
1200
                }
1086
1201
        }
1087
1202
 
1088
1203
        oldstatus = conn->status;
1159
1274
        if (CONN_DOWN != conn->status)
1160
1275
                conn->status = oldstatus;
1161
1276
        self->status = STMT_FINISHED;
1162
 
        LEAVE_CONN_CS(conn);
 
1277
        LEAVE_INNER_CONN_CS(func_cs_count, conn);
1163
1278
 
1164
1279
        /* Check the status of the result */
1165
1280
        if (res)
1166
1281
        {
1167
1282
                was_ok = QR_command_successful(res);
1168
1283
                was_nonfatal = QR_command_nonfatal(res);
1169
 
                if (res->command &&
1170
 
                        (strncmp(res->command, "UPDATE", 6) == 0 ||
1171
 
                        strncmp(res->command, "DELETE", 6) == 0) &&
1172
 
                        strtoul(res->command + 7, NULL, 0) == 0)
1173
 
                {
1174
 
                        was_rows_affected = 0;
1175
 
                }
1176
1284
 
1177
1285
                if (was_ok)
1178
1286
                        SC_set_errornumber(self, STMT_OK);
1179
1287
                else
1180
1288
                        SC_set_errornumber(self, was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND);
1181
1289
 
 
1290
                if (QR_command_fatal(res) && PQstatus(conn->pgconn) == CONNECTION_BAD)
 
1291
                    SC_set_errornumber(self, STMT_BAD_ERROR);
 
1292
 
 
1293
                if (SC_get_errornumber(self) == STMT_ERROR_TAKEN_FROM_BACKEND)
 
1294
                        SC_set_sqlstate(self, CC_get_sqlstate(conn));
 
1295
 
1182
1296
                /* set cursor before the first tuple in the list */
1183
1297
                self->currTuple = -1;
1184
 
                self->current_col = -1;
 
1298
                SC_set_current_col(self, -1);
1185
1299
                self->rowset_start = -1;
1186
1300
 
1187
1301
                /* issue "ABORT" when query aborted */
1188
1302
                if (QR_get_aborted(res))
1189
1303
                {
1190
 
                        if (!self->internal)
 
1304
                        if (!self->internal && CC_is_in_trans(conn) && CC_is_in_autocommit(conn) && !CC_is_in_manual_trans(conn))
1191
1305
                                CC_abort(conn);
 
1306
                        else
 
1307
                                QR_set_aborted(res, FALSE);
1192
1308
                }
1193
1309
                else
1194
1310
                {
1202
1318
                        /* now allocate the array to hold the binding info */
1203
1319
                        if (numcols > 0)
1204
1320
                        {
1205
 
                                ARDFields       *opts = SC_get_ARD(self);
 
1321
                                ARDFields       *opts = SC_get_ARDF(self);
1206
1322
                                extend_column_bindings(opts, numcols);
1207
1323
                                if (opts->bindings == NULL)
1208
1324
                                {
1209
1325
                                        QR_Destructor(res);
1210
1326
                                        SC_set_error(self, STMT_NO_MEMORY_ERROR,"Could not get enough free memory to store the binding information");
1211
 
                                        SC_log_error(func, "", self);
1212
 
                                        return SQL_ERROR;
 
1327
                                        goto cleanup;
1213
1328
                                }
1214
1329
                        }
1215
1330
                }
1217
1332
        else
1218
1333
        {
1219
1334
                /* Bad Error -- The error message will be in the Connection */
1220
 
                if (!conn->sock)
1221
 
                        SC_set_error(self, STMT_BAD_ERROR, CC_get_errormsg(conn));
 
1335
                if (!conn->pgconn)
 
1336
                SC_set_error(self, STMT_BAD_ERROR, CC_get_errormsg(conn));
1222
1337
                else if (self->statement_type == STMT_TYPE_CREATE)
1223
1338
                {
1224
1339
                        SC_set_error(self, STMT_CREATE_TABLE_ERROR, "Error creating the table");
1235
1350
                        SC_set_error(self, STMT_EXEC_ERROR, CC_get_errormsg(conn));
1236
1351
                }
1237
1352
 
1238
 
                if (!self->internal)
 
1353
                if (!self->internal && CC_is_in_trans(conn) && CC_is_in_autocommit(conn) && !CC_is_in_manual_trans(conn))
1239
1354
                        CC_abort(conn);
1240
1355
        }
1241
1356
        if (!SC_get_Result(self))
1248
1363
                last->next = res;
1249
1364
        }
1250
1365
 
1251
 
        apdopts = SC_get_APD(self);
 
1366
        ipdopts = SC_get_IPDF(self);
1252
1367
        if (self->statement_type == STMT_TYPE_PROCCALL &&
1253
1368
                (SC_get_errornumber(self) == STMT_OK ||
1254
1369
                 SC_get_errornumber(self) == STMT_INFO_ONLY) &&
1255
 
                apdopts->parameters &&
1256
 
                apdopts->parameters[0].buffer &&
1257
 
                apdopts->parameters[0].paramType == SQL_PARAM_OUTPUT)
 
1370
                ipdopts->parameters &&
 
1371
                ipdopts->parameters[0].paramType == SQL_PARAM_OUTPUT)
1258
1372
        {                                                       /* get the return value of the procedure
1259
1373
                                                                 * call */
1260
1374
                RETCODE         ret;
1263
1377
                ret = SC_fetch(hstmt);
1264
1378
                if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
1265
1379
                {
1266
 
                        ret = PGAPI_GetData(hstmt, 1, apdopts->parameters[0].CType, apdopts->parameters[0].buffer, apdopts->parameters[0].buflen, apdopts->parameters[0].used);
 
1380
                        APDFields       *apdopts = SC_get_APDF(self);
 
1381
 
 
1382
                        ret = PGAPI_GetData(hstmt, 1,
 
1383
                                            apdopts->parameters[0].CType,
 
1384
                                            apdopts->parameters[0].buffer,
 
1385
                                            apdopts->parameters[0].buflen,
 
1386
                                            (SDWORD *) apdopts->parameters[0].used);
1267
1387
                        if (ret != SQL_SUCCESS)
1268
1388
                        {
1269
1389
                                SC_set_error(self, STMT_EXEC_ERROR, "GetData to Procedure return failed.");
1274
1394
                        SC_set_error(self, STMT_EXEC_ERROR, "SC_fetch to get a Procedure return failed.");
1275
1395
                }
1276
1396
        }
 
1397
#undef  return
 
1398
cleanup:
 
1399
        CLEANUP_FUNC_CONN_CS(func_cs_count, conn);
1277
1400
        if (SC_get_errornumber(self) == STMT_OK)
1278
 
                if (was_rows_affected)
1279
 
                        return SQL_SUCCESS;
1280
 
                else
1281
 
                        return SQL_NO_DATA_FOUND;
 
1401
                return SQL_SUCCESS;
1282
1402
        else if (SC_get_errornumber(self) == STMT_INFO_ONLY)
1283
1403
                return SQL_SUCCESS_WITH_INFO;
1284
1404
        else
1290
1410
        }
1291
1411
}
1292
1412
 
 
1413
#define CALLBACK_ALLOC_ONCE     4
 
1414
int enqueueNeedDataCallback(StatementClass *stmt, NeedDataCallfunc func, void *data)
 
1415
{
 
1416
        if (stmt->num_callbacks >= stmt->allocated_callbacks)
 
1417
        {
 
1418
                SC_REALLOC_return_with_error(stmt->callbacks, NeedDataCallback,
 
1419
                        sizeof(NeedDataCallback) * (stmt->allocated_callbacks +
 
1420
                                CALLBACK_ALLOC_ONCE), stmt,
 
1421
                         "Couldn't alloc callbacks", -1) 
 
1422
                stmt->allocated_callbacks += CALLBACK_ALLOC_ONCE;
 
1423
        }
 
1424
        stmt->callbacks[stmt->num_callbacks].func = func;
 
1425
        stmt->callbacks[stmt->num_callbacks].data = data;
 
1426
        stmt->num_callbacks++;
 
1427
 
 
1428
inolog("enqueueNeedDataCallack stmt=%x, func=%x, count=%d\n", stmt, func, stmt->num_callbacks);
 
1429
        return stmt->num_callbacks;
 
1430
}
 
1431
 
 
1432
RETCODE dequeueNeedDataCallback(RETCODE retcode, StatementClass *stmt)
 
1433
{
 
1434
        RETCODE                 ret;
 
1435
        NeedDataCallfunc        func;
 
1436
        void                    *data;
 
1437
        int                     i, cnt;
 
1438
 
 
1439
        mylog("dequeueNeedDataCallback ret=%d count=%d\n", retcode, stmt->num_callbacks);
 
1440
        if (SQL_NEED_DATA == retcode)
 
1441
                return retcode;
 
1442
        if (stmt->num_callbacks <= 0)
 
1443
                return retcode;
 
1444
        func = stmt->callbacks[0].func;
 
1445
        data = stmt->callbacks[0].data;
 
1446
        for (i = 1; i < stmt->num_callbacks; i++)
 
1447
                stmt->callbacks[i - 1] = stmt->callbacks[i];
 
1448
        cnt = --stmt->num_callbacks;
 
1449
        ret = (*func)(retcode, data);
 
1450
        free(data);
 
1451
        if (SQL_NEED_DATA != ret && cnt > 0)
 
1452
                ret = dequeueNeedDataCallback(ret, stmt);
 
1453
        return ret;
 
1454
}
 
1455
 
 
1456
void    cancelNeedDataState(StatementClass *stmt)
 
1457
{
 
1458
        int     cnt = stmt->num_callbacks, i;
 
1459
 
 
1460
        stmt->num_callbacks = 0;
 
1461
        for (i = 0; i < cnt; i++)
 
1462
        {
 
1463
                if (stmt->callbacks[i].data)
 
1464
                        free(stmt->callbacks[i].data);
 
1465
        }
 
1466
        stmt->execute_delegate = NULL;
 
1467
}
1293
1468
 
1294
1469
void
1295
1470
SC_log_error(const char *func, const char *desc, const StatementClass *self)
1300
1475
        if (self)
1301
1476
        {
1302
1477
                QResultClass *res = SC_get_Result(self);
1303
 
                const ARDFields *opts = SC_get_ARD(self);
1304
 
                const APDFields *apdopts = SC_get_APD(self);
 
1478
                const ARDFields *opts = SC_get_ARDF(self);
 
1479
                const APDFields *apdopts = SC_get_APDF(self);
1305
1480
                int     rowsetSize;
1306
1481
 
1307
 
#if (ODBCVER >= 0x0300)
1308
1482
                rowsetSize = (7 == self->transition_status ? opts->size_of_rowset_odbc2 : opts->size_of_rowset);
1309
 
#else
1310
 
                rowsetSize = opts->size_of_rowset_odbc2;
1311
 
#endif /* ODBCVER */
1312
 
                qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
1313
 
                mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
 
1483
 
 
1484
                qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, sqlstate=%s, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__sqlstate), nullcheck(self->__error_message));
 
1485
                mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, sqlstate=%s, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__sqlstate), nullcheck(self->__error_message));
1314
1486
                qlog("                 ------------------------------------------------------------\n");
1315
1487
                qlog("                 hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, res);
1316
1488
                qlog("                 manual_result=%d, prepare=%d, internal=%d\n", self->manual_result, self->prepare, self->internal);