forked from postgresql-interfaces/psqlodbc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
statement.h
583 lines (538 loc) · 20.2 KB
/
statement.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
/* File: statement.hPD
*
* Description: See "statement.c"
*
* Comments: See "readme.txt" for copyright and license information.
*
*/
#ifndef __STATEMENT_H__
#define __STATEMENT_H__
#include "psqlodbc.h"
#include <time.h>
#include "pqexpbuffer.h"
#include "pgtypes.h"
#include "bind.h"
#include "descriptor.h"
#include "tuple.h"
#if defined (POSIX_MULTITHREAD_SUPPORT)
#include <pthread.h>
#endif
typedef enum
{
STMT_ALLOCATED, /* The statement handle is allocated, but
* not used so far */
STMT_READY, /* the statement is waiting to be executed */
STMT_DESCRIBED, /* ODBC states that it is legal to call
* e.g. SQLDescribeCol before a call to
* SQLExecute, but after SQLPrepare. To
* get all the necessary information in
* such a case, we parse the query _before_
* the actual call to SQLExecute, and the
* result set contains only column information,
* but no actual data. */
STMT_FINISHED, /* statement execution has finished */
STMT_EXECUTING /* statement execution is still going on */
} STMT_Status;
/*
* ERROR status code
*
* The code for warnings must be minus
* and LOWEST_STMT_ERROR must be set to
* the least code number.
* The code for STMT_OK is 0 and error
* codes follow after it.
*/
enum {
LOWEST_STMT_ERROR = (-6)
/* minus values mean warning returns */
,STMT_ERROR_IN_ROW = (-6)
,STMT_OPTION_VALUE_CHANGED = (-5)
,STMT_ROW_VERSION_CHANGED = (-4)
,STMT_POS_BEFORE_RECORDSET = (-3)
,STMT_TRUNCATED = (-2)
,STMT_INFO_ONLY = (-1)
/* not an error message,
* just a notification
* to be returned by
* SQLError
*/
,STMT_OK = 0
,STMT_EXEC_ERROR
,STMT_STATUS_ERROR
,STMT_SEQUENCE_ERROR
,STMT_NO_MEMORY_ERROR
,STMT_COLNUM_ERROR
,STMT_NO_STMTSTRING
,STMT_ERROR_TAKEN_FROM_BACKEND
,STMT_INTERNAL_ERROR
,STMT_STILL_EXECUTING
,STMT_NOT_IMPLEMENTED_ERROR
,STMT_BAD_PARAMETER_NUMBER_ERROR
,STMT_OPTION_OUT_OF_RANGE_ERROR
,STMT_INVALID_COLUMN_NUMBER_ERROR
,STMT_RESTRICTED_DATA_TYPE_ERROR
,STMT_INVALID_CURSOR_STATE_ERROR
,STMT_CREATE_TABLE_ERROR
,STMT_NO_CURSOR_NAME
,STMT_INVALID_CURSOR_NAME
,STMT_INVALID_ARGUMENT_NO
,STMT_ROW_OUT_OF_RANGE
,STMT_OPERATION_CANCELLED
,STMT_INVALID_CURSOR_POSITION
,STMT_VALUE_OUT_OF_RANGE
,STMT_OPERATION_INVALID
,STMT_PROGRAM_TYPE_OUT_OF_RANGE
,STMT_BAD_ERROR
,STMT_INVALID_OPTION_IDENTIFIER
,STMT_RETURN_NULL_WITHOUT_INDICATOR
,STMT_INVALID_DESCRIPTOR_IDENTIFIER
,STMT_OPTION_NOT_FOR_THE_DRIVER
,STMT_FETCH_OUT_OF_RANGE
,STMT_COUNT_FIELD_INCORRECT
,STMT_INVALID_NULL_ARG
,STMT_NO_RESPONSE
,STMT_COMMUNICATION_ERROR
,STMT_STRING_CONVERSION_ERROR
};
/* statement types */
enum
{
STMT_TYPE_UNKNOWN = -2
,STMT_TYPE_OTHER = -1
,STMT_TYPE_SELECT = 0
,STMT_TYPE_WITH
,STMT_TYPE_PROCCALL
,STMT_TYPE_TRANSACTION
,STMT_TYPE_DECLARE
,STMT_TYPE_FETCH
,STMT_TYPE_CLOSE
,STMT_TYPE_INSERT
,STMT_TYPE_UPDATE
,STMT_TYPE_DELETE
,STMT_TYPE_CREATE
,STMT_TYPE_ALTER
,STMT_TYPE_DROP
,STMT_TYPE_GRANT
,STMT_TYPE_REVOKE
,STMT_TYPE_LOCK
,STMT_TYPE_PREPARE
,STMT_TYPE_EXECUTE
,STMT_TYPE_DEALLOCATE
,STMT_TYPE_ANALYZE
,STMT_TYPE_NOTIFY
,STMT_TYPE_EXPLAIN
,STMT_TYPE_SET
,STMT_TYPE_RESET
,STMT_TYPE_MOVE
,STMT_TYPE_COPY
,STMT_TYPE_START
,STMT_TYPE_SPECIAL
};
#define STMT_UPDATE(stmt) ((stmt)->statement_type > STMT_TYPE_PROCCALL)
/* Parsing status */
enum
{
STMT_PARSE_NONE = 0
,STMT_PARSE_COMPLETE /* the driver parsed the statement */
,STMT_PARSE_INCOMPLETE
,STMT_PARSE_FATAL
,STMT_PARSE_MASK = 3L
,STMT_PARSED_OIDS = (1L << 2)
,STMT_FOUND_KEY = (1L << 3)
,STMT_HAS_ROW_DESCRIPTION = (1L << 4) /* already got the col info */
,STMT_REFLECTED_ROW_DESCRIPTION = (1L << 5)
};
/* transition status */
enum
{
STMT_TRANSITION_UNALLOCATED = 0
,STMT_TRANSITION_ALLOCATED = 1
,STMT_TRANSITION_FETCH_SCROLL = 6
,STMT_TRANSITION_EXTENDED_FETCH = 7
};
/* Result style */
enum
{
STMT_FETCH_NONE = 0,
STMT_FETCH_NORMAL,
STMT_FETCH_EXTENDED
};
/* Type of the 3rd parameter of Exec_with_parameters_resolved() */
typedef enum {
DIRECT_EXEC,
DEFFERED_EXEC,
LAST_EXEC
} EXEC_TYPE;
#define PG_NUM_NORMAL_KEYS 2
typedef RETCODE (*NeedDataCallfunc)(RETCODE, void *);
typedef struct
{
NeedDataCallfunc func;
void *data;
} NeedDataCallback;
/*
* ProcessedStmt represents a fragment of the original SQL query, after
* converting ? markers to $n style, processing ODBC escapes, and splitting
* a multi-statement into individual statements. Each individual statement
* is represented by one ProcessedStmt struct.
*/
struct ProcessedStmt
{
struct ProcessedStmt *next;
char *query;
int num_params; /* number of parameter markers in this,
* fragment or -1 if not known */
};
typedef struct ProcessedStmt ProcessedStmt;
/******** Statement Handle ***********/
struct StatementClass_
{
ConnectionClass *hdbc; /* pointer to ConnectionClass this
* statement belongs to */
QResultHold rhold;
QResultClass *curres; /* the current result in the chain */
QResultClass *parsed; /* parsed result before exec */
HSTMT *phstmt;
StatementOptions options;
StatementOptions options_orig;
/* attached descriptor handles */
DescriptorClass *ard;
DescriptorClass *apd;
DescriptorClass *ird;
DescriptorClass *ipd;
/* implicit descriptor handles */
DescriptorClass ardi;
DescriptorClass irdi;
DescriptorClass apdi;
DescriptorClass ipdi;
STMT_Status status;
char *__error_message;
int __error_number;
PG_ErrorInfo *pgerror;
SQLLEN currTuple; /* current absolute row number (GetData,
* SetPos, SQLFetch) */
GetDataInfo gdata_info;
SQLLEN save_rowset_size; /* saved rowset size in case of
* change/FETCH_NEXT */
SQLLEN rowset_start; /* start of rowset (an absolute row
* number) */
SQLSETPOSIROW bind_row; /* current offset for Multiple row/column
* binding */
Int2 current_col; /* current column for GetData -- used to
* handle multiple calls */
SQLLEN last_fetch_count; /* number of rows retrieved in
* last fetch/extended fetch */
int lobj_fd; /* fd of the current large object */
char *statement; /* if non--null pointer to the SQL
* statement that has been executed */
/*
* processed_statements is the SQL after splitting multi-statement into
* parts, and replacing ? markers with $n style markers, or injecting the
* values in UseServerSidePrepare=0 mode.
*/
ProcessedStmt *processed_statements;
TABLE_INFO **ti;
Int2 ntab;
Int2 num_key_fields;
Int2 statement_type; /* According to the defines above */
Int2 num_params;
Int2 data_at_exec; /* Number of params needing SQLPutData */
Int2 current_exec_param; /* The current parameter for
* SQLPutData */
UDWORD iflag; /* PGAPI_AllocStmt parameter */
PutDataInfo pdata_info;
po_ind_t parse_status;
po_ind_t proc_return;
po_ind_t put_data; /* Has SQLPutData been called ? */
po_ind_t catalog_result; /* Is this a result of catalog function ? */
po_ind_t prepare; /* is this a prepared statement ? */
po_ind_t prepared; /* is this statement already
* prepared at the server ? */
po_ind_t external; /* Allocated via SQLAllocHandle() */
po_ind_t transition_status; /* Transition status */
po_ind_t multi_statement; /* -1:unknown 0:single 1:multi */
po_ind_t rb_or_tc; /* rollback on error */
po_ind_t discard_output_params; /* discard output parameters on parse stage */
po_ind_t cancel_info; /* cancel information */
po_ind_t ref_CC_error; /* refer to CC_error ? */
po_ind_t lock_CC_for_rb; /* lock CC for statement rollback ? */
po_ind_t join_info; /* have joins ? */
po_ind_t parse_method; /* parse_statement is forced or ? */
po_ind_t has_notice; /* exec result contains notice messages ? */
pgNAME cursor_name;
char *plan_name;
char *stmt_with_params; /* statement after parameter
* substitution */
SQLLEN exec_start_row;
SQLLEN exec_end_row;
SQLLEN exec_current_row;
unsigned char miscinfo;
unsigned char execinfo;
po_ind_t updatable;
SQLLEN diag_row_count;
char *load_statement; /* to (re)load updatable individual rows */
ssize_t from_pos;
ssize_t load_from_pos;
ssize_t where_pos;
SQLLEN last_fetch_count_include_ommitted;
time_t stmt_time;
struct tm localtime;
// for batch execution
signed char use_server_side_prepare;
int batch_size;
EXEC_TYPE exec_type;
int count_of_deffered;
PQExpBufferData stmt_deffered;
/* SQL_NEED_DATA Callback list */
StatementClass *execute_delegate;
StatementClass *execute_parent;
UInt2 allocated_callbacks;
UInt2 num_callbacks;
NeedDataCallback *callbacks;
#if defined(WIN_MULTITHREAD_SUPPORT)
CRITICAL_SECTION cs;
#elif defined(POSIX_THREADMUTEX_SUPPORT)
pthread_mutex_t cs;
#endif /* WIN_MULTITHREAD_SUPPORT */
};
#define SC_get_conn(a) ((a)->hdbc)
void SC_init_Result(StatementClass *self);
void SC_set_Result(StatementClass *self, QResultClass *res);
void SC_set_ResultHold(StatementClass *self, QResultHold rhold);
QResultClass *SC_get_lastres(StatementClass *stmt);
#define SC_get_Result(a) ((a)->rhold).first
#define SC_set_Curres(a, b) ((a)->curres = b)
#define SC_get_Curres(a) ((a)->curres)
#define SC_get_ExecdOrParsed(a) ((a)->curres ? (a)->curres : (a)->parsed)
#define SC_get_ARD(a) ((a)->ard)
#define SC_get_APD(a) ((a)->apd)
#define SC_get_IRD(a) ((a)->ird)
#define SC_get_IPD(a) ((a)->ipd)
#define SC_get_ARDF(a) (&(SC_get_ARD(a)->ardf))
#define SC_get_APDF(a) (&(SC_get_APD(a)->apdf))
#define SC_get_IRDF(a) (&(SC_get_IRD(a)->irdf))
#define SC_get_IPDF(a) (&(SC_get_IPD(a)->ipdf))
#define SC_get_ARDi(a) (&((a)->ardi))
#define SC_get_APDi(a) (&((a)->apdi))
#define SC_get_IRDi(a) (&((a)->irdi))
#define SC_get_IPDi(a) (&((a)->ipdi))
#define SC_get_GDTI(a) (&((a)->gdata_info))
#define SC_get_PDTI(a) (&((a)->pdata_info))
#define SC_get_errornumber(a) ((a)->__error_number)
#define SC_set_errornumber(a, n) ((a)->__error_number = n)
#define SC_get_errormsg(a) ((a)->__error_message)
#define SC_is_prepare_statement(a) (0 != ((a)->prepare & PREPARE_STATEMENT))
#define SC_get_prepare_method(a) ((a)->prepare & (~PREPARE_STATEMENT))
#define SC_parsed_status(a) ((a)->parse_status & STMT_PARSE_MASK)
#define SC_set_parse_status(a, s) ((a)->parse_status |= s)
#define SC_update_not_ready(a) (SC_parsed_status(a) == STMT_PARSE_NONE || 0 == ((a)->parse_status & STMT_PARSED_OIDS))
#define SC_update_ready(a) (SC_parsed_status(a) == STMT_PARSE_COMPLETE && 0 != ((a)->parse_status & STMT_FOUND_KEY) && (a)->updatable)
#define SC_set_checked_hasoids(a, b) ((a)->parse_status |= (STMT_PARSED_OIDS | (b ? STMT_FOUND_KEY : 0)))
#define SC_checked_hasoids(a) (0 != ((a)->parse_status & STMT_PARSED_OIDS))
#define SC_set_delegate(p, c) ((p)->execute_delegate = c, (c)->execute_parent = p)
#define SC_is_updatable(s) (0 < ((s)->updatable))
#define SC_reset_updatable(s) ((s)->updatable = -1)
#define SC_set_updatable(s, b) ((s)->updatable = (b))
#define SC_clear_parse_method(s) ((s)->parse_method = 0)
#define SC_is_parse_forced(s) (0 != ((s)->parse_method & 1L))
#define SC_set_parse_forced(s) ((s)->parse_method |= 1L)
#define SC_cursor_is_valid(s) (NAME_IS_VALID((s)->cursor_name))
#define SC_cursor_name(s) (SAFE_NAME((s)->cursor_name))
void SC_reset_delegate(RETCODE, StatementClass *);
StatementClass *SC_get_ancestor(StatementClass *);
#define SC_is_lower_case(a, b) ((a)->options.metadata_id || (b)->connInfo.lower_case_identifier)
#define SC_MALLOC_return_with_error(t, tp, s, a, m, r) \
do { \
if (t = (tp *) malloc(s), NULL == t) \
{ \
SC_set_error(a, STMT_NO_MEMORY_ERROR, m, "SC_MALLOC"); \
return r; \
} \
} while (0)
#define SC_MALLOC_gexit_with_error(t, tp, s, a, m, r) \
do { \
if (t = (tp *) malloc(s), NULL == t) \
{ \
SC_set_error(a, STMT_NO_MEMORY_ERROR, m, "SC_MALLOC"); \
r; \
goto cleanup; \
} \
} while (0)
#define SC_REALLOC_return_with_error(t, tp, s, a, m, r) \
do { \
tp *tmp; \
if (tmp = (tp *) realloc(t, s), NULL == tmp) \
{ \
SC_set_error(a, STMT_NO_MEMORY_ERROR, m, "SC_REALLOC"); \
return r; \
} \
t = tmp; \
} while (0)
#define SC_REALLOC_gexit_with_error(t, tp, s, a, m, r) \
do { \
tp *tmp; \
if (tmp = (tp *) realloc(t, s), NULL == tmp) \
{ \
SC_set_error(a, STMT_NO_MEMORY_ERROR, m, __FUNCTION__); \
r; \
goto cleanup; \
} \
t = tmp; \
} while (0)
/* options for SC_free_params() */
#define STMT_FREE_PARAMS_ALL 0
#define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY 1
/* prepare state */
enum {
NON_PREPARE_STATEMENT = 0
, PREPARE_STATEMENT = 1
, PREPARE_BY_THE_DRIVER = (1L << 1)
, NAMED_PARSE_REQUEST = (3L << 1)
, PARSE_TO_EXEC_ONCE = (4L << 1)
, PARSE_REQ_FOR_INFO = (5L << 1)
};
/* prepared state */
enum
{
NOT_YET_PREPARED = 0
,PREPARING_PERMANENTLY
,PREPARING_TEMPORARILY
,PREPARED_PERMANENTLY
,PREPARED_TEMPORARILY /* Is currently, or once was, prepared as unnamed
* statement. You must check
* connection->unnamed_prepared_stmt to see if it
* still is */
};
/* misc info */
#define SC_set_fetchcursor(a) ((a)->miscinfo |= (1L << 1))
#define SC_no_fetchcursor(a) ((a)->miscinfo &= ~(1L << 1))
#define SC_is_fetchcursor(a) (((a)->miscinfo & (1L << 1)) != 0)
#define SC_miscinfo_clear(a) ((a)->miscinfo = 0)
#define SC_set_with_hold(a) ((a)->execinfo |= 1L)
#define SC_set_without_hold(a) ((a)->execinfo &= (~1L))
#define SC_is_with_hold(a) (((a)->execinfo & 1L) != 0)
#define SC_set_readonly(a) ((a)->execinfo |= (1L << 1))
#define SC_set_no_readonly(a) ((a)->execinfo &= ~(1L << 1))
#define SC_is_readonly(a) (((a)->execinfo & (1L << 1)) != 0)
#define SC_execinfo_clear(a) (((a)->execinfo = 0)
#define STMT_HAS_NO_JOIN 0L
#define STMT_HAS_OUTER_JOIN 1L
#define STMT_HAS_INNER_JOIN (1L << 1)
#define SC_has_join(a) (0 != (a)->join_info)
#define SC_has_outer_join(a) (0 != (STMT_HAS_OUTER_JOIN & (a)->join_info))
#define SC_has_inner_join(a) (0 != (STMT_HAS_INNER_JOIN & (a)->join_info))
#define SC_set_outer_join(a) ((a)->join_info |= STMT_HAS_OUTER_JOIN)
#define SC_set_inner_join(a) ((a)->join_info |= STMT_HAS_INNER_JOIN)
#define SC_start_tc_stmt(a) ((a)->rb_or_tc = (1L << 1))
#define SC_is_tc_stmt(a) (((a)->rb_or_tc & (1L << 1)) != 0)
#define SC_start_rb_stmt(a) ((a)->rb_or_tc = (1L << 2))
#define SC_is_rb_stmt(a) (((a)->rb_or_tc & (1L << 2)) != 0)
#define SC_unref_CC_error(a) (((a)->ref_CC_error) = FALSE)
#define SC_ref_CC_error(a) (((a)->ref_CC_error) = TRUE)
#define SC_can_parse_statement(a) (STMT_TYPE_SELECT == (a)->statement_type)
/*
* DECLARE CURSOR + FETCH can only be used with SELECT-type queries. And
* it's not currently supported with array-bound parameters.
*/
#define SC_may_use_cursor(a) \
(SC_get_APDF(a)->paramset_size <= 1 && \
(STMT_TYPE_SELECT == (a)->statement_type || STMT_TYPE_WITH == (a)->statement_type) )
#define SC_may_fetch_rows(a) (STMT_TYPE_SELECT == (a)->statement_type || STMT_TYPE_WITH == (a)->statement_type)
/* For Multi-thread */
#if defined(WIN_MULTITHREAD_SUPPORT)
#define INIT_STMT_CS(x) InitializeCriticalSection(&((x)->cs))
#define ENTER_STMT_CS(x) EnterCriticalSection(&((x)->cs))
#define TRY_ENTER_STMT_CS(x) TryEnterCriticalSection(&((x)->cs))
#define LEAVE_STMT_CS(x) LeaveCriticalSection(&((x)->cs))
#define DELETE_STMT_CS(x) DeleteCriticalSection(&((x)->cs))
#elif defined(POSIX_THREADMUTEX_SUPPORT)
#define INIT_STMT_CS(x) pthread_mutex_init(&((x)->cs),0)
#define ENTER_STMT_CS(x) pthread_mutex_lock(&((x)->cs))
#define TRY_ENTER_STMT_CS(x) (0 == pthread_mutex_trylock(&((x)->cs)))
#define LEAVE_STMT_CS(x) pthread_mutex_unlock(&((x)->cs))
#define DELETE_STMT_CS(x) pthread_mutex_destroy(&((x)->cs))
#else
#define INIT_STMT_CS(x)
#define ENTER_STMT_CS(x)
#define TRY_ENTER_STMT_CS(x) (1)
#define LEAVE_STMT_CS(x)
#define DELETE_STMT_CS(x)
#endif /* WIN_MULTITHREAD_SUPPORT */
/* Statement prototypes */
StatementClass *SC_Constructor(ConnectionClass *);
void InitializeStatementOptions(StatementOptions *opt);
char SC_Destructor(StatementClass *self);
BOOL SC_opencheck(StatementClass *self, const char *func);
RETCODE SC_initialize_and_recycle(StatementClass *self);
void SC_initialize_cols_info(StatementClass *self, BOOL DCdestroy, BOOL parseReset);
void SC_reset_result_for_rerun(StatementClass *self);
int statement_type(const char *statement);
char parse_statement(StatementClass *stmt, BOOL);
char parse_sqlsvr(StatementClass *stmt);
SQLRETURN SC_set_SS_columnkey(StatementClass *stmt);
Int4 SC_describe(StatementClass *self);
char SC_unbind_cols(StatementClass *self);
char SC_recycle_statement(StatementClass *self);
void SC_clear_error(StatementClass *self);
void SC_set_error(StatementClass *self, int errnum, const char *msg, const char *func);
void SC_set_errormsg(StatementClass *self, const char *msg);
void SC_error_copy(StatementClass *self, const StatementClass *from, BOOL);
void SC_full_error_copy(StatementClass *self, const StatementClass *from, BOOL);
void SC_replace_error_with_res(StatementClass *self, int errnum, const char *msg, const QResultClass*, BOOL);
void SC_set_prepared(StatementClass *self, int);
void SC_set_planname(StatementClass *self, const char *plan_name);
void SC_set_rowset_start(StatementClass *self, SQLLEN, BOOL);
void SC_inc_rowset_start(StatementClass *self, SQLLEN);
RETCODE SC_initialize_stmts(StatementClass *self, BOOL);
RETCODE SC_execute(StatementClass *self);
RETCODE SC_fetch(StatementClass *self);
void SC_free_params(StatementClass *self, char option);
void SC_log_error(const char *func, const char *desc, const StatementClass *self);
time_t SC_get_time(StatementClass *self);
struct tm *SC_get_localtime(StatementClass *self);
SQLLEN SC_get_int4_bookmark(StatementClass *self);
RETCODE SC_pos_reload(StatementClass *self, SQLULEN index, UInt2 *, Int4);
RETCODE SC_pos_update(StatementClass *self, SQLSETPOSIROW irow, SQLULEN index, const KeySet *keyset);
RETCODE SC_pos_delete(StatementClass *self, SQLSETPOSIROW irow, SQLULEN index, const KeySet *keyset);
RETCODE SC_pos_refresh(StatementClass *self, SQLSETPOSIROW irow, SQLULEN index);
RETCODE SC_pos_fetch(StatementClass *self, const PG_BM *pg_bm);
RETCODE SC_pos_add(StatementClass *self, SQLSETPOSIROW irow);
RETCODE SC_fetch_by_bookmark(StatementClass *self);
int SC_Create_bookmark(StatementClass *stmt, BindInfoClass *bookmark, Int4 row_pos, Int4 currTuple, const KeySet *keyset);
PG_BM SC_Resolve_bookmark(const ARDFields *opts, Int4 idx);
int SC_set_current_col(StatementClass *self, int col);
void SC_setInsertedTable(StatementClass *, RETCODE);
void SC_scanQueryAndCountParams(const char *, const ConnectionClass *,
ssize_t *next_cmd, SQLSMALLINT *num_params,
po_ind_t *multi, po_ind_t *proc_return);
BOOL SC_IsExecuting(const StatementClass *self);
BOOL SC_SetExecuting(StatementClass *self, BOOL on);
BOOL SC_SetCancelRequest(StatementClass *self);
BOOL SC_AcceptedCancelRequest(const StatementClass *self);
BOOL SC_connection_lost_check(StatementClass *stmt, const char *funcname);
int enqueueNeedDataCallback(StatementClass *self, NeedDataCallfunc, void *);
RETCODE dequeueNeedDataCallback(RETCODE, StatementClass *self);
void cancelNeedDataState(StatementClass *self);
int StartRollbackState(StatementClass *self);
RETCODE SetStatementSvp(StatementClass *self, unsigned int option);
RETCODE DiscardStatementSvp(StatementClass *self, RETCODE, BOOL errorOnly);
QResultClass *ParseAndDescribeWithLibpq(StatementClass *stmt, const char *plan_name, const char *query_p, Int2 num_params, const char *comment, QResultClass *res);
BOOL CheckPgClassInfo(StatementClass *);
/*
* Macros to convert global index <-> relative index in resultset/rowset
*/
/* a global index to the relative index in a rowset */
#define SC_get_rowset_start(stmt) ((stmt)->rowset_start)
#define GIdx2RowIdx(gidx, stmt) (gidx - (stmt)->rowset_start)
/* a global index to the relative index in a resultset(not a rowset) */
#define GIdx2CacheIdx(gidx, s, r) (gidx - (QR_has_valid_base(r) ? ((s)->rowset_start - (r)->base) : 0))
#define GIdx2KResIdx(gidx, s, r) (gidx - (QR_has_valid_base(r) ? ((s)->rowset_start - (r)->key_base) : 0))
/* a relative index in a rowset to the global index */
#define RowIdx2GIdx(ridx, stmt) (ridx + (stmt)->rowset_start)
/* a relative index in a resultset to the global index */
#define CacheIdx2GIdx(ridx, stmt, res) (ridx - (res)->base + (stmt)->rowset_start)
#define KResIdx2GIdx(ridx, stmt, res) (ridx - (res)->key_base + (stmt)->rowset_start)
#define BOOKMARK_SHIFT 1
#define SC_make_int4_bookmark(b) ((b < 0) ? (b) : (b + BOOKMARK_SHIFT))
#define SC_resolve_int4_bookmark(b) ((b < 0) ? (b) : (b - BOOKMARK_SHIFT))
#endif /* __STATEMENT_H__ */