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