1 /*-------
2  * Module:			execute.c
3  *
4  * Description:		This module contains routines related to
5  *					preparing and executing an SQL statement.
6  *
7  * Classes:			n/a
8  *
9  * API functions:	SQLPrepare, SQLExecute, SQLExecDirect, SQLTransact,
10  *					SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
11  *
12  * Comments:		See "readme.txt" for copyright and license information.
13  *-------
14  */
15 
16 #include "psqlodbc.h"
17 #include "misc.h"
18 
19 #include <stdio.h>
20 #include <string.h>
21 
22 #ifndef	WIN32
23 #include <ctype.h>
24 #endif /* WIN32 */
25 
26 #include "environ.h"
27 #include "connection.h"
28 #include "statement.h"
29 #include "qresult.h"
30 #include "convert.h"
31 #include "bind.h"
32 #include "pgtypes.h"
33 #include "lobj.h"
34 #include "pgapifunc.h"
35 
36 /*		Perform a Prepare on the SQL statement */
37 RETCODE		SQL_API
PGAPI_Prepare(HSTMT hstmt,const SQLCHAR * szSqlStr,SQLINTEGER cbSqlStr)38 PGAPI_Prepare(HSTMT hstmt,
39 			  const SQLCHAR * szSqlStr,
40 			  SQLINTEGER cbSqlStr)
41 {
42 	CSTR func = "PGAPI_Prepare";
43 	StatementClass *self = (StatementClass *) hstmt;
44 	RETCODE	retval = SQL_SUCCESS;
45 	BOOL	prepared;
46 
47 	MYLOG(0, "entering...\n");
48 
49 #define	return	DONT_CALL_RETURN_FROM_HERE???
50 	/* StartRollbackState(self); */
51 
52 	/*
53 	 * According to the ODBC specs it is valid to call SQLPrepare multiple
54 	 * times. In that case, the bound SQL statement is replaced by the new
55 	 * one
56 	 */
57 
58 	prepared = self->prepared;
59 	SC_set_prepared(self, NOT_YET_PREPARED);
60 	switch (self->status)
61 	{
62 		case STMT_DESCRIBED:
63 			MYLOG(0, "**** STMT_DESCRIBED, recycle\n");
64 			SC_recycle_statement(self); /* recycle the statement, but do
65 										 * not remove parameter bindings */
66 			break;
67 
68 		case STMT_FINISHED:
69 			MYLOG(0, "**** STMT_FINISHED, recycle\n");
70 			SC_recycle_statement(self); /* recycle the statement, but do
71 										 * not remove parameter bindings */
72 			break;
73 
74 		case STMT_ALLOCATED:
75 			MYLOG(0, "**** STMT_ALLOCATED, copy\n");
76 			self->status = STMT_READY;
77 			break;
78 
79 		case STMT_READY:
80 			MYLOG(0, "**** STMT_READY, change SQL\n");
81 			if (NOT_YET_PREPARED != prepared)
82 				SC_recycle_statement(self); /* recycle the statement */
83 			break;
84 
85 		case STMT_EXECUTING:
86 			MYLOG(0, "**** STMT_EXECUTING, error!\n");
87 
88 			SC_set_error(self, STMT_SEQUENCE_ERROR, "PGAPI_Prepare(): The handle does not point to a statement that is ready to be executed", func);
89 
90 			retval = SQL_ERROR;
91 			goto cleanup;
92 
93 		default:
94 			SC_set_error(self, STMT_INTERNAL_ERROR, "An Internal Error has occured -- Unknown statement status.", func);
95 			retval = SQL_ERROR;
96 			goto cleanup;
97 	}
98 
99 	SC_initialize_stmts(self, TRUE);
100 
101 	if (!szSqlStr)
102 	{
103 		SC_set_error(self, STMT_NO_MEMORY_ERROR, "the query is NULL", func);
104 		retval = SQL_ERROR;
105 		goto cleanup;
106 	}
107 	if (!szSqlStr[0])
108 		self->statement = strdup("");
109 	else
110 		self->statement = make_string(szSqlStr, cbSqlStr, NULL, 0);
111 	if (!self->statement)
112 	{
113 		SC_set_error(self, STMT_NO_MEMORY_ERROR, "No memory available to store statement", func);
114 		retval = SQL_ERROR;
115 		goto cleanup;
116 	}
117 
118 	self->prepare = PREPARE_STATEMENT;
119 	self->statement_type = statement_type(self->statement);
120 
121 	/* Check if connection is onlyread (only selects are allowed) */
122 	if (CC_is_onlyread(SC_get_conn(self)) && STMT_UPDATE(self))
123 	{
124 		SC_set_error(self, STMT_EXEC_ERROR, "Connection is readonly, only select statements are allowed.", func);
125 		retval = SQL_ERROR;
126 		goto cleanup;
127 	}
128 
129 cleanup:
130 #undef	return
131 MYLOG(DETAIL_LOG_LEVEL, "leaving %d\n", retval);
132 	return retval;
133 }
134 
135 
136 /*		Performs the equivalent of SQLPrepare, followed by SQLExecute. */
137 RETCODE		SQL_API
PGAPI_ExecDirect(HSTMT hstmt,const SQLCHAR * szSqlStr,SQLINTEGER cbSqlStr,UWORD flag)138 PGAPI_ExecDirect(HSTMT hstmt,
139 				 const SQLCHAR * szSqlStr,
140 				 SQLINTEGER cbSqlStr,
141 				 UWORD flag)
142 {
143 	StatementClass *stmt = (StatementClass *) hstmt;
144 	RETCODE		result;
145 	CSTR func = "PGAPI_ExecDirect";
146 	const ConnectionClass	*conn = SC_get_conn(stmt);
147 
148 	MYLOG(0, "entering...%x\n", flag);
149 
150 	if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
151 		return result;
152 
153 	/*
154 	 * keep a copy of the un-parametrized statement, in case they try to
155 	 * execute this statement again
156 	 */
157 	stmt->statement = make_string(szSqlStr, cbSqlStr, NULL, 0);
158 MYLOG(DETAIL_LOG_LEVEL, "a2\n");
159 	if (!stmt->statement)
160 	{
161 		SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "No memory available to store statement", func);
162 		return SQL_ERROR;
163 	}
164 
165 	MYLOG(0, "**** hstmt=%p, statement='%s'\n", hstmt, stmt->statement);
166 
167 	if (0 != (flag & PODBC_WITH_HOLD))
168 		SC_set_with_hold(stmt);
169 	if (0 != (flag & PODBC_RDONLY))
170 		SC_set_readonly(stmt);
171 
172 	/*
173 	 * If an SQLPrepare was performed prior to this, but was left in the
174 	 * described state because an error occurred prior to SQLExecute then
175 	 * set the statement to finished so it can be recycled.
176 	 */
177 	if (stmt->status == STMT_DESCRIBED)
178 		stmt->status = STMT_FINISHED;
179 
180 	stmt->statement_type = statement_type(stmt->statement);
181 
182 	/* Check if connection is onlyread (only selects are allowed) */
183 	if (CC_is_onlyread(conn) && STMT_UPDATE(stmt))
184 	{
185 		SC_set_error(stmt, STMT_EXEC_ERROR, "Connection is readonly, only select statements are allowed.", func);
186 		return SQL_ERROR;
187 	}
188 
189 	MYLOG(0, "calling PGAPI_Execute...\n");
190 
191 	result = PGAPI_Execute(hstmt, flag);
192 
193 	MYLOG(0, "leaving %hd\n", result);
194 	return result;
195 }
196 
197 static int
inquireHowToPrepare(const StatementClass * stmt)198 inquireHowToPrepare(const StatementClass *stmt)
199 {
200 	ConnectionClass	*conn;
201 	ConnInfo	*ci;
202 	int		ret = 0;
203 
204 	conn = SC_get_conn(stmt);
205 	ci = &(conn->connInfo);
206 	if (!stmt->use_server_side_prepare)
207 	{
208 		/* Do prepare operations by the driver itself */
209 		return PREPARE_BY_THE_DRIVER;
210 	}
211 	if (NOT_YET_PREPARED == stmt->prepared)
212 	{
213 		SQLSMALLINT	num_params;
214 
215 		if (STMT_TYPE_DECLARE == stmt->statement_type &&
216 		    PG_VERSION_LT(conn, 8.0))
217 		{
218 			return PREPARE_BY_THE_DRIVER;
219 		}
220 		if (stmt->multi_statement < 0)
221 			PGAPI_NumParams((StatementClass *) stmt, &num_params);
222 		if (stmt->multi_statement > 0)
223 		{
224 			/*
225 			 * divide the query into multiple commands and apply V3 parse
226 			 * requests for each of them
227 			 */
228 			ret = PARSE_REQ_FOR_INFO;
229 		}
230 		else
231 		{
232 			if (SC_may_use_cursor(stmt))
233 			{
234 				if (ci->drivers.use_declarefetch)
235 					return PARSE_REQ_FOR_INFO;
236 				else if (SQL_CURSOR_FORWARD_ONLY != stmt->options.cursor_type)
237 					ret = PARSE_REQ_FOR_INFO;
238 				else
239 					ret = PARSE_TO_EXEC_ONCE;
240 			}
241 			else
242 				ret = PARSE_TO_EXEC_ONCE;
243 		}
244 	}
245 	if (SC_is_prepare_statement(stmt) && (PARSE_TO_EXEC_ONCE == ret))
246 		ret = NAMED_PARSE_REQUEST;
247 
248 	return ret;
249 }
250 
251 int
decideHowToPrepare(StatementClass * stmt,BOOL force)252 decideHowToPrepare(StatementClass *stmt, BOOL force)
253 {
254 	int	method = SC_get_prepare_method(stmt);
255 
256 	if (0 != method) /* a method was already determined */
257 		return method;
258 	switch (stmt->prepare)
259 	{
260 		case NON_PREPARE_STATEMENT: /* not a prepare statement */
261 			if (!force)
262 				return method;
263 			break;
264 	}
265 	method = inquireHowToPrepare(stmt);
266 	stmt->prepare |= method;
267 	if (PREPARE_BY_THE_DRIVER == method)
268 		stmt->discard_output_params = 1;
269 	return method;
270 }
271 
272 /* dont/should/can send Parse request ? */
273 enum {
274 	 doNothing = 0
275 	,allowParse
276 	,preferParse
277 	,shouldParse
278 	,usingCommand
279 };
280 
281 #define	ONESHOT_CALL_PARSE		allowParse
282 #define	NOPARAM_ONESHOT_CALL_PARSE	doNothing
283 
284 static
HowToPrepareBeforeExec(StatementClass * stmt,BOOL checkOnly)285 int HowToPrepareBeforeExec(StatementClass *stmt, BOOL checkOnly)
286 {
287 	SQLSMALLINT	num_params = stmt->num_params;
288 	ConnectionClass	*conn = SC_get_conn(stmt);
289 	ConnInfo *ci = &(conn->connInfo);
290 	int		nCallParse = doNothing, how_to_prepare = 0;
291 	BOOL		bNeedsTrans = FALSE;
292 
293 	if (num_params < 0)
294 		PGAPI_NumParams(stmt, &num_params);
295 	how_to_prepare = decideHowToPrepare(stmt, checkOnly);
296 	if (checkOnly)
297 	{
298 		if (num_params <= 0)
299 			return doNothing;
300 	}
301 	else
302 	{
303 		switch (how_to_prepare)
304 		{
305 			case NAMED_PARSE_REQUEST:
306 				return shouldParse;
307 			case PARSE_TO_EXEC_ONCE:
308 				switch (stmt->prepared)
309 				{
310 					case PREPARED_TEMPORARILY:
311 						nCallParse = preferParse;
312 						break;
313 					default:
314 						if (num_params <= 0)
315 							nCallParse = NOPARAM_ONESHOT_CALL_PARSE;
316 						else
317 							nCallParse = ONESHOT_CALL_PARSE;
318 				}
319 				break;
320 			default:
321 				return doNothing;
322 		}
323 	}
324 
325 	if (num_params > 0)
326 	{
327 		int	param_number = -1;
328 		ParameterInfoClass *apara;
329 		ParameterImplClass *ipara;
330 		OID	pgtype;
331 
332 		while (TRUE)
333 		{
334 			SC_param_next(stmt, &param_number, &apara, &ipara);
335 			if (!ipara || !apara)
336 				break;
337 			pgtype = PIC_get_pgtype(*ipara);
338 			if (checkOnly)
339 			{
340 				switch (ipara->SQLType)
341 				{
342 					case SQL_LONGVARBINARY:
343 						if (0 == pgtype)
344 						{
345 							if (ci->bytea_as_longvarbinary &&
346 							    0 != conn->lobj_type)
347 								nCallParse = shouldParse;
348 						}
349 						break;
350 					case SQL_CHAR:
351 						if (ci->cvt_null_date_string)
352 							nCallParse = shouldParse;
353 						break;
354 					case SQL_VARCHAR:
355 						if (ci->drivers.bools_as_char &&
356 						    PG_WIDTH_OF_BOOLS_AS_CHAR == ipara->column_size)
357 							nCallParse = shouldParse;
358 						break;
359 				}
360 			}
361 			else
362 			{
363 				BOOL	bBytea = FALSE;
364 
365 				switch (ipara->SQLType)
366 				{
367 					case SQL_LONGVARBINARY:
368 						if (conn->lobj_type == pgtype || PG_TYPE_OID == pgtype)
369 							bNeedsTrans = TRUE;
370 						else if (PG_TYPE_BYTEA == pgtype)
371 							bBytea = TRUE;
372 						else if (0 == pgtype)
373 						{
374 							if (ci->bytea_as_longvarbinary)
375 								bBytea = TRUE;
376 							else
377 								bNeedsTrans = TRUE;
378 						}
379 						if (bBytea)
380 							if (nCallParse < preferParse)
381 								nCallParse = preferParse;
382 						break;
383 				}
384 			}
385 		}
386 	}
387 	if (bNeedsTrans &&
388 	    PARSE_TO_EXEC_ONCE == how_to_prepare)
389 	{
390 		if (!CC_is_in_trans(conn) && CC_does_autocommit(conn))
391 			nCallParse = doNothing;
392 	}
393 	return nCallParse;
394 }
395 
396 static
GetSvpName(const ConnectionClass * conn,char * wrk,int wrksize)397 const char *GetSvpName(const ConnectionClass *conn, char *wrk, int wrksize)
398 {
399 	snprintf(wrk, wrksize, "_EXEC_SVP_%p", conn);
400 	return wrk;
401 }
402 
403 /*
404  *	The execution after all parameters were resolved.
405  */
406 
407 #define INVALID_EXPBUFFER	PQExpBufferDataBroken(stmt->stmt_deffered)
408 #define VALID_EXPBUFFER	(!PQExpBufferDataBroken(stmt->stmt_deffered))
409 
410 static
param_status_batch_update(IPDFields * ipdopts,RETCODE retval,SQLLEN target_row,int count_of_deffered)411 void param_status_batch_update(IPDFields *ipdopts, RETCODE retval, SQLLEN target_row, int count_of_deffered)
412 {
413 	int i, j;
414 	if (NULL != ipdopts->param_status_ptr)
415 	{
416 		for (i = target_row, j = 0; i >= 0 && j <= count_of_deffered; i--)
417 		{
418 			if (SQL_PARAM_UNUSED != ipdopts->param_status_ptr[i])
419 			{
420 				ipdopts->param_status_ptr[i] = retval;
421 				j++;
422 			}
423 		}
424 	}
425 }
426 
427 static
Exec_with_parameters_resolved(StatementClass * stmt,EXEC_TYPE exec_type,BOOL * exec_end)428 RETCODE	Exec_with_parameters_resolved(StatementClass *stmt, EXEC_TYPE exec_type, BOOL *exec_end)
429 {
430 	CSTR func = "Exec_with_parameters_resolved";
431 	RETCODE		retval;
432 	SQLLEN		start_row, end_row;
433 	SQLINTEGER	cursor_type, scroll_concurrency;
434 	ConnectionClass	*conn;
435 	QResultClass	*res;
436 	APDFields	*apdopts;
437 	IPDFields	*ipdopts;
438 	BOOL		prepare_before_exec = FALSE;
439 	char *stmt_with_params;
440 	SQLLEN		status_row = stmt->exec_current_row;
441 	int		count_of_deffered;
442 
443 	*exec_end = FALSE;
444 	conn = SC_get_conn(stmt);
445 	MYLOG(0, "copying statement params: trans_status=%d, len=" FORMAT_SIZE_T ", stmt='%s'\n", conn->transact_status, strlen(stmt->statement), stmt->statement);
446 
447 #define	return	DONT_CALL_RETURN_FROM_HERE???
448 #define	RETURN(code)	{ retval = code; goto cleanup; }
449 	ENTER_CONN_CS(conn);
450 	/* save the cursor's info before the execution */
451 	cursor_type = stmt->options.cursor_type;
452 	scroll_concurrency = stmt->options.scroll_concurrency;
453 	/* Prepare the statement if possible at backend side */
454 	if (HowToPrepareBeforeExec(stmt, FALSE) >= allowParse)
455 		prepare_before_exec = TRUE;
456 
457 MYLOG(DETAIL_LOG_LEVEL, "prepare_before_exec=%d srv=%d\n", prepare_before_exec, stmt->use_server_side_prepare);
458 	/* Create the statement with parameters substituted. */
459 	stmt_with_params = stmt->stmt_with_params;
460 	if (LAST_EXEC == exec_type)
461 	{
462 		if (NULL != stmt_with_params)
463 		{
464 			free(stmt_with_params);
465 			stmt_with_params = stmt->stmt_with_params = NULL;
466 		}
467 		if (INVALID_EXPBUFFER ||
468 		    !stmt->stmt_deffered.data[0])
469 			RETURN(SQL_SUCCESS);
470 	}
471 	else
472 	{
473 		retval = copy_statement_with_parameters(stmt, prepare_before_exec);
474 		stmt->current_exec_param = -1;
475 		if (retval != SQL_SUCCESS)
476 		{
477 			stmt->exec_current_row = -1;
478 			*exec_end = TRUE;
479 			RETURN(retval) /* error msg is passed from the above */
480 		}
481 		stmt_with_params = stmt->stmt_with_params;
482 		if (!stmt_with_params) // Extended Protocol
483 			exec_type = DIRECT_EXEC;
484 	}
485 
486 	MYLOG(0, "   stmt_with_params = '%s'\n", stmt->stmt_with_params);
487 
488 	/*
489 	 *	The real execution.
490 	 */
491 MYLOG(0, "about to begin SC_execute exec_type=%d\n", exec_type);
492 	ipdopts = SC_get_IPDF(stmt);
493 	apdopts = SC_get_APDF(stmt);
494 	if (start_row = stmt->exec_start_row, start_row < 0)
495 		start_row = 0;
496 	if (end_row = stmt->exec_end_row, end_row < 0)
497 	{
498 		end_row = (SQLINTEGER) apdopts->paramset_size - 1;
499 		if (end_row < 0)
500 			end_row = 0;
501 	}
502 	if (LAST_EXEC == exec_type &&
503 	    NULL != ipdopts->param_status_ptr)
504 	{
505 		int i;
506 		for (i = end_row; i >= start_row; i--)
507 		{
508 			if (SQL_PARAM_UNUSED != ipdopts->param_status_ptr[i])
509 			{
510 				status_row = i;
511 				break;
512 			}
513 		}
514 	}
515 	count_of_deffered = stmt->count_of_deffered;
516 	if (DIRECT_EXEC == exec_type)
517 	{
518 		retval = SC_execute(stmt);
519 		stmt->count_of_deffered = 0;
520 	}
521 	else if (DEFFERED_EXEC == exec_type &&
522 		 stmt->exec_current_row < end_row &&
523 		 stmt->count_of_deffered + 1 < stmt->batch_size)
524 	{
525 		if (INVALID_EXPBUFFER)
526 			initPQExpBuffer(&stmt->stmt_deffered);
527 		if (INVALID_EXPBUFFER)
528 		{
529 			retval = SQL_ERROR;
530 			SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory", __FUNCTION__);
531 		}
532 		else
533 		{
534 			if (NULL != stmt_with_params)
535 			{
536 				if (stmt->stmt_deffered.data[0])
537 					appendPQExpBuffer(&stmt->stmt_deffered, ";%s", stmt_with_params);
538 				else
539 					printfPQExpBuffer(&stmt->stmt_deffered, "%s", stmt_with_params);
540 			}
541 			if (NULL != ipdopts->param_status_ptr)
542 				ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS; // set without exec
543 			stmt->count_of_deffered++;
544 			stmt->exec_current_row++;
545 			RETURN(SQL_SUCCESS);
546 		}
547 	}
548 	else
549 	{
550 		if (VALID_EXPBUFFER)
551 		{
552 			if (NULL != stmt_with_params)
553 				appendPQExpBuffer(&stmt->stmt_deffered, ";%s", stmt_with_params);
554 			stmt->stmt_with_params = stmt->stmt_deffered.data;
555 		}
556 		retval = SC_execute(stmt);
557 		stmt->stmt_with_params = stmt_with_params;
558 		stmt->count_of_deffered = 0;
559 		if (VALID_EXPBUFFER)
560 			resetPQExpBuffer(&stmt->stmt_deffered);
561 	}
562 	if (retval == SQL_ERROR)
563 	{
564 MYLOG(0, "count_of_deffered=%d\n", count_of_deffered);
565 		param_status_batch_update(ipdopts, SQL_PARAM_ERROR, stmt->exec_current_row, count_of_deffered);
566 		stmt->exec_current_row = -1;
567 		*exec_end = TRUE;
568 		RETURN(retval)
569 	}
570 	res = SC_get_Result(stmt);
571 	/* special handling of result for keyset driven cursors */
572 	if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
573 	    SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
574 	{
575 		QResultClass	*kres;
576 
577 		if (kres = QR_nextr(res), kres)
578 		{
579 			QR_set_fields(kres, QR_get_fields(res));
580 			QR_set_fields(res,  NULL);
581 			kres->num_fields = res->num_fields;
582 			QR_detach(res);
583 			SC_set_Result(stmt, kres);
584 			res = kres;
585 		}
586 	}
587 	ipdopts = SC_get_IPDF(stmt);
588 	if (ipdopts->param_status_ptr)
589 	{
590 		switch (retval)
591 		{
592 			case SQL_SUCCESS:
593 				ipdopts->param_status_ptr[status_row] = SQL_PARAM_SUCCESS;
594 				break;
595 			case SQL_SUCCESS_WITH_INFO:
596 MYLOG(0, "count_of_deffered=%d has_notice=%d\n", count_of_deffered, stmt->has_notice);
597 				param_status_batch_update(ipdopts, (count_of_deffered > 0 && !stmt->has_notice) ? SQL_PARAM_SUCCESS : SQL_PARAM_SUCCESS_WITH_INFO, status_row, count_of_deffered);
598 				break;
599 			default:
600 				param_status_batch_update(ipdopts, SQL_PARAM_ERROR, status_row, count_of_deffered);
601 				break;
602 		}
603 	}
604 	stmt->has_notice = 0;
605 	if (stmt->exec_current_row >= end_row)
606 	{
607 		*exec_end = TRUE;
608 		stmt->exec_current_row = -1;
609 	}
610 	else
611 		stmt->exec_current_row++;
612 	if (res)
613 	{
614 		EnvironmentClass *env = (EnvironmentClass *) CC_get_env(conn);
615 		const char *cmd = QR_get_command(res);
616 
617 		if (retval == SQL_SUCCESS &&
618 		    NULL != cmd &&
619 		    start_row >= end_row &&
620 		    NULL != env &&
621 		    EN_is_odbc3(env))
622 		{
623 			int     count;
624 
625 			if (sscanf(cmd , "UPDATE %d", &count) == 1)
626 				;
627 			else if (sscanf(cmd , "DELETE %d", &count) == 1)
628 				;
629 			else
630 				count = -1;
631 			if (0 == count)
632 				retval = SQL_NO_DATA;
633 		}
634 		stmt->diag_row_count = res->recent_processed_row_count;
635 	}
636 	/*
637 	 *	The cursor's info was changed ?
638 	 */
639 	if (retval == SQL_SUCCESS &&
640 	    (stmt->options.cursor_type != cursor_type ||
641 	     stmt->options.scroll_concurrency != scroll_concurrency))
642 	{
643 		SC_set_error(stmt, STMT_OPTION_VALUE_CHANGED, "cursor updatability changed", func);
644 		retval = SQL_SUCCESS_WITH_INFO;
645 	}
646 
647 cleanup:
648 #undef	RETURN
649 #undef	return
650 	LEAVE_CONN_CS(conn);
651 	return retval;
652 }
653 
654 int
StartRollbackState(StatementClass * stmt)655 StartRollbackState(StatementClass *stmt)
656 {
657 	int			ret;
658 	ConnectionClass	*conn;
659 	ConnInfo	*ci = NULL;
660 
661 MYLOG(DETAIL_LOG_LEVEL, "entering %p->external=%d\n", stmt, stmt->external);
662 	conn = SC_get_conn(stmt);
663 	if (conn)
664 		ci = &conn->connInfo;
665 
666 	if (!ci || ci->rollback_on_error < 0) /* default */
667 	{
668 		if (conn && PG_VERSION_GE(conn, 8.0))
669 			ret = 2; /* statement rollback */
670 		else
671 			ret = 1; /* transaction rollback */
672 	}
673 	else
674 	{
675 		ret = ci->rollback_on_error;
676 		if (2 == ret && PG_VERSION_LT(conn, 8.0))
677 			ret = 1;
678 	}
679 
680 	switch (ret)
681 	{
682 		case 1:
683 			SC_start_tc_stmt(stmt);
684 			break;
685 		case 2:
686 			SC_start_rb_stmt(stmt);
687 			break;
688 	}
689 	return	ret;
690 }
691 
692 int
GenerateSvpCommand(ConnectionClass * conn,int type,char * cmd,int buflen)693 GenerateSvpCommand(ConnectionClass *conn, int type, char *cmd, int buflen)
694 {
695 	char esavepoint[50];
696 	int	rtn = -1;
697 
698 	cmd[0] = '\0';
699 	switch (type)
700 	{
701 		case INTERNAL_SAVEPOINT_OPERATION:	/* savepoint */
702 #ifdef	_RELEASE_INTERNAL_SAVEPOINT
703 			if (conn->internal_svp)
704 				rtn = snprintf(cmd, buflen, "RELEASE %s;", GetSvpName(conn, esavepoint, sizeof(esavepoint)));
705 #endif /* _RELEASE_INTERNAL_SAVEPOINT */
706 			rtn = snprintfcat(cmd, buflen, "SAVEPOINT %s", GetSvpName(conn, esavepoint, sizeof(esavepoint)));
707 			break;
708 		case INTERNAL_ROLLBACK_OPERATION: /* rollback */
709 			if (conn->internal_svp)
710 				rtn = snprintf(cmd, buflen, "ROLLBACK TO %s", GetSvpName(conn, esavepoint, sizeof(esavepoint)));
711 			else
712 				rtn = snprintf(cmd, buflen, "ROLLBACK");
713 
714 			break;
715 	}
716 
717 	return rtn;
718 }
719 
720 /*
721  *	Must be in a transaction or the subsequent execution
722  *	invokes a transaction.
723  */
724 RETCODE
SetStatementSvp(StatementClass * stmt,unsigned int option)725 SetStatementSvp(StatementClass *stmt, unsigned int option)
726 {
727 	CSTR	func = "SetStatementSvp";
728 	char	cmd[128];
729 	ConnectionClass	*conn = SC_get_conn(stmt);
730 	QResultClass *res;
731 	RETCODE	ret = SQL_SUCCESS_WITH_INFO;
732 
733 	if (NULL == conn->pqconn)
734 	{
735 		SC_set_error(stmt, STMT_COMMUNICATION_ERROR, "The connection has been lost", __FUNCTION__);
736 		return SQL_ERROR;
737 	}
738 	if (CC_is_in_error_trans(conn))
739 		return ret;
740 
741 	if (!stmt->lock_CC_for_rb)
742 	{
743 		ENTER_CONN_CS(conn);
744 		stmt->lock_CC_for_rb = TRUE;
745 	}
746 MYLOG(DETAIL_LOG_LEVEL, " %p->accessed=%d opt=%u in_progress=%u prev=%u\n", conn, CC_accessed_db(conn), option, conn->opt_in_progress, conn->opt_previous);
747 	conn->opt_in_progress &= option;
748 	switch (stmt->statement_type)
749 	{
750 		case STMT_TYPE_SPECIAL:
751 		case STMT_TYPE_TRANSACTION:
752 			return ret;
753 	}
754 	/* If rbpoint is not yet started and the previous statement was not read-only */
755 	if (!CC_started_rbpoint(conn) && 0 == (conn->opt_previous & SVPOPT_RDONLY))
756 	{
757 		BOOL	need_savep = FALSE;
758 
759 		if (SC_is_rb_stmt(stmt))
760 		{
761 			if (CC_is_in_trans(conn)) /* needless to issue SAVEPOINT before the 1st command */
762 			{
763 				need_savep = TRUE;
764 			}
765 		}
766 		if (need_savep)
767 		{
768 			if (0 != (option & SVPOPT_REDUCE_ROUNDTRIP))
769 			{
770 				conn->internal_op = PREPEND_IN_PROGRESS;
771 				CC_set_accessed_db(conn);
772 				return ret;
773 			}
774 			GenerateSvpCommand(conn, INTERNAL_SAVEPOINT_OPERATION, cmd, sizeof(cmd));
775 			conn->internal_op = SAVEPOINT_IN_PROGRESS;
776 			res = CC_send_query(conn, cmd, NULL, 0, NULL);
777 			conn->internal_op = 0;
778 			if (QR_command_maybe_successful(res))
779 				ret = SQL_SUCCESS;
780 			else
781 			{
782 				SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal SAVEPOINT failed", func);
783 				ret = SQL_ERROR;
784 			}
785 			QR_Destructor(res);
786 		}
787 	}
788 	CC_set_accessed_db(conn);
789 MYLOG(DETAIL_LOG_LEVEL, "leaving %p->accessed=%d\n", conn, CC_accessed_db(conn));
790 	return ret;
791 }
792 
793 RETCODE
DiscardStatementSvp(StatementClass * stmt,RETCODE ret,BOOL errorOnly)794 DiscardStatementSvp(StatementClass *stmt, RETCODE ret, BOOL errorOnly)
795 {
796 	CSTR	func = "DiscardStatementSvp";
797 	ConnectionClass	*conn = SC_get_conn(stmt);
798 	BOOL	start_stmt = FALSE;
799 
800 MYLOG(DETAIL_LOG_LEVEL, "entering %p->accessed=%d is_in=%d is_rb=%d is_tc=%d\n", conn, CC_accessed_db(conn),
801 CC_is_in_trans(conn), SC_is_rb_stmt(stmt), SC_is_tc_stmt(stmt));
802 	if (stmt->lock_CC_for_rb)
803 		MYLOG(0, "in_progress=%u previous=%d\n", conn->opt_in_progress, conn->opt_previous);
804 	switch (ret)
805 	{
806 		case SQL_NEED_DATA:
807 			break;
808 		case SQL_ERROR:
809 			start_stmt = TRUE;
810 			break;
811 		default:
812 			if (!errorOnly)
813 				start_stmt = TRUE;
814 			break;
815 	}
816 	if (!CC_accessed_db(conn) || !CC_is_in_trans(conn))
817 		goto cleanup;
818 	if (!SC_is_rb_stmt(stmt) && !SC_is_tc_stmt(stmt))
819 		goto cleanup;
820 	if (SQL_ERROR == ret)
821 	{
822 		if (CC_started_rbpoint(conn) && conn->internal_svp)
823 		{
824 			int	cmd_success = CC_internal_rollback(conn, PER_STATEMENT_ROLLBACK, FALSE);
825 
826 			if (!cmd_success)
827 			{
828 				SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal ROLLBACK failed", func);
829 				goto cleanup;
830 			}
831 		}
832 		else
833 		{
834 			CC_abort(conn);
835 			goto cleanup;
836 		}
837 	}
838 	else if (errorOnly)
839 		return ret;
840 MYLOG(DETAIL_LOG_LEVEL, "\tret=%d\n", ret);
841 cleanup:
842 #ifdef NOT_USED
843 	if (!SC_is_prepare_statement(stmt) && ONCE_DESCRIBED == stmt->prepared)
844 		SC_set_prepared(stmt, NOT_YET_PREPARED);
845 #endif
846 	if (start_stmt || SQL_ERROR == ret)
847 	{
848 		stmt->execinfo = 0;
849 		if (SQL_ERROR != ret && CC_accessed_db(conn))
850 		{
851 			conn->opt_previous = conn->opt_in_progress;
852 			CC_init_opt_in_progress(conn);
853 		}
854 		if (stmt->lock_CC_for_rb)
855 		{
856 			stmt->lock_CC_for_rb = FALSE;
857 			LEAVE_CONN_CS(conn);
858 			MYLOG(DETAIL_LOG_LEVEL, " release conn_lock\n");
859 		}
860 		CC_start_stmt(conn);
861 	}
862 	MYLOG(DETAIL_LOG_LEVEL, "leaving %d\n", ret);
863 	return ret;
864 }
865 
866 /*
867  * Given a SQL statement, see if it is an INSERT INTO statement and extract
868  * the name of the table (with schema) of the table that was inserted to.
869  * (It is needed to resolve any @@identity references in the future.)
870  */
871 void
SC_setInsertedTable(StatementClass * stmt,RETCODE retval)872 SC_setInsertedTable(StatementClass *stmt, RETCODE retval)
873 {
874 	const char *cmd = stmt->statement;
875 	ConnectionClass	*conn;
876 	size_t	len;
877 
878 	if (STMT_TYPE_INSERT != stmt->statement_type)
879 		return;
880 	if (!SQL_SUCCEEDED(retval))
881 		return;
882 	conn = SC_get_conn(stmt);
883 #ifdef	NOT_USED /* give up the use of lastval() */
884 	if (PG_VERSION_GE(conn, 8.1)) /* lastval() is available */
885 		return;
886 #endif /* NOT_USED */
887 	/*if (!CC_fake_mss(conn))
888 		return;*/
889 
890 	/*
891 	 * Parse a statement that was just executed. If it looks like an INSERT INTO
892 	 * statement, try to extract the table name (and schema) of the table that
893 	 * we inserted into.
894 	 *
895 	 * This is by no means fool-proof, we don't implement the whole backend
896 	 * lexer and grammar here, but should handle most simple INSERT statements.
897 	 */
898 	while (isspace((UCHAR) *cmd)) cmd++;
899 	if (!*cmd)
900 		return;
901 	len = 6;
902 	if (strnicmp(cmd, "insert", len))
903 		return;
904 	cmd += len;
905 	while (isspace((UCHAR) *(++cmd)));
906 	if (!*cmd)
907 		return;
908 	len = 4;
909 	if (strnicmp(cmd, "into", len))
910 		return;
911 	cmd += len;
912 	while (isspace((UCHAR) *cmd)) cmd++;
913 	if (!*cmd)
914 		return;
915 	NULL_THE_NAME(conn->schemaIns);
916 	NULL_THE_NAME(conn->tableIns);
917 
918 	eatTableIdentifiers((const UCHAR *) cmd, conn->ccsc, &conn->tableIns, &conn->schemaIns);
919 	if (!NAME_IS_VALID(conn->tableIns))
920 		NULL_THE_NAME(conn->schemaIns);
921 }
922 
923 /*	Execute a prepared SQL statement */
924 RETCODE		SQL_API
PGAPI_Execute(HSTMT hstmt,UWORD flag)925 PGAPI_Execute(HSTMT hstmt, UWORD flag)
926 {
927 	CSTR func = "PGAPI_Execute";
928 	StatementClass *stmt = (StatementClass *) hstmt;
929 	RETCODE		retval = SQL_SUCCESS;
930 	ConnectionClass	*conn;
931 	APDFields	*apdopts;
932 	IPDFields	*ipdopts;
933 	SQLLEN		i, start_row, end_row;
934 	BOOL	exec_end = FALSE, recycled = FALSE, recycle = TRUE;
935 	SQLSMALLINT	num_params;
936 
937 	MYLOG(0, "entering...%x %p status=%d\n", flag, stmt, stmt->status);
938 
939 	stmt->has_notice = 0;
940 	conn = SC_get_conn(stmt);
941 	apdopts = SC_get_APDF(stmt);
942 
943 	/*
944 	 * If the statement was previously described, just recycle the old result
945 	 * set that contained just the column information.
946 	 */
947 	if ((stmt->prepare && stmt->status == STMT_DESCRIBED) ||
948 	    (stmt->status == STMT_FINISHED && 0 != (flag & PODBC_RECYCLE_STATEMENT)))
949 	{
950 		stmt->exec_current_row = -1;
951 		SC_recycle_statement(stmt);
952 	}
953 
954 	MYLOG(0, "clear errors...\n");
955 
956 	SC_clear_error(stmt);
957 	if (!stmt->statement)
958 	{
959 		SC_set_error(stmt, STMT_NO_STMTSTRING, "This handle does not have a SQL statement stored in it", func);
960 		MYLOG(0, "problem with handle\n");
961 		return SQL_ERROR;
962 	}
963 
964 #define	return	DONT_CALL_RETURN_FROM_HERE???
965 
966 	if (stmt->exec_current_row > 0)
967 	{
968 		/*
969 		 * executing an array of parameters.
970 		 * Don't recycle the statement.
971 		 */
972 		recycle = FALSE;
973 	}
974 	else if (PREPARED_PERMANENTLY == stmt->prepared ||
975 		 PREPARED_TEMPORARILY == stmt->prepared)
976 	{
977 		/*
978 		 * re-executing an prepared statement.
979 		 * Don't recycle the statement but
980 		 * discard the old result.
981 		 */
982 		recycle = FALSE;
983 		SC_reset_result_for_rerun(stmt);
984 	}
985 	/*
986 	 * If SQLExecute is being called again, recycle the statement. Note
987 	 * this should have been done by the application in a call to
988 	 * SQLFreeStmt(SQL_CLOSE) or SQLCancel.
989 	 */
990 	else if (stmt->status == STMT_FINISHED)
991 	{
992 		MYLOG(0, "recycling statement (should have been done by app)...\n");
993 /******** Is this really NEEDED ? ******/
994 		SC_recycle_statement(stmt);
995 		recycled = TRUE;
996 	}
997 	/* Check if the statement is in the correct state */
998 	else if ((stmt->prepare && stmt->status != STMT_READY) ||
999 		(stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
1000 	{
1001 		SC_set_error(stmt, STMT_STATUS_ERROR, "The handle does not point to a statement that is ready to be executed", func);
1002 		MYLOG(0, "problem with statement\n");
1003 		retval = SQL_ERROR;
1004 		goto cleanup;
1005 	}
1006 
1007 	if (start_row = stmt->exec_start_row, start_row < 0)
1008 		start_row = 0;
1009 	if (end_row = stmt->exec_end_row, end_row < 0)
1010 	{
1011 		end_row = (SQLINTEGER) apdopts->paramset_size - 1;
1012 		if (end_row < 0)
1013 		       end_row = 0;
1014 	}
1015 	if (stmt->exec_current_row < 0)
1016 		stmt->exec_current_row = start_row;
1017 	ipdopts = SC_get_IPDF(stmt);
1018 	num_params = stmt->num_params;
1019 	if (num_params < 0)
1020 		PGAPI_NumParams(stmt, &num_params);
1021 	if (stmt->exec_current_row == start_row)
1022 	{
1023 		/*
1024 		   We sometimes need to know about the PG type of binding
1025 		   parameters even in case of non-prepared statements.
1026 		 */
1027 		int	nCallParse = doNothing;
1028 		BOOL	maybeBatch = FALSE;
1029 
1030 		if (end_row > start_row &&
1031 		    SQL_CURSOR_FORWARD_ONLY == stmt->options.cursor_type &&
1032 		    SQL_CONCUR_READ_ONLY == stmt->options.scroll_concurrency &&
1033 		    stmt->batch_size > 1)
1034 			maybeBatch = TRUE;
1035 MYLOG(0, "prepare=%d prepared=%d  batch_size=%d start_row=" FORMAT_LEN "end_row=" FORMAT_LEN " => maybeBatch=%d\n", stmt->prepare, stmt->prepared, stmt->batch_size, start_row, end_row, maybeBatch);
1036 		if (NOT_YET_PREPARED == stmt->prepared)
1037 		{
1038 			if (maybeBatch)
1039 				stmt->use_server_side_prepare = 0;
1040 			switch (nCallParse = HowToPrepareBeforeExec(stmt, TRUE))
1041 			{
1042 				case shouldParse:
1043 					if (retval = prepareParameters(stmt, FALSE), SQL_ERROR == retval)
1044 						goto cleanup;
1045 					break;
1046 			}
1047 		}
1048 MYLOG(0, "prepareParameters was %s called, prepare state:%d\n", shouldParse == nCallParse ? "" : "not", stmt->prepare);
1049 
1050 		if (shouldParse == nCallParse &&
1051 		    PREPARE_BY_THE_DRIVER == stmt->prepare)
1052 		{
1053 			SC_set_Result(stmt, NULL);
1054 		}
1055 		if (0 != (PREPARE_BY_THE_DRIVER & stmt->prepare) &&
1056 		    maybeBatch)
1057 			stmt->exec_type = DEFFERED_EXEC;
1058 		else
1059 			stmt->exec_type = DIRECT_EXEC;
1060 
1061 MYLOG(0, "prepare=%d maybeBatch=%d exec_type=%d\n", stmt->prepare, maybeBatch, stmt->exec_type);
1062 		if (ipdopts->param_processed_ptr)
1063 			*ipdopts->param_processed_ptr = 0;
1064 		/*
1065 		 * Initialize param_status_ptr
1066 		 */
1067 		if (ipdopts->param_status_ptr)
1068 		{
1069 			for (i = 0; i <= end_row; i++)
1070 				ipdopts->param_status_ptr[i] = SQL_PARAM_UNUSED;
1071 		}
1072 		if (recycle && !recycled)
1073 			SC_recycle_statement(stmt);
1074 		if (isSqlServr() &&
1075 		    stmt->external &&
1076 		    0 != stmt->prepare &&
1077 		    PG_VERSION_LT(conn, 8.4) &&
1078 		    SC_can_parse_statement(stmt))
1079 			parse_sqlsvr(stmt);
1080 	}
1081 
1082 next_param_row:
1083 	if (stmt->exec_current_row > end_row)
1084 		exec_end = TRUE;
1085 	else if (apdopts->param_operation_ptr)
1086 	{
1087 		while (apdopts->param_operation_ptr[stmt->exec_current_row] == SQL_PARAM_IGNORE)
1088 		{
1089 			if (stmt->exec_current_row >= end_row)
1090 			{
1091 				exec_end = TRUE;
1092 				break;
1093 			}
1094 			++stmt->exec_current_row;
1095 		}
1096 	}
1097 	if (exec_end)
1098 	{
1099 		if (DEFFERED_EXEC == stmt->exec_type )
1100 			retval = Exec_with_parameters_resolved(stmt, LAST_EXEC, &exec_end);
1101 		stmt->exec_current_row = -1;
1102 		goto cleanup;
1103 	}
1104 	/*
1105 	 *	Initialize the current row status
1106 	 */
1107 	if (ipdopts->param_status_ptr)
1108 		ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
1109 
1110 	/*
1111 	 *	Free any data at exec params before the statement is
1112 	 *	executed again or the next set of parameters is processed.
1113 	 *	If not,	then there will be a memory leak when the next
1114 	 *	SQLParamData/SQLPutData is called.
1115 	 */
1116 	SC_free_params(stmt, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
1117 
1118 	/*
1119 	 * Check if statement has any data-at-execute parameters when it is
1120 	 * not in SC_pre_execute.
1121 	 */
1122 	{
1123 		/*
1124 		 * The bound parameters could have possibly changed since the last
1125 		 * execute of this statement?  Therefore check for params and
1126 		 * re-copy.
1127 		 */
1128 		SQLULEN	offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
1129 		SQLINTEGER	bind_size = apdopts->param_bind_type;
1130 		SQLLEN		current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
1131 		Int4	num_p = num_params < apdopts->allocated ? num_params : apdopts->allocated;
1132 
1133 		/*
1134 		 *	Increment the  number of currently processed rows
1135 		 */
1136 		if (ipdopts->param_processed_ptr)
1137 			(*ipdopts->param_processed_ptr)++;
1138 		stmt->data_at_exec = -1;
1139 		for (i = 0; i < num_p; i++)
1140 		{
1141 			SQLLEN	   *pcVal = apdopts->parameters[i].used;
1142 
1143 			apdopts->parameters[i].data_at_exec = FALSE;
1144 			if (pcVal)
1145 			{
1146 				if (bind_size > 0)
1147 					pcVal = LENADDR_SHIFT(pcVal, offset + bind_size * current_row);
1148 				else
1149 					pcVal = LENADDR_SHIFT(pcVal, offset) + current_row;
1150 				if (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET)
1151 					apdopts->parameters[i].data_at_exec = TRUE;
1152 			}
1153 			/* Check for data at execution parameters */
1154 			if (apdopts->parameters[i].data_at_exec)
1155 			{
1156 				MYLOG(0, "The " FORMAT_LEN "th parameter of " FORMAT_LEN "-row is data at exec(" FORMAT_LEN ")\n", i, current_row, pcVal ? (*pcVal) : -1);
1157 				if (stmt->data_at_exec < 0)
1158 					stmt->data_at_exec = 1;
1159 				else
1160 					stmt->data_at_exec++;
1161 			}
1162 		}
1163 
1164 		/*
1165 		 * If there are some data at execution parameters, return need
1166 		 * data
1167 		 */
1168 
1169 		/*
1170 		 * SQLParamData and SQLPutData will be used to send params and
1171 		 * execute the statement.
1172 		 */
1173 		if (stmt->data_at_exec > 0)
1174 		{
1175 			retval = SQL_NEED_DATA;
1176 			goto cleanup;
1177 		}
1178 	}
1179 
1180 	if (0 != (flag & PODBC_WITH_HOLD))
1181 		SC_set_with_hold(stmt);
1182 	retval = Exec_with_parameters_resolved(stmt, stmt->exec_type, &exec_end);
1183 	if (!exec_end)
1184 	{
1185 		goto next_param_row;
1186 	}
1187 cleanup:
1188 MYLOG(0, "leaving %p retval=%d status=%d\n", stmt, retval, stmt->status);
1189 	SC_setInsertedTable(stmt, retval);
1190 #undef	return
1191 	if (SQL_SUCCESS == retval &&
1192 	    STMT_OK > SC_get_errornumber(stmt))
1193 		retval = SQL_SUCCESS_WITH_INFO;
1194 	return retval;
1195 }
1196 
1197 
1198 RETCODE		SQL_API
PGAPI_Transact(HENV henv,HDBC hdbc,SQLUSMALLINT fType)1199 PGAPI_Transact(HENV henv,
1200 			   HDBC hdbc,
1201 			   SQLUSMALLINT fType)
1202 {
1203 	CSTR func = "PGAPI_Transact";
1204 	ConnectionClass *conn;
1205 	char		ok;
1206 	int			lf;
1207 
1208 	MYLOG(0, "entering hdbc=%p, henv=%p\n", hdbc, henv);
1209 
1210 	if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV)
1211 	{
1212 		CC_log_error(func, "", NULL);
1213 		return SQL_INVALID_HANDLE;
1214 	}
1215 
1216 	/*
1217 	 * If hdbc is null and henv is valid, it means transact all
1218 	 * connections on that henv.
1219 	 */
1220 	if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV)
1221 	{
1222 		ConnectionClass * const *conns = getConnList();
1223 		const int	conn_count = getConnCount();
1224 		for (lf = 0; lf < conn_count; lf++)
1225 		{
1226 			conn = conns[lf];
1227 
1228 			if (conn && CC_get_env(conn) == henv)
1229 				if (PGAPI_Transact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
1230 					return SQL_ERROR;
1231 		}
1232 		return SQL_SUCCESS;
1233 	}
1234 
1235 	conn = (ConnectionClass *) hdbc;
1236 
1237 	if (fType != SQL_COMMIT &&
1238 	    fType != SQL_ROLLBACK)
1239 	{
1240 		CC_set_error(conn, CONN_INVALID_ARGUMENT_NO, "PGAPI_Transact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter", func);
1241 		return SQL_ERROR;
1242 	}
1243 
1244 	/* If manual commit and in transaction, then proceed. */
1245 	if (CC_loves_visible_trans(conn) && CC_is_in_trans(conn))
1246 	{
1247 		MYLOG(0, "sending on conn %p '%d'\n", conn, fType);
1248 
1249 		ok = (SQL_COMMIT == fType) ? CC_commit(conn) : CC_abort(conn);
1250 		if (!ok)
1251 		{
1252 			/* error msg will be in the connection */
1253 			CC_on_abort(conn, NO_TRANS);
1254 			CC_log_error(func, "", conn);
1255 			return SQL_ERROR;
1256 		}
1257 	}
1258 	return SQL_SUCCESS;
1259 }
1260 
1261 
1262 RETCODE		SQL_API
PGAPI_Cancel(HSTMT hstmt)1263 PGAPI_Cancel(HSTMT hstmt)		/* Statement to cancel. */
1264 {
1265 	CSTR func = "PGAPI_Cancel";
1266 	StatementClass *stmt = (StatementClass *) hstmt, *estmt;
1267 	ConnectionClass *conn;
1268 	RETCODE		ret = SQL_SUCCESS;
1269 
1270 	MYLOG(0, "entering...\n");
1271 
1272 	/* Check if this can handle canceling in the middle of a SQLPutData? */
1273 	if (!stmt)
1274 	{
1275 		SC_log_error(func, "", NULL);
1276 		return SQL_INVALID_HANDLE;
1277 	}
1278 	conn = SC_get_conn(stmt);
1279 
1280 	if (stmt->execute_delegate)
1281 		estmt = stmt->execute_delegate;
1282 	else
1283 		estmt = stmt;
1284 
1285 	/*
1286 	 * SQLCancel works differently depending on what the statement is
1287 	 * currently doing:
1288 	 *
1289 	 * 1. In the middle of SQLParamData / SQLPutData
1290 	 *    -> cancel the statement
1291 	 *
1292 	 * 2. Running a query asynchronously. (asynchronous mode is not supported
1293 	 *    by psqlODBC)
1294 	 *
1295 	 * 3. Busy running a function in another thread.
1296 	 *    -> Send a query cancel request to the server
1297 	 *
1298 	 * 4. Not doing anything.
1299 	 *    -> in ODBC version 2.0, same as SQLFreeStmt(SQL_CLOSE). In version
1300 	 *       3.5, it has no effect.
1301 	 *
1302 	 * XXX: Checking for these conditions is racy. For example, we might
1303 	 * see that the statement is waiting for SQLParamdata/SQLPutData, but
1304 	 * before we acquire the lock on the statement, another thread has
1305 	 * supplied the data and started executing. In that case, we'll block
1306 	 * on the lock until the execution finishes.
1307 	 */
1308 	if (estmt->data_at_exec >= 0)
1309 	{
1310 		/* Waiting for more data from SQLParamData/SQLPutData. Cancel that. */
1311 		/*
1312 		 * Note, any previous data-at-exec buffers will be freed
1313 		 * if they call SQLExecDirect or SQLExecute again.
1314 		 */
1315 
1316 		ENTER_STMT_CS(stmt);
1317 		SC_clear_error(stmt);
1318 		estmt->data_at_exec = -1;
1319 		estmt->current_exec_param = -1;
1320 		estmt->put_data = FALSE;
1321 		cancelNeedDataState(estmt);
1322 		LEAVE_STMT_CS(stmt);
1323 		return ret;
1324 	}
1325 	else if (estmt->status == STMT_EXECUTING)
1326 	{
1327 		/*
1328 		 * Busy executing in a different thread. Send a cancel request to
1329 		 * the server.
1330 		 */
1331 		if (!CC_send_cancel_request(conn))
1332 			return SQL_ERROR;
1333 		else
1334 			return SQL_SUCCESS;
1335 	}
1336 	else
1337 	{
1338 		/*
1339 		 * The statement is not executing, and it's not waiting for params
1340 		 * either. Looks like it's not doing anything.
1341 		 */
1342 		return SQL_SUCCESS;
1343 	}
1344 }
1345 
1346 
1347 /*
1348  *	Returns the SQL string as modified by the driver.
1349  *	Currently, just copy the input string without modification
1350  *	observing buffer limits and truncation.
1351  */
1352 RETCODE		SQL_API
PGAPI_NativeSql(HDBC hdbc,const SQLCHAR * szSqlStrIn,SQLINTEGER cbSqlStrIn,SQLCHAR * szSqlStr,SQLINTEGER cbSqlStrMax,SQLINTEGER * pcbSqlStr)1353 PGAPI_NativeSql(HDBC hdbc,
1354 				const SQLCHAR * szSqlStrIn,
1355 				SQLINTEGER cbSqlStrIn,
1356 				SQLCHAR * szSqlStr,
1357 				SQLINTEGER cbSqlStrMax,
1358 				SQLINTEGER * pcbSqlStr)
1359 {
1360 	CSTR func = "PGAPI_NativeSql";
1361 	size_t		len = 0;
1362 	char	   *ptr;
1363 	ConnectionClass *conn = (ConnectionClass *) hdbc;
1364 	RETCODE		result;
1365 
1366 	MYLOG(0, "entering...cbSqlStrIn=" FORMAT_INTEGER "\n", cbSqlStrIn);
1367 
1368 	ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL, 0);
1369 	if (!ptr)
1370 	{
1371 		CC_set_error(conn, CONN_NO_MEMORY_ERROR, "No memory available to store native sql string", func);
1372 		return SQL_ERROR;
1373 	}
1374 
1375 	result = SQL_SUCCESS;
1376 	len = strlen(ptr);
1377 
1378 	if (szSqlStr)
1379 	{
1380 		strncpy_null((char *) szSqlStr, ptr, cbSqlStrMax);
1381 
1382 		if (len >= cbSqlStrMax)
1383 		{
1384 			result = SQL_SUCCESS_WITH_INFO;
1385 			CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the NativeSQL.", func);
1386 		}
1387 	}
1388 
1389 	if (pcbSqlStr)
1390 		*pcbSqlStr = (SQLINTEGER) len;
1391 
1392 	if (cbSqlStrIn)
1393 		free(ptr);
1394 
1395 	return result;
1396 }
1397 
1398 
1399 /*
1400  *	Supplies parameter data at execution time.
1401  *	Used in conjuction with SQLPutData.
1402  */
1403 RETCODE		SQL_API
PGAPI_ParamData(HSTMT hstmt,PTR * prgbValue)1404 PGAPI_ParamData(HSTMT hstmt,
1405 				PTR * prgbValue)
1406 {
1407 	CSTR func = "PGAPI_ParamData";
1408 	StatementClass *stmt = (StatementClass *) hstmt, *estmt;
1409 	APDFields	*apdopts;
1410 	IPDFields	*ipdopts;
1411 	RETCODE		retval;
1412 	int		i;
1413 	Int2		num_p;
1414 	ConnectionClass	*conn = NULL;
1415 
1416 	MYLOG(0, "entering...\n");
1417 
1418 	conn = SC_get_conn(stmt);
1419 
1420 	estmt = stmt->execute_delegate ? stmt->execute_delegate : stmt;
1421 	apdopts = SC_get_APDF(estmt);
1422 	MYLOG(0, "\tdata_at_exec=%d, params_alloc=%d\n", estmt->data_at_exec, apdopts->allocated);
1423 
1424 #define	return	DONT_CALL_RETURN_FROM_HERE???
1425 	if (SC_AcceptedCancelRequest(stmt))
1426 	{
1427 		SC_set_error(stmt, STMT_OPERATION_CANCELLED, "Cancel the statement, sorry", func);
1428 		retval = SQL_ERROR;
1429 		goto cleanup;
1430 	}
1431 	if (estmt->data_at_exec < 0)
1432 	{
1433 		SC_set_error(stmt, STMT_SEQUENCE_ERROR, "No execution-time parameters for this statement", func);
1434 		retval = SQL_ERROR;
1435 		goto cleanup;
1436 	}
1437 
1438 	if (estmt->data_at_exec > apdopts->allocated)
1439 	{
1440 		SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Too many execution-time parameters were present", func);
1441 		retval = SQL_ERROR;
1442 		goto cleanup;
1443 	}
1444 
1445 	/* close the large object */
1446 	if (estmt->lobj_fd >= 0)
1447 	{
1448 		odbc_lo_close(conn, estmt->lobj_fd);
1449 
1450 		/* commit transaction if needed */
1451 		if (!CC_cursor_count(conn) && CC_does_autocommit(conn))
1452 		{
1453 			if (!CC_commit(conn))
1454 			{
1455 				SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction", func);
1456 				retval = SQL_ERROR;
1457 				goto cleanup;
1458 			}
1459 		}
1460 		estmt->lobj_fd = -1;
1461 	}
1462 
1463 	/* Done, now copy the params and then execute the statement */
1464 	ipdopts = SC_get_IPDF(estmt);
1465 MYLOG(DETAIL_LOG_LEVEL, "ipdopts=%p\n", ipdopts);
1466 	if (estmt->data_at_exec == 0)
1467 	{
1468 		BOOL	exec_end;
1469 		UWORD	flag = SC_is_with_hold(stmt) ? PODBC_WITH_HOLD : 0;
1470 
1471 		retval = Exec_with_parameters_resolved(estmt, stmt->exec_type, &exec_end);
1472 		if (exec_end)
1473 		{
1474 			/**SC_reset_delegate(retval, stmt);**/
1475 			retval = dequeueNeedDataCallback(retval, stmt);
1476 			goto cleanup;
1477 		}
1478 
1479 		if (retval = PGAPI_Execute(estmt, flag), SQL_NEED_DATA != retval)
1480 		{
1481 			goto cleanup;
1482 		}
1483 	}
1484 
1485 	/*
1486 	 * Set beginning param;  if first time SQLParamData is called , start
1487 	 * at 0. Otherwise, start at the last parameter + 1.
1488 	 */
1489 	i = estmt->current_exec_param >= 0 ? estmt->current_exec_param + 1 : 0;
1490 
1491 	num_p = estmt->num_params;
1492 	if (num_p < 0)
1493 		PGAPI_NumParams(estmt, &num_p);
1494 MYLOG(DETAIL_LOG_LEVEL, "i=%d allocated=%d num_p=%d\n", i, apdopts->allocated, num_p);
1495 	if (num_p > apdopts->allocated)
1496 		num_p = apdopts->allocated;
1497 	/* At least 1 data at execution parameter, so Fill in the token value */
1498 	for (; i < num_p; i++)
1499 	{
1500 MYLOG(DETAIL_LOG_LEVEL, "i=%d", i);
1501 		if (apdopts->parameters[i].data_at_exec)
1502 		{
1503 MYPRINTF(DETAIL_LOG_LEVEL, " at exec buffer=%p", apdopts->parameters[i].buffer);
1504 			estmt->data_at_exec--;
1505 			estmt->current_exec_param = i;
1506 			estmt->put_data = FALSE;
1507 			if (prgbValue)
1508 			{
1509 				/* returns token here */
1510 				if (stmt->execute_delegate)
1511 				{
1512 					SQLULEN	offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
1513 					SQLLEN	perrow = apdopts->param_bind_type > 0 ? apdopts->param_bind_type : apdopts->parameters[i].buflen;
1514 
1515 MYPRINTF(DETAIL_LOG_LEVEL, " offset=" FORMAT_LEN " perrow=" FORMAT_LEN, offset, perrow);
1516 					*prgbValue = apdopts->parameters[i].buffer + offset + estmt->exec_current_row * perrow;
1517 				}
1518 				else
1519 					*prgbValue = apdopts->parameters[i].buffer;
1520 			}
1521 			break;
1522 		}
1523 MYPRINTF(DETAIL_LOG_LEVEL, "\n");
1524 	}
1525 
1526 	retval = SQL_NEED_DATA;
1527 MYLOG(DETAIL_LOG_LEVEL, "return SQL_NEED_DATA\n");
1528 cleanup:
1529 #undef	return
1530 	SC_setInsertedTable(stmt, retval);
1531 	MYLOG(0, "leaving %d\n", retval);
1532 	return retval;
1533 }
1534 
1535 
1536 /*
1537  *	Supplies parameter data at execution time.
1538  *	Used in conjunction with SQLParamData.
1539  */
1540 RETCODE		SQL_API
PGAPI_PutData(HSTMT hstmt,PTR rgbValue,SQLLEN cbValue)1541 PGAPI_PutData(HSTMT hstmt,
1542 			  PTR rgbValue,
1543 			  SQLLEN cbValue)
1544 {
1545 	CSTR func = "PGAPI_PutData";
1546 	StatementClass *stmt = (StatementClass *) hstmt, *estmt;
1547 	ConnectionClass *conn;
1548 	RETCODE		retval = SQL_SUCCESS;
1549 	APDFields	*apdopts;
1550 	IPDFields	*ipdopts;
1551 	PutDataInfo	*pdata;
1552 	SQLLEN		old_pos;
1553 	ParameterInfoClass *current_param;
1554 	ParameterImplClass *current_iparam;
1555 	PutDataClass	*current_pdata;
1556 	char	   *putbuf, *allocbuf = NULL;
1557 	Int2		ctype;
1558 	SQLLEN		putlen;
1559 	BOOL		lenset = FALSE, handling_lo = FALSE;
1560 
1561 	MYLOG(0, "entering...\n");
1562 
1563 #define	return	DONT_CALL_RETURN_FROM_HERE???
1564 	if (SC_AcceptedCancelRequest(stmt))
1565 	{
1566 		SC_set_error(stmt, STMT_OPERATION_CANCELLED, "Cancel the statement, sorry.", func);
1567 		retval = SQL_ERROR;
1568 		goto cleanup;
1569 	}
1570 
1571 	estmt = stmt->execute_delegate ? stmt->execute_delegate : stmt;
1572 	apdopts = SC_get_APDF(estmt);
1573 	if (estmt->current_exec_param < 0)
1574 	{
1575 		SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Previous call was not SQLPutData or SQLParamData", func);
1576 		retval = SQL_ERROR;
1577 		goto cleanup;
1578 	}
1579 
1580 	current_param = &(apdopts->parameters[estmt->current_exec_param]);
1581 	ipdopts = SC_get_IPDF(estmt);
1582 	current_iparam = &(ipdopts->parameters[estmt->current_exec_param]);
1583 	pdata = SC_get_PDTI(estmt);
1584 	current_pdata = &(pdata->pdata[estmt->current_exec_param]);
1585 	ctype = current_param->CType;
1586 
1587 	conn = SC_get_conn(estmt);
1588 	if (ctype == SQL_C_DEFAULT)
1589 	{
1590 		ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
1591 #ifdef	UNICODE_SUPPORT
1592 		if (SQL_C_WCHAR == ctype &&
1593 		    CC_default_is_c(conn))
1594 			ctype = SQL_C_CHAR;
1595 #endif
1596 	}
1597 	if (SQL_NTS == cbValue)
1598 	{
1599 #ifdef	UNICODE_SUPPORT
1600 		if (SQL_C_WCHAR == ctype)
1601 		{
1602 			putlen = WCLEN * ucs2strlen((SQLWCHAR *) rgbValue);
1603 			lenset = TRUE;
1604 		}
1605 		else
1606 #endif /* UNICODE_SUPPORT */
1607 		if (SQL_C_CHAR == ctype)
1608 		{
1609 			putlen = strlen(rgbValue);
1610 			lenset = TRUE;
1611 		}
1612 	}
1613 	if (!lenset)
1614 	{
1615 		if (cbValue < 0)
1616 			putlen = cbValue;
1617 		else
1618 #ifdef	UNICODE_SUPPORT
1619 		if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
1620 #else
1621 		if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
1622 #endif /* UNICODE_SUPPORT */
1623 			putlen = cbValue;
1624 		else
1625 			putlen = ctype_length(ctype);
1626 	}
1627 	putbuf = rgbValue;
1628 	handling_lo = (PIC_dsp_pgtype(conn, *current_iparam) == conn->lobj_type);
1629 	if (handling_lo && SQL_C_CHAR == ctype)
1630 	{
1631 		allocbuf = malloc(putlen / 2 + 1);
1632 		if (allocbuf)
1633 		{
1634 			pg_hex2bin(rgbValue, allocbuf, putlen);
1635 			putbuf = allocbuf;
1636 			putlen /= 2;
1637 		}
1638 	}
1639 
1640 	if (!estmt->put_data)
1641 	{							/* first call */
1642 		MYLOG(0, "(1) cbValue = " FORMAT_LEN "\n", cbValue);
1643 
1644 		estmt->put_data = TRUE;
1645 
1646 		current_pdata->EXEC_used = (SQLLEN *) malloc(sizeof(SQLLEN));
1647 		if (!current_pdata->EXEC_used)
1648 		{
1649 			SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (1)", func);
1650 			retval = SQL_ERROR;
1651 			goto cleanup;
1652 		}
1653 
1654 		*current_pdata->EXEC_used = putlen;
1655 
1656 		if (cbValue == SQL_NULL_DATA)
1657 		{
1658 			retval = SQL_SUCCESS;
1659 			goto cleanup;
1660 		}
1661 
1662 		/* Handle Long Var Binary with Large Objects */
1663 		/* if (current_iparam->SQLType == SQL_LONGVARBINARY) */
1664 		if (handling_lo)
1665 		{
1666 			/* begin transaction if needed */
1667 			if (!CC_is_in_trans(conn))
1668 			{
1669 				if (!CC_begin(conn))
1670 				{
1671 					SC_set_error(stmt, STMT_EXEC_ERROR, "Could not begin (in-line) a transaction", func);
1672 					retval = SQL_ERROR;
1673 					goto cleanup;
1674 				}
1675 			}
1676 
1677 			/* store the oid */
1678 			current_pdata->lobj_oid = odbc_lo_creat(conn, INV_READ | INV_WRITE);
1679 			if (current_pdata->lobj_oid == 0)
1680 			{
1681 				SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt create large object.", func);
1682 				retval = SQL_ERROR;
1683 				goto cleanup;
1684 			}
1685 
1686 			/*
1687 			 * major hack -- to allow convert to see somethings there have
1688 			 * to modify convert to handle this better
1689 			 */
1690 			/***current_param->EXEC_buffer = (char *) &current_param->lobj_oid;***/
1691 
1692 			/* store the fd */
1693 			estmt->lobj_fd = odbc_lo_open(conn, current_pdata->lobj_oid, INV_WRITE);
1694 			if (estmt->lobj_fd < 0)
1695 			{
1696 				SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt open large object for writing.", func);
1697 				retval = SQL_ERROR;
1698 				goto cleanup;
1699 			}
1700 
1701 			retval = odbc_lo_write(conn, estmt->lobj_fd, putbuf, (Int4) putlen);
1702 			MYLOG(0, "lo_write: cbValue=" FORMAT_LEN ", wrote %d bytes\n", putlen, retval);
1703 		}
1704 		else
1705 		{
1706 			current_pdata->EXEC_buffer = malloc(putlen + 1);
1707 			if (!current_pdata->EXEC_buffer)
1708 			{
1709 				SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)", func);
1710 				retval = SQL_ERROR;
1711 				goto cleanup;
1712 			}
1713 			memcpy(current_pdata->EXEC_buffer, putbuf, putlen);
1714 			current_pdata->EXEC_buffer[putlen] = '\0';
1715 		}
1716 	}
1717 	else
1718 	{
1719 		/* calling SQLPutData more than once */
1720 		MYLOG(0, "(>1) cbValue = " FORMAT_LEN "\n", cbValue);
1721 
1722 		/* if (current_iparam->SQLType == SQL_LONGVARBINARY) */
1723 		if (handling_lo)
1724 		{
1725 			/* the large object fd is in EXEC_buffer */
1726 			retval = odbc_lo_write(conn, estmt->lobj_fd, putbuf, (Int4) putlen);
1727 			MYLOG(0, "lo_write(2): cbValue = " FORMAT_LEN ", wrote %d bytes\n", putlen, retval);
1728 
1729 			*current_pdata->EXEC_used += putlen;
1730 		}
1731 		else
1732 		{
1733 			old_pos = *current_pdata->EXEC_used;
1734 			if (putlen > 0)
1735 			{
1736 				SQLLEN	used = *current_pdata->EXEC_used + putlen;
1737 				SQLLEN allocsize;
1738 				char *buffer;
1739 
1740 				for (allocsize = (1 << 4); allocsize <= used; allocsize <<= 1) ;
1741 				MYLOG(0, "        cbValue = " FORMAT_LEN ", old_pos = " FORMAT_LEN ", *used = " FORMAT_LEN "\n", putlen, old_pos, used);
1742 
1743 				/* dont lose the old pointer in case out of memory */
1744 				buffer = realloc(current_pdata->EXEC_buffer, allocsize);
1745 				if (!buffer)
1746 				{
1747 					SC_set_error(stmt, STMT_NO_MEMORY_ERROR,"Out of memory in PGAPI_PutData (3)", func);
1748 					retval = SQL_ERROR;
1749 					goto cleanup;
1750 				}
1751 
1752 				memcpy(&buffer[old_pos], putbuf, putlen);
1753 				buffer[used] = '\0';
1754 
1755 				/* reassign buffer incase realloc moved it */
1756 				*current_pdata->EXEC_used = used;
1757 				current_pdata->EXEC_buffer = buffer;
1758 			}
1759 			else
1760 			{
1761 				SC_set_error(stmt, STMT_INTERNAL_ERROR, "bad cbValue", func);
1762 				retval = SQL_ERROR;
1763 				goto cleanup;
1764 			}
1765 		}
1766 	}
1767 
1768 	retval = SQL_SUCCESS;
1769 cleanup:
1770 #undef	return
1771 	if (allocbuf)
1772 		free(allocbuf);
1773 
1774 	return retval;
1775 }
1776