3 * Description: See "statement.c"
5 * Comments: See "notice.txt" for copyright and license information.
9 #ifndef __STATEMENT_H__
10 #define __STATEMENT_H__
17 #include "descriptor.h"
19 #if defined (POSIX_MULTITHREAD_SUPPORT)
25 STMT_ALLOCATED
, /* The statement handle is allocated, but
27 STMT_READY
, /* the statement is waiting to be executed */
28 STMT_PREMATURE
, /* ODBC states that it is legal to call
29 * e.g. SQLDescribeCol before a call to
30 * SQLExecute, but after SQLPrepare. To
31 * get all the necessary information in
32 * such a case, we simply execute the
33 * query _before_ the actual call to
34 * SQLExecute, so that statement is
35 * considered to be "premature". */
36 STMT_FINISHED
, /* statement execution has finished */
37 STMT_EXECUTING
/* statement execution is still going on */
42 * The code for warnings must be minus
43 * and LOWEST_STMT_ERROR must be set to
44 * the least code number.
45 * The code for STMT_OK is 0 and error
46 * codes follow after it.
49 LOWEST_STMT_ERROR
= (-6)
50 /* minus values mean warning returns */
51 ,STMT_ERROR_IN_ROW
= (-6)
52 ,STMT_OPTION_VALUE_CHANGED
= (-5)
53 ,STMT_ROW_VERSION_CHANGED
= (-4)
54 ,STMT_POS_BEFORE_RECORDSET
= (-3)
55 ,STMT_TRUNCATED
= (-2)
56 ,STMT_INFO_ONLY
= (-1)
57 /* not an error message,
69 ,STMT_ERROR_TAKEN_FROM_BACKEND
72 ,STMT_NOT_IMPLEMENTED_ERROR
73 ,STMT_BAD_PARAMETER_NUMBER_ERROR
74 ,STMT_OPTION_OUT_OF_RANGE_ERROR
75 ,STMT_INVALID_COLUMN_NUMBER_ERROR
76 ,STMT_RESTRICTED_DATA_TYPE_ERROR
77 ,STMT_INVALID_CURSOR_STATE_ERROR
78 ,STMT_CREATE_TABLE_ERROR
80 ,STMT_INVALID_CURSOR_NAME
81 ,STMT_INVALID_ARGUMENT_NO
82 ,STMT_ROW_OUT_OF_RANGE
83 ,STMT_OPERATION_CANCELLED
84 ,STMT_INVALID_CURSOR_POSITION
85 ,STMT_VALUE_OUT_OF_RANGE
86 ,STMT_OPERATION_INVALID
87 ,STMT_PROGRAM_TYPE_OUT_OF_RANGE
89 ,STMT_INVALID_OPTION_IDENTIFIER
90 ,STMT_RETURN_NULL_WITHOUT_INDICATOR
91 ,STMT_INVALID_DESCRIPTOR_IDENTIFIER
92 ,STMT_OPTION_NOT_FOR_THE_DRIVER
93 ,STMT_FETCH_OUT_OF_RANGE
94 ,STMT_COUNT_FIELD_INCORRECT
95 ,STMT_INVALID_NULL_ARG
101 STMT_TYPE_UNKNOWN
= -2
102 ,STMT_TYPE_OTHER
= -1
103 ,STMT_TYPE_SELECT
= 0
114 ,STMT_TYPE_TRANSACTION
119 ,STMT_TYPE_DEALLOCATE
132 #define STMT_UPDATE(stmt) (stmt->statement_type > STMT_TYPE_SELECT)
139 ,STMT_PARSE_COMPLETE
/* the driver parsed the statement */
140 ,STMT_PARSE_INCOMPLETE
142 ,STMT_PARSE_MASK
= 3L
143 ,STMT_PARSED_OIDS
= (1L << 2)
144 ,STMT_FOUND_KEY
= (1L << 3)
145 ,STMT_HAS_ROW_DESCRIPTION
= (1L << 4) /* already got the col info */
146 ,STMT_REFLECTED_ROW_DESCRIPTION
= (1L << 5)
157 #define PG_NUM_NORMAL_KEYS 2
159 typedef RETCODE (*NeedDataCallfunc
)(RETCODE
, void *);
162 NeedDataCallfunc func
;
166 /******** Statement Handle ***********/
167 struct StatementClass_
169 ConnectionClass
*hdbc
; /* pointer to ConnectionClass this
170 * statement belongs to */
171 QResultClass
*result
; /* result of the current statement */
172 QResultClass
*curres
; /* the current result in the chain */
174 StatementOptions options
;
175 StatementOptions options_orig
;
176 /* attached descriptor handles */
181 /* implicit descriptor handles */
188 char *__error_message
;
190 PG_ErrorInfo
*pgerror
;
192 SQLLEN currTuple
; /* current absolute row number (GetData,
193 * SetPos, SQLFetch) */
194 GetDataInfo gdata_info
;
195 SQLLEN save_rowset_size
; /* saved rowset size in case of
196 * change/FETCH_NEXT */
197 SQLLEN rowset_start
; /* start of rowset (an absolute row
199 SQLSETPOSIROW bind_row
; /* current offset for Multiple row/column
201 Int2 current_col
; /* current column for GetData -- used to
202 * handle multiple calls */
203 SQLLEN last_fetch_count
; /* number of rows retrieved in
204 * last fetch/extended fetch */
206 char *statement
; /* if non--null pointer to the SQL
207 * statement that has been executed */
212 Int2 statement_type
; /* According to the defines above */
214 Int2 data_at_exec
; /* Number of params needing SQLPutData */
215 Int2 current_exec_param
; /* The current parameter for
219 char put_data
; /* Has SQLPutData been called ? */
220 char catalog_result
; /* Is this a result of catalog function ? */
221 char prepare
; /* is this a prepared statement ? */
222 char prepared
; /* is this statement already
223 * prepared at the server ? */
224 char internal
; /* Is this statement being called
226 char transition_status
; /* Transition status */
227 char multi_statement
; /* -1:unknown 0:single 1:multi */
228 char discard_output_params
; /* discard output parameters on parse stage */
229 char cancel_info
; /* cancel information */
230 char ref_CC_error
; /* refer to CC_error ? */
231 char lock_CC_for_rb
; /* lock CC for statement rollback ? */
232 char join_info
; /* have joins ? */
233 char parse_method
; /* parse_statement is forced or ? */
237 char *stmt_with_params
; /* statement after parameter
239 Int4 stmt_size_limit
; /* PG restriction */
240 SQLLEN exec_start_row
;
242 SQLLEN exec_current_row
;
244 char pre_executing
; /* This statement is prematurely executing */
245 char inaccurate_result
; /* Current status is PREMATURE but
246 * result is inaccurate */
247 unsigned char miscinfo
;
249 SQLLEN diag_row_count
;
250 char *load_statement
; /* to (re)load updatable individual rows */
251 char *execute_statement
; /* to execute the prepared plans */
254 SQLLEN last_fetch_count_include_ommitted
;
256 /* SQL_NEED_DATA Callback list */
257 StatementClass
*execute_delegate
;
258 StatementClass
*execute_parent
;
259 UInt2 allocated_callbacks
;
261 NeedDataCallback
*callbacks
;
262 #if defined(WIN_MULTITHREAD_SUPPORT)
264 #elif defined(POSIX_THREADMUTEX_SUPPORT)
266 #endif /* WIN_MULTITHREAD_SUPPORT */
270 #define SC_get_conn(a) (a->hdbc)
271 #define SC_init_Result(a) (a->result = a->curres = NULL, mylog("result=%x\n", a)+1)
272 void SC_set_Result(StatementClass
*s
, QResultClass
*q
);
273 #define SC_get_Result(a) (a->result)
274 #define SC_set_Curres(a, b) (a->curres = b)
275 #define SC_get_Curres(a) (a->curres)
276 #define SC_get_ARD(a) (a->ard)
277 #define SC_get_APD(a) (a->apd)
278 #define SC_get_IRD(a) (a->ird)
279 #define SC_get_IPD(a) (a->ipd)
280 #define SC_get_ARDF(a) (&(SC_get_ARD(a)->ardopts))
281 #define SC_get_APDF(a) (&(SC_get_APD(a)->apdopts))
282 #define SC_get_IRDF(a) (&(SC_get_IRD(a)->irdopts))
283 #define SC_get_IPDF(a) (&(SC_get_IPD(a)->ipdopts))
284 #define SC_get_ARDi(a) (&(a->ardi))
285 #define SC_get_APDi(a) (&(a->apdi))
286 #define SC_get_IRDi(a) (&(a->irdi))
287 #define SC_get_IPDi(a) (&(a->ipdi))
288 #define SC_get_GDTI(a) (&(a->gdata_info))
290 #define SC_get_errornumber(a) (a->__error_number)
291 #define SC_set_errornumber(a, n) (a->__error_number = n)
292 #define SC_get_errormsg(a) (a->__error_message)
293 #define SC_get_errormsg(a) (a->__error_message)
294 #define SC_is_prepare_statement(a) (0 != (a->prepare & PREPARE_STATEMENT))
295 #define SC_get_prepare_method(a) (a->prepare & (~PREPARE_STATEMENT))
297 #define SC_parsed_status(a) (a->parse_status & STMT_PARSE_MASK)
298 #define SC_set_parse_status(a, s) (a->parse_status |= s)
299 #define SC_update_not_ready(a) (SC_parsed_status(a) == STMT_PARSE_NONE || 0 == (a->parse_status & STMT_PARSED_OIDS))
300 #define SC_update_ready(a) (SC_parsed_status(a) == STMT_PARSE_COMPLETE && 0 != (a->parse_status & STMT_FOUND_KEY) && a->updatable)
301 #define SC_set_checked_hasoids(a, b) (a->parse_status |= (STMT_PARSED_OIDS | (b ? STMT_FOUND_KEY : 0)))
302 #define SC_checked_hasoids(a) (0 != (a->parse_status & STMT_PARSED_OIDS))
303 #define SC_set_delegate(p, c) (p->execute_delegate = c, c->execute_parent = p)
305 #define SC_clear_parse_method(s) ((s)->parse_method = 0)
306 #define SC_is_parse_forced(s) (0 != ((s)->parse_method & 1L))
307 #define SC_set_parse_forced(s) ((s)->parse_method |= 1L)
308 #define SC_is_parse_tricky(s) (0 != ((s)->parse_method & 2L))
309 #define SC_set_parse_tricky(s) ((s)->parse_method |= 2L)
310 #define SC_no_parse_tricky(s) ((s)->parse_method &= ~2L)
312 #define SC_cursor_is_valid(s) (NAME_IS_VALID(s->cursor_name))
313 #define SC_cursor_name(s) (SAFE_NAME(s->cursor_name))
315 void SC_reset_delegate(RETCODE
, StatementClass
*);
316 StatementClass
*SC_get_ancestor(StatementClass
*);
318 #define SC_is_lower_case(a, b) (a->options.metadata_id || b->connInfo.lower_case_identifier)
320 #define SC_MALLOC_return_with_error(t, tp, s, a, m, r) \
322 if (t = (tp *) malloc(s), NULL == t) \
324 SC_set_error(a, STMT_NO_MEMORY_ERROR, m, "SC_MALLOC"); \
328 #define SC_REALLOC_return_with_error(t, tp, s, a, m, r) \
330 if (t = (tp *) realloc(t, s), NULL == t) \
332 SC_set_error(a, STMT_NO_MEMORY_ERROR, m, "SC_REALLOC"); \
337 /* options for SC_free_params() */
338 #define STMT_FREE_PARAMS_ALL 0
339 #define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY 1
343 NON_PREPARE_STATEMENT
= 0
344 , PREPARE_STATEMENT
= 1
345 , PREPARE_BY_THE_DRIVER
= (1L << 1)
346 , USING_PREPARE_COMMAND
= (2L << 1)
347 , NAMED_PARSE_REQUEST
= (3L << 1)
348 , PARSE_TO_EXEC_ONCE
= (4L << 1)
349 , PARSE_REQ_FOR_INFO
= (5L << 1)
356 ,PREPARED_PERMANENTLY
357 ,PREPARED_TEMPORARILY
362 #define SC_set_pre_executable(a) (a->miscinfo |= 1L)
363 #define SC_no_pre_executable(a) (a->miscinfo &= ~1L)
364 #define SC_is_pre_executable(a) ((a->miscinfo & 1L) != 0)
365 #define SC_set_concat_prepare_exec(a) (a->miscinfo |= (1L << 2))
366 #define SC_no_concat_prepare_exec(a) (a->miscinfo &= ~(1L << 2))
367 #define SC_is_concat_prepare_exec(a) ((a->miscinfo & (1L << 2)) != 0)
368 #define SC_set_with_hold(a) (a->miscinfo |= (1L << 3))
369 #define SC_set_without_hold(a) (a->miscinfo &= ~(1L << 3))
370 #define SC_is_with_hold(a) ((a->miscinfo & (1L << 3)) != 0)
371 #define SC_miscinfo_clear(a) (a->miscinfo &= (1L << 3))
372 #define STMT_HAS_OUTER_JOIN 1L
373 #define STMT_HAS_INNER_JOIN (1L << 1)
374 #define SC_has_join(a) (0 != (a)->join_info)
375 #define SC_has_outer_join(a) (0 != (STMT_HAS_OUTER_JOIN & (a)->join_info))
376 #define SC_has_inner_join(a) (0 != (STMT_HAS_INNER_JOIN & (a)->join_info))
377 #define SC_set_outer_join(a) ((a)->join_info |= STMT_HAS_OUTER_JOIN)
378 #define SC_set_inner_join(a) ((a)->join_info |= STMT_HAS_INNER_JOIN)
380 #define SC_unref_CC_error(a) ((a->ref_CC_error) = FALSE)
381 #define SC_ref_CC_error(a) ((a->ref_CC_error) = TRUE)
382 #define SC_forget_unnamed(a) (PREPARED_TEMPORARILY == (a)->prepared ? SC_set_prepared(a, ONCE_DESCRIBED) : (void) 0)
385 /* For Multi-thread */
386 #if defined(WIN_MULTITHREAD_SUPPORT)
387 #define INIT_STMT_CS(x) InitializeCriticalSection(&((x)->cs))
388 #define ENTER_STMT_CS(x) EnterCriticalSection(&((x)->cs))
389 #define TRY_ENTER_STMT_CS(x) TryEnterCriticalSection(&((x)->cs))
390 #define LEAVE_STMT_CS(x) LeaveCriticalSection(&((x)->cs))
391 #define DELETE_STMT_CS(x) DeleteCriticalSection(&((x)->cs))
392 #elif defined(POSIX_THREADMUTEX_SUPPORT)
393 #define INIT_STMT_CS(x) pthread_mutex_init(&((x)->cs),0)
394 #define ENTER_STMT_CS(x) pthread_mutex_lock(&((x)->cs))
395 #define TRY_ENTER_STMT_CS(x) (0 == pthread_mutex_trylock(&((x)->cs)))
396 #define LEAVE_STMT_CS(x) pthread_mutex_unlock(&((x)->cs))
397 #define DELETE_STMT_CS(x) pthread_mutex_destroy(&((x)->cs))
399 #define INIT_STMT_CS(x)
400 #define ENTER_STMT_CS(x)
401 #define TRY_ENTER_STMT_CS(x) (1)
402 #define LEAVE_STMT_CS(x)
403 #define DELETE_STMT_CS(x)
404 #endif /* WIN_MULTITHREAD_SUPPORT */
405 /* Statement prototypes */
406 StatementClass
*SC_Constructor(ConnectionClass
*);
407 void InitializeStatementOptions(StatementOptions
*opt
);
408 char SC_Destructor(StatementClass
*self
);
409 BOOL
SC_opencheck(StatementClass
*self
, const char *func
);
410 RETCODE
SC_initialize_and_recycle(StatementClass
*self
);
411 void SC_initialize_cols_info(StatementClass
*self
, BOOL DCdestroy
, BOOL parseReset
);
412 int statement_type(const char *statement
);
413 char parse_statement(StatementClass
*stmt
, BOOL
);
414 Int4
SC_pre_execute(StatementClass
*self
);
415 char SC_unbind_cols(StatementClass
*self
);
416 char SC_recycle_statement(StatementClass
*self
);
418 void SC_clear_error(StatementClass
*self
);
419 void SC_set_error(StatementClass
*self
, int errnum
, const char *msg
, const char *func
);
420 void SC_set_errormsg(StatementClass
*self
, const char *msg
);
421 void SC_error_copy(StatementClass
*self
, const StatementClass
*from
, BOOL
);
422 void SC_full_error_copy(StatementClass
*self
, const StatementClass
*from
, BOOL
);
423 void SC_replace_error_with_res(StatementClass
*self
, int errnum
, const char *msg
, const QResultClass
*, BOOL
);
424 void SC_set_prepared(StatementClass
*self
, BOOL
);
425 void SC_set_planname(StatementClass
*self
, const char *plan_name
);
426 void SC_set_rowset_start(StatementClass
*self
, SQLLEN
, BOOL
);
427 void SC_inc_rowset_start(StatementClass
*self
, SQLLEN
);
428 RETCODE
SC_initialize_stmts(StatementClass
*self
, BOOL
);
429 RETCODE
SC_fetch(StatementClass
*self
);
430 void SC_log_error(const char *func
, const char *desc
, const StatementClass
*self
);
431 time_t SC_get_time(StatementClass
*self
);
432 SQLULEN
SC_get_bookmark(StatementClass
*self
);
433 RETCODE
SC_pos_reload(StatementClass
*self
, SQLULEN index
, UInt2
*, Int4
);
434 RETCODE
SC_pos_update(StatementClass
*self
, SQLSETPOSIROW irow
, SQLULEN index
);
435 RETCODE
SC_pos_delete(StatementClass
*self
, SQLSETPOSIROW irow
, SQLULEN index
);
436 RETCODE
SC_pos_refresh(StatementClass
*self
, SQLSETPOSIROW irow
, SQLULEN index
);
437 RETCODE
SC_pos_add(StatementClass
*self
, SQLSETPOSIROW irow
);
438 int SC_set_current_col(StatementClass
*self
, int col
);
439 void SC_setInsertedTable(StatementClass
*, RETCODE
);
440 void SC_scanQueryAndCountParams(const char *, const ConnectionClass
*,
441 Int4
*next_cmd
, SQLSMALLINT
*num_params
,
442 char *multi
, char *proc_return
);
444 BOOL
SC_IsExecuting(const StatementClass
*self
);
445 BOOL
SC_SetExecuting(StatementClass
*self
, BOOL on
);
446 BOOL
SC_SetCancelRequest(StatementClass
*self
);
447 BOOL
SC_AcceptedCancelRequest(const StatementClass
*self
);
449 DescriptorClass
*SC_set_ARD(StatementClass
*stmt
, DescriptorClass
*desc
);
450 DescriptorClass
*SC_set_APD(StatementClass
*stmt
, DescriptorClass
*desc
);
451 int enqueueNeedDataCallback(StatementClass
*self
, NeedDataCallfunc
, void *);
452 RETCODE
dequeueNeedDataCallback(RETCODE
, StatementClass
*self
);
453 void cancelNeedDataState(StatementClass
*self
);
454 int StartRollbackState(StatementClass
*self
);
455 RETCODE
DiscardStatementSvp(StatementClass
*self
, RETCODE
, BOOL errorOnly
);
458 * Macros to convert global index <-> relative index in resultset/rowset
460 /* a global index to the relative index in a rowset */
461 #define SC_get_rowset_start(stmt) (stmt->rowset_start)
462 #define GIdx2RowIdx(gidx, stmt) (gidx - stmt->rowset_start)
463 /* a global index to the relative index in a resultset(not a rowset) */
464 #define GIdx2CacheIdx(gidx, s, r) (gidx - (QR_has_valid_base(r) ? (s->rowset_start - r->base) : 0))
465 #define GIdx2KResIdx(gidx, s, r) (gidx - (QR_has_valid_base(r) ? (s->rowset_start - r->key_base) : 0))
466 /* a relative index in a rowset to the global index */
467 #define RowIdx2GIdx(ridx, stmt) (ridx + stmt->rowset_start)
468 /* a relative index in a resultset to the global index */
469 #define CacheIdx2GIdx(ridx, stmt, res) (ridx - res->base + stmt->rowset_start)
470 #define KResIdx2GIdx(ridx, stmt, res) (ridx - res->key_base + stmt->rowset_start)
472 #define BOOKMARK_SHIFT 1
473 #define SC_make_bookmark(b) ((b < 0) ? (b) : (b + BOOKMARK_SHIFT))
474 #define SC_resolve_bookmark(b) ((b < 0) ? (b) : (b - BOOKMARK_SHIFT))
475 #endif /* __STATEMENT_H__ */