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