'make test' on Windows doesn't need you to say "mono --debug".
[versaplex.git] / vxodbc / statement.h
blob76769bd2a5fea7b3ae677f2feee6d167c5b26760
1 /* File: statement.h
3 * Description: See "statement.c"
5 * Comments: See "notice.txt" for copyright and license information.
7 */
9 #ifndef __STATEMENT_H__
10 #define __STATEMENT_H__
12 #include "psqlodbc.h"
13 #include <time.h>
15 #include "pgtypes.h"
16 #include "bind.h"
17 #include "descriptor.h"
19 #if defined (POSIX_MULTITHREAD_SUPPORT)
20 #include <pthread.h>
21 #endif
23 typedef enum
25 STMT_ALLOCATED, /* The statement handle is allocated, but
26 * not used so far */
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 */
38 } STMT_Status;
40 * ERROR status code
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.
47 */
48 enum {
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,
58 * just a notification
59 * to be returned by
60 * SQLError
62 ,STMT_OK = 0
63 ,STMT_EXEC_ERROR
64 ,STMT_STATUS_ERROR
65 ,STMT_SEQUENCE_ERROR
66 ,STMT_NO_MEMORY_ERROR
67 ,STMT_COLNUM_ERROR
68 ,STMT_NO_STMTSTRING
69 ,STMT_ERROR_TAKEN_FROM_BACKEND
70 ,STMT_INTERNAL_ERROR
71 ,STMT_STILL_EXECUTING
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
79 ,STMT_NO_CURSOR_NAME
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
88 ,STMT_BAD_ERROR
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
98 /* statement types */
99 enum
101 STMT_TYPE_UNKNOWN = -2
102 ,STMT_TYPE_OTHER = -1
103 ,STMT_TYPE_SELECT = 0
104 ,STMT_TYPE_INSERT
105 ,STMT_TYPE_UPDATE
106 ,STMT_TYPE_DELETE
107 ,STMT_TYPE_CREATE
108 ,STMT_TYPE_ALTER
109 ,STMT_TYPE_DROP
110 ,STMT_TYPE_GRANT
111 ,STMT_TYPE_REVOKE
112 ,STMT_TYPE_PROCCALL
113 ,STMT_TYPE_LOCK
114 ,STMT_TYPE_TRANSACTION
115 ,STMT_TYPE_CLOSE
116 ,STMT_TYPE_FETCH
117 ,STMT_TYPE_PREPARE
118 ,STMT_TYPE_EXECUTE
119 ,STMT_TYPE_DEALLOCATE
120 ,STMT_TYPE_ANALYZE
121 ,STMT_TYPE_NOTIFY
122 ,STMT_TYPE_EXPLAIN
123 ,STMT_TYPE_SET
124 ,STMT_TYPE_RESET
125 ,STMT_TYPE_DECLARE
126 ,STMT_TYPE_MOVE
127 ,STMT_TYPE_COPY
128 ,STMT_TYPE_START
129 ,STMT_TYPE_SPECIAL
132 #define STMT_UPDATE(stmt) (stmt->statement_type > STMT_TYPE_SELECT)
135 /* Parsing status */
136 enum
138 STMT_PARSE_NONE = 0
139 ,STMT_PARSE_COMPLETE /* the driver parsed the statement */
140 ,STMT_PARSE_INCOMPLETE
141 ,STMT_PARSE_FATAL
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)
149 /* Result style */
150 enum
152 STMT_FETCH_NONE = 0,
153 STMT_FETCH_NORMAL,
154 STMT_FETCH_EXTENDED
157 #define PG_NUM_NORMAL_KEYS 2
159 typedef RETCODE (*NeedDataCallfunc)(RETCODE, void *);
160 typedef struct
162 NeedDataCallfunc func;
163 void *data;
164 } NeedDataCallback;
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 */
173 HSTMT FAR *phstmt;
174 StatementOptions options;
175 StatementOptions options_orig;
176 /* attached descriptor handles */
177 ARDClass *ard;
178 APDClass *apd;
179 IRDClass *ird;
180 IPDClass *ipd;
181 /* implicit descriptor handles */
182 ARDClass ardi;
183 IRDClass irdi;
184 APDClass apdi;
185 IPDClass ipdi;
187 STMT_Status status;
188 char *__error_message;
189 int __error_number;
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
198 * number) */
199 SQLSETPOSIROW bind_row; /* current offset for Multiple row/column
200 * binding */
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 */
209 TABLE_INFO **ti;
210 Int2 ntab;
211 Int2 num_key_fields;
212 Int2 statement_type; /* According to the defines above */
213 Int2 num_params;
214 Int2 data_at_exec; /* Number of params needing SQLPutData */
215 Int2 current_exec_param; /* The current parameter for
216 * SQLPutData */
217 char parse_status;
218 char proc_return;
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
225 * internally ? */
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 ? */
234 pgNAME cursor_name;
235 char *plan_name;
237 char *stmt_with_params; /* statement after parameter
238 * substitution */
239 Int4 stmt_size_limit; /* PG restriction */
240 SQLLEN exec_start_row;
241 SQLLEN exec_end_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;
248 char updatable;
249 SQLLEN diag_row_count;
250 char *load_statement; /* to (re)load updatable individual rows */
251 char *execute_statement; /* to execute the prepared plans */
252 Int4 from_pos;
253 Int4 where_pos;
254 SQLLEN last_fetch_count_include_ommitted;
255 time_t stmt_time;
256 /* SQL_NEED_DATA Callback list */
257 StatementClass *execute_delegate;
258 StatementClass *execute_parent;
259 UInt2 allocated_callbacks;
260 UInt2 num_callbacks;
261 NeedDataCallback *callbacks;
262 #if defined(WIN_MULTITHREAD_SUPPORT)
263 CRITICAL_SECTION cs;
264 #elif defined(POSIX_THREADMUTEX_SUPPORT)
265 pthread_mutex_t cs;
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) \
321 do { \
322 if (t = (tp *) malloc(s), NULL == t) \
324 SC_set_error(a, STMT_NO_MEMORY_ERROR, m, "SC_MALLOC"); \
325 return r; \
327 } while (0)
328 #define SC_REALLOC_return_with_error(t, tp, s, a, m, r) \
329 do { \
330 if (t = (tp *) realloc(t, s), NULL == t) \
332 SC_set_error(a, STMT_NO_MEMORY_ERROR, m, "SC_REALLOC"); \
333 return r; \
335 } while (0)
337 /* options for SC_free_params() */
338 #define STMT_FREE_PARAMS_ALL 0
339 #define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY 1
341 /* prepare state */
342 enum {
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)
352 /* prepared state */
353 enum
355 NOT_YET_PREPARED = 0
356 ,PREPARED_PERMANENTLY
357 ,PREPARED_TEMPORARILY
358 ,ONCE_DESCRIBED
361 /* misc info */
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))
398 #else
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__ */