1 /* src/interfaces/ecpg/ecpglib/execute.c */
2 
3 /*
4  * The aim is to get a simpler interface to the database routines.
5  * All the tedious messing around with tuples is supposed to be hidden
6  * by this function.
7  */
8 /* Author: Linus Tolke
9    (actually most if the code is "borrowed" from the distribution and just
10    slightly modified)
11  */
12 
13 /* Taken over as part of PostgreSQL by Michael Meskes <meskes@postgresql.org>
14    on Feb. 5th, 1998 */
15 
16 #define POSTGRES_ECPG_INTERNAL
17 #include "postgres_fe.h"
18 
19 #include <float.h>
20 #include <math.h>
21 
22 #include "pg_type.h"
23 
24 #include "ecpgtype.h"
25 #include "ecpglib.h"
26 #include "ecpgerrno.h"
27 #include "extern.h"
28 #include "sqlca.h"
29 #include "sqlda-native.h"
30 #include "sqlda-compat.h"
31 #include "sql3types.h"
32 #include "pgtypes_numeric.h"
33 #include "pgtypes_date.h"
34 #include "pgtypes_timestamp.h"
35 #include "pgtypes_interval.h"
36 
37 /*
38  *	This function returns a newly malloced string that has ' and \
39  *	escaped.
40  */
41 static char *
quote_postgres(char * arg,bool quote,int lineno)42 quote_postgres(char *arg, bool quote, int lineno)
43 {
44 	char	   *res;
45 	size_t		length;
46 	size_t		escaped_len;
47 	size_t		buffer_len;
48 
49 	/*
50 	 * if quote is false we just need to store things in a descriptor they
51 	 * will be quoted once they are inserted in a statement
52 	 */
53 	if (!quote)
54 		return arg;
55 	else
56 	{
57 		length = strlen(arg);
58 		buffer_len = 2 * length + 1;
59 		res = (char *) ecpg_alloc(buffer_len + 3, lineno);
60 		if (!res)
61 			return (res);
62 		escaped_len = PQescapeString(res + 1, arg, buffer_len);
63 		if (length == escaped_len)
64 		{
65 			res[0] = res[escaped_len + 1] = '\'';
66 			res[escaped_len + 2] = '\0';
67 		}
68 		else
69 		{
70 			/*
71 			 * We don't know if the target database is using
72 			 * standard_conforming_strings, so we always use E'' strings.
73 			 */
74 			memmove(res + 2, res + 1, escaped_len);
75 			res[0] = ESCAPE_STRING_SYNTAX;
76 			res[1] = res[escaped_len + 2] = '\'';
77 			res[escaped_len + 3] = '\0';
78 		}
79 		ecpg_free(arg);
80 		return res;
81 	}
82 }
83 
84 static void
free_variable(struct variable * var)85 free_variable(struct variable *var)
86 {
87 	struct variable *var_next;
88 
89 	while (var)
90 	{
91 		var_next = var->next;
92 		ecpg_free(var);
93 		var = var_next;
94 	}
95 }
96 
97 static void
free_statement(struct statement * stmt)98 free_statement(struct statement *stmt)
99 {
100 	if (stmt == NULL)
101 		return;
102 	free_variable(stmt->inlist);
103 	free_variable(stmt->outlist);
104 	ecpg_free(stmt->command);
105 	ecpg_free(stmt->name);
106 #ifdef HAVE_USELOCALE
107 	if (stmt->clocale)
108 		freelocale(stmt->clocale);
109 #else
110 	ecpg_free(stmt->oldlocale);
111 #endif
112 	ecpg_free(stmt);
113 }
114 
115 static int
next_insert(char * text,int pos,bool questionmarks,bool std_strings)116 next_insert(char *text, int pos, bool questionmarks, bool std_strings)
117 {
118 	bool		string = false;
119 	int			p = pos;
120 
121 	for (; text[p] != '\0'; p++)
122 	{
123 		if (string && !std_strings && text[p] == '\\')	/* escape character */
124 			p++;
125 		else if (text[p] == '\'')
126 			string = string ? false : true;
127 		else if (!string)
128 		{
129 			if (text[p] == '$' && isdigit((unsigned char) text[p + 1]))
130 			{
131 				/* this can be either a dollar quote or a variable */
132 				int			i;
133 
134 				for (i = p + 1; isdigit((unsigned char) text[i]); i++)
135 					 /* empty loop body */ ;
136 				if (!isalpha((unsigned char) text[i]) &&
137 					isascii((unsigned char) text[i]) &&text[i] != '_')
138 					/* not dollar delimited quote */
139 					return p;
140 			}
141 			else if (questionmarks && text[p] == '?')
142 			{
143 				/* also allow old style placeholders */
144 				return p;
145 			}
146 		}
147 	}
148 
149 	return -1;
150 }
151 
152 static bool
ecpg_type_infocache_push(struct ECPGtype_information_cache ** cache,int oid,enum ARRAY_TYPE isarray,int lineno)153 ecpg_type_infocache_push(struct ECPGtype_information_cache **cache, int oid, enum ARRAY_TYPE isarray, int lineno)
154 {
155 	struct ECPGtype_information_cache *new_entry
156 	= (struct ECPGtype_information_cache *) ecpg_alloc(sizeof(struct ECPGtype_information_cache), lineno);
157 
158 	if (new_entry == NULL)
159 		return (false);
160 
161 	new_entry->oid = oid;
162 	new_entry->isarray = isarray;
163 	new_entry->next = *cache;
164 	*cache = new_entry;
165 	return (true);
166 }
167 
168 static enum ARRAY_TYPE
ecpg_is_type_an_array(int type,const struct statement * stmt,const struct variable * var)169 ecpg_is_type_an_array(int type, const struct statement *stmt, const struct variable *var)
170 {
171 	char	   *array_query;
172 	enum ARRAY_TYPE isarray = ECPG_ARRAY_NOT_SET;
173 	PGresult   *query;
174 	struct ECPGtype_information_cache *cache_entry;
175 
176 	if ((stmt->connection->cache_head) == NULL)
177 	{
178 		/*
179 		 * Text like types are not an array for ecpg, but postgres counts them
180 		 * as an array. This define reminds you to not 'correct' these values.
181 		 */
182 #define not_an_array_in_ecpg ECPG_ARRAY_NONE
183 
184 		/* populate cache with well known types to speed things up */
185 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BOOLOID, ECPG_ARRAY_NONE, stmt->lineno))
186 			return (ECPG_ARRAY_ERROR);
187 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BYTEAOID, ECPG_ARRAY_NONE, stmt->lineno))
188 			return (ECPG_ARRAY_ERROR);
189 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CHAROID, ECPG_ARRAY_NONE, stmt->lineno))
190 			return (ECPG_ARRAY_ERROR);
191 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), NAMEOID, not_an_array_in_ecpg, stmt->lineno))
192 			return (ECPG_ARRAY_ERROR);
193 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT8OID, ECPG_ARRAY_NONE, stmt->lineno))
194 			return (ECPG_ARRAY_ERROR);
195 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT2OID, ECPG_ARRAY_NONE, stmt->lineno))
196 			return (ECPG_ARRAY_ERROR);
197 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT2VECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno))
198 			return (ECPG_ARRAY_ERROR);
199 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INT4OID, ECPG_ARRAY_NONE, stmt->lineno))
200 			return (ECPG_ARRAY_ERROR);
201 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), REGPROCOID, ECPG_ARRAY_NONE, stmt->lineno))
202 			return (ECPG_ARRAY_ERROR);
203 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TEXTOID, ECPG_ARRAY_NONE, stmt->lineno))
204 			return (ECPG_ARRAY_ERROR);
205 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), OIDOID, ECPG_ARRAY_NONE, stmt->lineno))
206 			return (ECPG_ARRAY_ERROR);
207 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIDOID, ECPG_ARRAY_NONE, stmt->lineno))
208 			return (ECPG_ARRAY_ERROR);
209 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), XIDOID, ECPG_ARRAY_NONE, stmt->lineno))
210 			return (ECPG_ARRAY_ERROR);
211 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIDOID, ECPG_ARRAY_NONE, stmt->lineno))
212 			return (ECPG_ARRAY_ERROR);
213 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), OIDVECTOROID, ECPG_ARRAY_VECTOR, stmt->lineno))
214 			return (ECPG_ARRAY_ERROR);
215 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), POINTOID, ECPG_ARRAY_VECTOR, stmt->lineno))
216 			return (ECPG_ARRAY_ERROR);
217 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), LSEGOID, ECPG_ARRAY_VECTOR, stmt->lineno))
218 			return (ECPG_ARRAY_ERROR);
219 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), PATHOID, ECPG_ARRAY_NONE, stmt->lineno))
220 			return (ECPG_ARRAY_ERROR);
221 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BOXOID, ECPG_ARRAY_VECTOR, stmt->lineno))
222 			return (ECPG_ARRAY_ERROR);
223 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), POLYGONOID, ECPG_ARRAY_NONE, stmt->lineno))
224 			return (ECPG_ARRAY_ERROR);
225 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), LINEOID, ECPG_ARRAY_VECTOR, stmt->lineno))
226 			return (ECPG_ARRAY_ERROR);
227 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), FLOAT4OID, ECPG_ARRAY_NONE, stmt->lineno))
228 			return (ECPG_ARRAY_ERROR);
229 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), FLOAT8OID, ECPG_ARRAY_NONE, stmt->lineno))
230 			return (ECPG_ARRAY_ERROR);
231 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), ABSTIMEOID, ECPG_ARRAY_NONE, stmt->lineno))
232 			return (ECPG_ARRAY_ERROR);
233 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), RELTIMEOID, ECPG_ARRAY_NONE, stmt->lineno))
234 			return (ECPG_ARRAY_ERROR);
235 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TINTERVALOID, ECPG_ARRAY_NONE, stmt->lineno))
236 			return (ECPG_ARRAY_ERROR);
237 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), UNKNOWNOID, ECPG_ARRAY_NONE, stmt->lineno))
238 			return (ECPG_ARRAY_ERROR);
239 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIRCLEOID, ECPG_ARRAY_NONE, stmt->lineno))
240 			return (ECPG_ARRAY_ERROR);
241 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CASHOID, ECPG_ARRAY_NONE, stmt->lineno))
242 			return (ECPG_ARRAY_ERROR);
243 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INETOID, ECPG_ARRAY_NONE, stmt->lineno))
244 			return (ECPG_ARRAY_ERROR);
245 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), CIDROID, ECPG_ARRAY_NONE, stmt->lineno))
246 			return (ECPG_ARRAY_ERROR);
247 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), BPCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
248 			return (ECPG_ARRAY_ERROR);
249 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), VARCHAROID, ECPG_ARRAY_NONE, stmt->lineno))
250 			return (ECPG_ARRAY_ERROR);
251 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), DATEOID, ECPG_ARRAY_NONE, stmt->lineno))
252 			return (ECPG_ARRAY_ERROR);
253 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMEOID, ECPG_ARRAY_NONE, stmt->lineno))
254 			return (ECPG_ARRAY_ERROR);
255 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMESTAMPOID, ECPG_ARRAY_NONE, stmt->lineno))
256 			return (ECPG_ARRAY_ERROR);
257 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMESTAMPTZOID, ECPG_ARRAY_NONE, stmt->lineno))
258 			return (ECPG_ARRAY_ERROR);
259 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), INTERVALOID, ECPG_ARRAY_NONE, stmt->lineno))
260 			return (ECPG_ARRAY_ERROR);
261 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), TIMETZOID, ECPG_ARRAY_NONE, stmt->lineno))
262 			return (ECPG_ARRAY_ERROR);
263 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), ZPBITOID, ECPG_ARRAY_NONE, stmt->lineno))
264 			return (ECPG_ARRAY_ERROR);
265 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), VARBITOID, ECPG_ARRAY_NONE, stmt->lineno))
266 			return (ECPG_ARRAY_ERROR);
267 		if (!ecpg_type_infocache_push(&(stmt->connection->cache_head), NUMERICOID, ECPG_ARRAY_NONE, stmt->lineno))
268 			return (ECPG_ARRAY_ERROR);
269 	}
270 
271 	for (cache_entry = (stmt->connection->cache_head); cache_entry != NULL; cache_entry = cache_entry->next)
272 	{
273 		if (cache_entry->oid == type)
274 			return cache_entry->isarray;
275 	}
276 
277 	array_query = (char *) ecpg_alloc(strlen("select typlen from pg_type where oid= and typelem<>0") + 11, stmt->lineno);
278 	if (array_query == NULL)
279 		return (ECPG_ARRAY_ERROR);
280 
281 	sprintf(array_query, "select typlen from pg_type where oid=%d and typelem<>0", type);
282 	query = PQexec(stmt->connection->connection, array_query);
283 	ecpg_free(array_query);
284 	if (!ecpg_check_PQresult(query, stmt->lineno, stmt->connection->connection, stmt->compat))
285 		return (ECPG_ARRAY_ERROR);
286 	else if (PQresultStatus(query) == PGRES_TUPLES_OK)
287 	{
288 		if (PQntuples(query) == 0)
289 			isarray = ECPG_ARRAY_NONE;
290 		else
291 		{
292 			isarray = (atol((char *) PQgetvalue(query, 0, 0)) == -1) ? ECPG_ARRAY_ARRAY : ECPG_ARRAY_VECTOR;
293 			if (ecpg_dynamic_type(type) == SQL3_CHARACTER ||
294 				ecpg_dynamic_type(type) == SQL3_CHARACTER_VARYING)
295 			{
296 				/*
297 				 * arrays of character strings are not yet implemented
298 				 */
299 				isarray = ECPG_ARRAY_NONE;
300 			}
301 		}
302 		PQclear(query);
303 	}
304 	else
305 		return (ECPG_ARRAY_ERROR);
306 
307 	ecpg_type_infocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno);
308 	ecpg_log("ecpg_is_type_an_array on line %d: type (%d); C (%d); array (%s)\n", stmt->lineno, type, var->type, ECPG_IS_ARRAY(isarray) ? "yes" : "no");
309 	return isarray;
310 }
311 
312 
313 bool
ecpg_store_result(const PGresult * results,int act_field,const struct statement * stmt,struct variable * var)314 ecpg_store_result(const PGresult *results, int act_field,
315 				  const struct statement *stmt, struct variable *var)
316 {
317 	enum ARRAY_TYPE isarray;
318 	int			act_tuple,
319 				ntuples = PQntuples(results);
320 	bool		status = true;
321 
322 	if ((isarray = ecpg_is_type_an_array(PQftype(results, act_field), stmt, var)) == ECPG_ARRAY_ERROR)
323 	{
324 		ecpg_raise(stmt->lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
325 		return false;
326 	}
327 
328 	if (isarray == ECPG_ARRAY_NONE)
329 	{
330 		/*
331 		 * if we don't have enough space, we cannot read all tuples
332 		 */
333 		if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
334 		{
335 			ecpg_log("ecpg_store_result on line %d: incorrect number of matches; %d don't fit into array of %ld\n",
336 					 stmt->lineno, ntuples, var->arrsize);
337 			ecpg_raise(stmt->lineno, INFORMIX_MODE(stmt->compat) ? ECPG_INFORMIX_SUBSELECT_NOT_ONE : ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL);
338 			return false;
339 		}
340 	}
341 	else
342 	{
343 		/*
344 		 * since we read an array, the variable has to be an array too
345 		 */
346 		if (var->arrsize == 0)
347 		{
348 			ecpg_raise(stmt->lineno, ECPG_NO_ARRAY, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
349 			return false;
350 		}
351 	}
352 
353 	/*
354 	 * allocate memory for NULL pointers
355 	 */
356 	if ((var->arrsize == 0 || var->varcharsize == 0) && var->value == NULL)
357 	{
358 		int			len = 0;
359 
360 		if (!PQfformat(results, act_field))
361 		{
362 			switch (var->type)
363 			{
364 				case ECPGt_char:
365 				case ECPGt_unsigned_char:
366 				case ECPGt_string:
367 					if (!var->varcharsize && !var->arrsize)
368 					{
369 						/* special mode for handling char**foo=0 */
370 						for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
371 							len += strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
372 						len *= var->offset; /* should be 1, but YMNK */
373 						len += (ntuples + 1) * sizeof(char *);
374 					}
375 					else
376 					{
377 						var->varcharsize = 0;
378 						/* check strlen for each tuple */
379 						for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
380 						{
381 							int			len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
382 
383 							if (len > var->varcharsize)
384 								var->varcharsize = len;
385 						}
386 						var->offset *= var->varcharsize;
387 						len = var->offset * ntuples;
388 					}
389 					break;
390 				case ECPGt_varchar:
391 					len = ntuples * (var->varcharsize + sizeof(int));
392 					break;
393 				default:
394 					len = var->offset * ntuples;
395 					break;
396 			}
397 		}
398 		else
399 		{
400 			for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
401 				len += PQgetlength(results, act_tuple, act_field);
402 		}
403 
404 		ecpg_log("ecpg_store_result on line %d: allocating memory for %d tuples\n", stmt->lineno, ntuples);
405 		var->value = (char *) ecpg_auto_alloc(len, stmt->lineno);
406 		if (!var->value)
407 			return false;
408 		*((char **) var->pointer) = var->value;
409 	}
410 
411 	/* allocate indicator variable if needed */
412 	if ((var->ind_arrsize == 0 || var->ind_varcharsize == 0) && var->ind_value == NULL && var->ind_pointer != NULL)
413 	{
414 		int			len = var->ind_offset * ntuples;
415 
416 		var->ind_value = (char *) ecpg_auto_alloc(len, stmt->lineno);
417 		if (!var->ind_value)
418 			return false;
419 		*((char **) var->ind_pointer) = var->ind_value;
420 	}
421 
422 	/* fill the variable with the tuple(s) */
423 	if (!var->varcharsize && !var->arrsize &&
424 		(var->type == ECPGt_char || var->type == ECPGt_unsigned_char || var->type == ECPGt_string))
425 	{
426 		/* special mode for handling char**foo=0 */
427 
428 		/* filling the array of (char*)s */
429 		char	  **current_string = (char **) var->value;
430 
431 		/* storing the data (after the last array element) */
432 		char	   *current_data_location = (char *) &current_string[ntuples + 1];
433 
434 		for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
435 		{
436 			int			len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
437 
438 			if (!ecpg_get_data(results, act_tuple, act_field, stmt->lineno,
439 							   var->type, var->ind_type, current_data_location,
440 							   var->ind_value, len, 0, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
441 				status = false;
442 			else
443 			{
444 				*current_string = current_data_location;
445 				current_data_location += len;
446 				current_string++;
447 			}
448 		}
449 
450 		/* terminate the list */
451 		*current_string = NULL;
452 	}
453 	else
454 	{
455 		for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
456 		{
457 			if (!ecpg_get_data(results, act_tuple, act_field, stmt->lineno,
458 							   var->type, var->ind_type, var->value,
459 							   var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
460 				status = false;
461 		}
462 	}
463 	return status;
464 }
465 
466 static void
sprintf_double_value(char * ptr,double value,const char * delim)467 sprintf_double_value(char *ptr, double value, const char *delim)
468 {
469 	if (isnan(value))
470 		sprintf(ptr, "%s%s", "NaN", delim);
471 	else if (isinf(value))
472 	{
473 		if (value < 0)
474 			sprintf(ptr, "%s%s", "-Infinity", delim);
475 		else
476 			sprintf(ptr, "%s%s", "Infinity", delim);
477 	}
478 	else
479 		sprintf(ptr, "%.15g%s", value, delim);
480 }
481 
482 static void
sprintf_float_value(char * ptr,float value,const char * delim)483 sprintf_float_value(char *ptr, float value, const char *delim)
484 {
485 	if (isnan(value))
486 		sprintf(ptr, "%s%s", "NaN", delim);
487 	else if (isinf(value))
488 	{
489 		if (value < 0)
490 			sprintf(ptr, "%s%s", "-Infinity", delim);
491 		else
492 			sprintf(ptr, "%s%s", "Infinity", delim);
493 	}
494 	else
495 		sprintf(ptr, "%.15g%s", value, delim);
496 }
497 
498 bool
ecpg_store_input(const int lineno,const bool force_indicator,const struct variable * var,char ** tobeinserted_p,bool quote)499 ecpg_store_input(const int lineno, const bool force_indicator, const struct variable *var,
500 				 char **tobeinserted_p, bool quote)
501 {
502 	char	   *mallocedval = NULL;
503 	char	   *newcopy = NULL;
504 
505 	/*
506 	 * arrays are not possible unless the column is an array, too FIXME: we do
507 	 * not know if the column is an array here array input to singleton column
508 	 * will result in a runtime error
509 	 */
510 
511 	/*
512 	 * Some special treatment is needed for records since we want their
513 	 * contents to arrive in a comma-separated list on insert (I think).
514 	 */
515 
516 	*tobeinserted_p = "";
517 
518 	/* check for null value and set input buffer accordingly */
519 	switch (var->ind_type)
520 	{
521 		case ECPGt_short:
522 		case ECPGt_unsigned_short:
523 			if (*(short *) var->ind_value < 0)
524 				*tobeinserted_p = NULL;
525 			break;
526 		case ECPGt_int:
527 		case ECPGt_unsigned_int:
528 			if (*(int *) var->ind_value < 0)
529 				*tobeinserted_p = NULL;
530 			break;
531 		case ECPGt_long:
532 		case ECPGt_unsigned_long:
533 			if (*(long *) var->ind_value < 0L)
534 				*tobeinserted_p = NULL;
535 			break;
536 #ifdef HAVE_LONG_LONG_INT
537 		case ECPGt_long_long:
538 		case ECPGt_unsigned_long_long:
539 			if (*(long long int *) var->ind_value < (long long) 0)
540 				*tobeinserted_p = NULL;
541 			break;
542 #endif							/* HAVE_LONG_LONG_INT */
543 		case ECPGt_NO_INDICATOR:
544 			if (force_indicator == false)
545 			{
546 				if (ECPGis_noind_null(var->type, var->value))
547 					*tobeinserted_p = NULL;
548 			}
549 			break;
550 		default:
551 			break;
552 	}
553 	if (*tobeinserted_p != NULL)
554 	{
555 		int			asize = var->arrsize ? var->arrsize : 1;
556 
557 		switch (var->type)
558 		{
559 				int			element;
560 
561 			case ECPGt_short:
562 				if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
563 					return false;
564 
565 				if (asize > 1)
566 				{
567 					strcpy(mallocedval, "{");
568 
569 					for (element = 0; element < asize; element++)
570 						sprintf(mallocedval + strlen(mallocedval), "%hd,", ((short *) var->value)[element]);
571 
572 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
573 				}
574 				else
575 					sprintf(mallocedval, "%hd", *((short *) var->value));
576 
577 				*tobeinserted_p = mallocedval;
578 				break;
579 
580 			case ECPGt_int:
581 				if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
582 					return false;
583 
584 				if (asize > 1)
585 				{
586 					strcpy(mallocedval, "{");
587 
588 					for (element = 0; element < asize; element++)
589 						sprintf(mallocedval + strlen(mallocedval), "%d,", ((int *) var->value)[element]);
590 
591 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
592 				}
593 				else
594 					sprintf(mallocedval, "%d", *((int *) var->value));
595 
596 				*tobeinserted_p = mallocedval;
597 				break;
598 
599 			case ECPGt_unsigned_short:
600 				if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
601 					return false;
602 
603 				if (asize > 1)
604 				{
605 					strcpy(mallocedval, "{");
606 
607 					for (element = 0; element < asize; element++)
608 						sprintf(mallocedval + strlen(mallocedval), "%hu,", ((unsigned short *) var->value)[element]);
609 
610 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
611 				}
612 				else
613 					sprintf(mallocedval, "%hu", *((unsigned short *) var->value));
614 
615 				*tobeinserted_p = mallocedval;
616 				break;
617 
618 			case ECPGt_unsigned_int:
619 				if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
620 					return false;
621 
622 				if (asize > 1)
623 				{
624 					strcpy(mallocedval, "{");
625 
626 					for (element = 0; element < asize; element++)
627 						sprintf(mallocedval + strlen(mallocedval), "%u,", ((unsigned int *) var->value)[element]);
628 
629 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
630 				}
631 				else
632 					sprintf(mallocedval, "%u", *((unsigned int *) var->value));
633 
634 				*tobeinserted_p = mallocedval;
635 				break;
636 
637 			case ECPGt_long:
638 				if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
639 					return false;
640 
641 				if (asize > 1)
642 				{
643 					strcpy(mallocedval, "{");
644 
645 					for (element = 0; element < asize; element++)
646 						sprintf(mallocedval + strlen(mallocedval), "%ld,", ((long *) var->value)[element]);
647 
648 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
649 				}
650 				else
651 					sprintf(mallocedval, "%ld", *((long *) var->value));
652 
653 				*tobeinserted_p = mallocedval;
654 				break;
655 
656 			case ECPGt_unsigned_long:
657 				if (!(mallocedval = ecpg_alloc(asize * 20, lineno)))
658 					return false;
659 
660 				if (asize > 1)
661 				{
662 					strcpy(mallocedval, "{");
663 
664 					for (element = 0; element < asize; element++)
665 						sprintf(mallocedval + strlen(mallocedval), "%lu,", ((unsigned long *) var->value)[element]);
666 
667 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
668 				}
669 				else
670 					sprintf(mallocedval, "%lu", *((unsigned long *) var->value));
671 
672 				*tobeinserted_p = mallocedval;
673 				break;
674 #ifdef HAVE_LONG_LONG_INT
675 			case ECPGt_long_long:
676 				if (!(mallocedval = ecpg_alloc(asize * 30, lineno)))
677 					return false;
678 
679 				if (asize > 1)
680 				{
681 					strcpy(mallocedval, "{");
682 
683 					for (element = 0; element < asize; element++)
684 						sprintf(mallocedval + strlen(mallocedval), "%lld,", ((long long int *) var->value)[element]);
685 
686 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
687 				}
688 				else
689 					sprintf(mallocedval, "%lld", *((long long int *) var->value));
690 
691 				*tobeinserted_p = mallocedval;
692 				break;
693 
694 			case ECPGt_unsigned_long_long:
695 				if (!(mallocedval = ecpg_alloc(asize * 30, lineno)))
696 					return false;
697 
698 				if (asize > 1)
699 				{
700 					strcpy(mallocedval, "{");
701 
702 					for (element = 0; element < asize; element++)
703 						sprintf(mallocedval + strlen(mallocedval), "%llu,", ((unsigned long long int *) var->value)[element]);
704 
705 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
706 				}
707 				else
708 					sprintf(mallocedval, "%llu", *((unsigned long long int *) var->value));
709 
710 				*tobeinserted_p = mallocedval;
711 				break;
712 #endif							/* HAVE_LONG_LONG_INT */
713 			case ECPGt_float:
714 				if (!(mallocedval = ecpg_alloc(asize * 25, lineno)))
715 					return false;
716 
717 				if (asize > 1)
718 				{
719 					strcpy(mallocedval, "{");
720 
721 					for (element = 0; element < asize; element++)
722 						sprintf_float_value(mallocedval + strlen(mallocedval), ((float *) var->value)[element], ",");
723 
724 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
725 				}
726 				else
727 					sprintf_float_value(mallocedval, *((float *) var->value), "");
728 
729 				*tobeinserted_p = mallocedval;
730 				break;
731 
732 			case ECPGt_double:
733 				if (!(mallocedval = ecpg_alloc(asize * 25, lineno)))
734 					return false;
735 
736 				if (asize > 1)
737 				{
738 					strcpy(mallocedval, "{");
739 
740 					for (element = 0; element < asize; element++)
741 						sprintf_double_value(mallocedval + strlen(mallocedval), ((double *) var->value)[element], ",");
742 
743 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
744 				}
745 				else
746 					sprintf_double_value(mallocedval, *((double *) var->value), "");
747 
748 				*tobeinserted_p = mallocedval;
749 				break;
750 
751 			case ECPGt_bool:
752 				if (!(mallocedval = ecpg_alloc(var->arrsize + sizeof("{}"), lineno)))
753 					return false;
754 
755 				if (var->arrsize > 1)
756 				{
757 					strcpy(mallocedval, "{");
758 
759 					for (element = 0; element < asize; element++)
760 						sprintf(mallocedval + strlen(mallocedval), "%c,", (((bool *) var->value)[element]) ? 't' : 'f');
761 
762 					strcpy(mallocedval + strlen(mallocedval) - 1, "}");
763 				}
764 				else
765 				{
766 					if (var->offset == sizeof(char))
767 						sprintf(mallocedval, "%c", (*((char *) var->value)) ? 't' : 'f');
768 					else if (var->offset == sizeof(int))
769 						sprintf(mallocedval, "%c", (*((int *) var->value)) ? 't' : 'f');
770 					else
771 						ecpg_raise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
772 				}
773 
774 				*tobeinserted_p = mallocedval;
775 				break;
776 
777 			case ECPGt_char:
778 			case ECPGt_unsigned_char:
779 			case ECPGt_string:
780 				{
781 					/* set slen to string length if type is char * */
782 					int			slen = (var->varcharsize == 0) ? strlen((char *) var->value) : (unsigned int) var->varcharsize;
783 
784 					if (!(newcopy = ecpg_alloc(slen + 1, lineno)))
785 						return false;
786 
787 					strncpy(newcopy, (char *) var->value, slen);
788 					newcopy[slen] = '\0';
789 
790 					mallocedval = quote_postgres(newcopy, quote, lineno);
791 					if (!mallocedval)
792 					{
793 						ecpg_free(newcopy);
794 						return false;
795 					}
796 
797 					*tobeinserted_p = mallocedval;
798 				}
799 				break;
800 			case ECPGt_const:
801 			case ECPGt_char_variable:
802 				{
803 					int			slen = strlen((char *) var->value);
804 
805 					if (!(mallocedval = ecpg_alloc(slen + 1, lineno)))
806 						return false;
807 
808 					strncpy(mallocedval, (char *) var->value, slen);
809 					mallocedval[slen] = '\0';
810 
811 					*tobeinserted_p = mallocedval;
812 				}
813 				break;
814 			case ECPGt_varchar:
815 				{
816 					struct ECPGgeneric_varchar *variable =
817 					(struct ECPGgeneric_varchar *) (var->value);
818 
819 					if (!(newcopy = (char *) ecpg_alloc(variable->len + 1, lineno)))
820 						return false;
821 
822 					strncpy(newcopy, variable->arr, variable->len);
823 					newcopy[variable->len] = '\0';
824 
825 					mallocedval = quote_postgres(newcopy, quote, lineno);
826 					if (!mallocedval)
827 					{
828 						ecpg_free(newcopy);
829 						return false;
830 					}
831 
832 					*tobeinserted_p = mallocedval;
833 				}
834 				break;
835 
836 			case ECPGt_decimal:
837 			case ECPGt_numeric:
838 				{
839 					char	   *str = NULL;
840 					int			slen;
841 					numeric    *nval;
842 
843 					if (var->arrsize > 1)
844 						mallocedval = ecpg_strdup("{", lineno);
845 					else
846 						mallocedval = ecpg_strdup("", lineno);
847 
848 					if (!mallocedval)
849 						return false;
850 
851 					for (element = 0; element < asize; element++)
852 					{
853 						int			result;
854 
855 						nval = PGTYPESnumeric_new();
856 						if (!nval)
857 						{
858 							ecpg_free(mallocedval);
859 							return false;
860 						}
861 
862 						if (var->type == ECPGt_numeric)
863 							result = PGTYPESnumeric_copy(&(((numeric *) (var->value))[element]), nval);
864 						else
865 							result = PGTYPESnumeric_from_decimal(&(((decimal *) (var->value))[element]), nval);
866 
867 						if (result != 0)
868 						{
869 							PGTYPESnumeric_free(nval);
870 							ecpg_free(mallocedval);
871 							return false;
872 						}
873 
874 						str = PGTYPESnumeric_to_asc(nval, nval->dscale);
875 						slen = strlen(str);
876 						PGTYPESnumeric_free(nval);
877 
878 						if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
879 						{
880 							ecpg_free(mallocedval);
881 							ecpg_free(str);
882 							return false;
883 						}
884 						mallocedval = newcopy;
885 
886 						/* also copy trailing '\0' */
887 						memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
888 						if (var->arrsize > 1)
889 							strcpy(mallocedval + strlen(mallocedval), ",");
890 
891 						ecpg_free(str);
892 					}
893 
894 					if (var->arrsize > 1)
895 						strcpy(mallocedval + strlen(mallocedval) - 1, "}");
896 
897 					*tobeinserted_p = mallocedval;
898 				}
899 				break;
900 
901 			case ECPGt_interval:
902 				{
903 					char	   *str = NULL;
904 					int			slen;
905 
906 					if (var->arrsize > 1)
907 						mallocedval = ecpg_strdup("{", lineno);
908 					else
909 						mallocedval = ecpg_strdup("", lineno);
910 
911 					if (!mallocedval)
912 						return false;
913 
914 					for (element = 0; element < asize; element++)
915 					{
916 						str = quote_postgres(PGTYPESinterval_to_asc(&(((interval *) (var->value))[element])), quote, lineno);
917 						if (!str)
918 						{
919 							ecpg_free(mallocedval);
920 							return false;
921 						}
922 
923 						slen = strlen(str);
924 
925 						if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
926 						{
927 							ecpg_free(mallocedval);
928 							ecpg_free(str);
929 							return false;
930 						}
931 						mallocedval = newcopy;
932 
933 						/* also copy trailing '\0' */
934 						memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
935 						if (var->arrsize > 1)
936 							strcpy(mallocedval + strlen(mallocedval), ",");
937 
938 						ecpg_free(str);
939 					}
940 
941 					if (var->arrsize > 1)
942 						strcpy(mallocedval + strlen(mallocedval) - 1, "}");
943 
944 					*tobeinserted_p = mallocedval;
945 				}
946 				break;
947 
948 			case ECPGt_date:
949 				{
950 					char	   *str = NULL;
951 					int			slen;
952 
953 					if (var->arrsize > 1)
954 						mallocedval = ecpg_strdup("{", lineno);
955 					else
956 						mallocedval = ecpg_strdup("", lineno);
957 
958 					if (!mallocedval)
959 						return false;
960 
961 					for (element = 0; element < asize; element++)
962 					{
963 						str = quote_postgres(PGTYPESdate_to_asc(((date *) (var->value))[element]), quote, lineno);
964 						if (!str)
965 						{
966 							ecpg_free(mallocedval);
967 							return false;
968 						}
969 
970 						slen = strlen(str);
971 
972 						if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
973 						{
974 							ecpg_free(mallocedval);
975 							ecpg_free(str);
976 							return false;
977 						}
978 						mallocedval = newcopy;
979 
980 						/* also copy trailing '\0' */
981 						memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
982 						if (var->arrsize > 1)
983 							strcpy(mallocedval + strlen(mallocedval), ",");
984 
985 						ecpg_free(str);
986 					}
987 
988 					if (var->arrsize > 1)
989 						strcpy(mallocedval + strlen(mallocedval) - 1, "}");
990 
991 					*tobeinserted_p = mallocedval;
992 				}
993 				break;
994 
995 			case ECPGt_timestamp:
996 				{
997 					char	   *str = NULL;
998 					int			slen;
999 
1000 					if (var->arrsize > 1)
1001 						mallocedval = ecpg_strdup("{", lineno);
1002 					else
1003 						mallocedval = ecpg_strdup("", lineno);
1004 
1005 					if (!mallocedval)
1006 						return false;
1007 
1008 					for (element = 0; element < asize; element++)
1009 					{
1010 						str = quote_postgres(PGTYPEStimestamp_to_asc(((timestamp *) (var->value))[element]), quote, lineno);
1011 						if (!str)
1012 						{
1013 							ecpg_free(mallocedval);
1014 							return false;
1015 						}
1016 
1017 						slen = strlen(str);
1018 
1019 						if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
1020 						{
1021 							ecpg_free(mallocedval);
1022 							ecpg_free(str);
1023 							return false;
1024 						}
1025 						mallocedval = newcopy;
1026 
1027 						/* also copy trailing '\0' */
1028 						memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
1029 						if (var->arrsize > 1)
1030 							strcpy(mallocedval + strlen(mallocedval), ",");
1031 
1032 						ecpg_free(str);
1033 					}
1034 
1035 					if (var->arrsize > 1)
1036 						strcpy(mallocedval + strlen(mallocedval) - 1, "}");
1037 
1038 					*tobeinserted_p = mallocedval;
1039 				}
1040 				break;
1041 
1042 			case ECPGt_descriptor:
1043 			case ECPGt_sqlda:
1044 				break;
1045 
1046 			default:
1047 				/* Not implemented yet */
1048 				ecpg_raise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ecpg_type_name(var->type));
1049 				return false;
1050 				break;
1051 		}
1052 	}
1053 	return true;
1054 }
1055 
1056 void
ecpg_free_params(struct statement * stmt,bool print)1057 ecpg_free_params(struct statement *stmt, bool print)
1058 {
1059 	int			n;
1060 
1061 	for (n = 0; n < stmt->nparams; n++)
1062 	{
1063 		if (print)
1064 			ecpg_log("ecpg_free_params on line %d: parameter %d = %s\n", stmt->lineno, n + 1, stmt->paramvalues[n] ? stmt->paramvalues[n] : "null");
1065 		ecpg_free(stmt->paramvalues[n]);
1066 	}
1067 	ecpg_free(stmt->paramvalues);
1068 	stmt->paramvalues = NULL;
1069 	stmt->nparams = 0;
1070 }
1071 
1072 static bool
insert_tobeinserted(int position,int ph_len,struct statement * stmt,char * tobeinserted)1073 insert_tobeinserted(int position, int ph_len, struct statement *stmt, char *tobeinserted)
1074 {
1075 	char	   *newcopy;
1076 
1077 	if (!(newcopy = (char *) ecpg_alloc(strlen(stmt->command)
1078 										+ strlen(tobeinserted)
1079 										+ 1, stmt->lineno)))
1080 	{
1081 		ecpg_free(tobeinserted);
1082 		return false;
1083 	}
1084 
1085 	strcpy(newcopy, stmt->command);
1086 	strcpy(newcopy + position - 1, tobeinserted);
1087 
1088 	/*
1089 	 * The strange thing in the second argument is the rest of the string from
1090 	 * the old string
1091 	 */
1092 	strcat(newcopy,
1093 		   stmt->command
1094 		   + position
1095 		   + ph_len - 1);
1096 
1097 	ecpg_free(stmt->command);
1098 	stmt->command = newcopy;
1099 
1100 	ecpg_free((char *) tobeinserted);
1101 	return true;
1102 }
1103 
1104 /*
1105  * ecpg_build_params
1106  *		Build statement parameters
1107  *
1108  * The input values are taken from user variables, and the results are stored
1109  * in arrays which can be used by PQexecParams().
1110  */
1111 bool
ecpg_build_params(struct statement * stmt)1112 ecpg_build_params(struct statement *stmt)
1113 {
1114 	struct variable *var;
1115 	int			desc_counter = 0;
1116 	int			position = 0;
1117 	const char	   *value;
1118 	bool		std_strings = false;
1119 
1120 	/* Get standard_conforming_strings setting. */
1121 	value = PQparameterStatus(stmt->connection->connection, "standard_conforming_strings");
1122 	if (value && strcmp(value, "on") == 0)
1123 		std_strings = true;
1124 
1125 	/*
1126 	 * If the type is one of the fill in types then we take the argument and
1127 	 * enter it to our parameter array at the first position. Then if there
1128 	 * are any more fill in types we add more parameters.
1129 	 */
1130 	var = stmt->inlist;
1131 	while (var)
1132 	{
1133 		char	   *tobeinserted;
1134 		int			counter = 1;
1135 
1136 		tobeinserted = NULL;
1137 
1138 		/*
1139 		 * A descriptor is a special case since it contains many variables but
1140 		 * is listed only once.
1141 		 */
1142 		if (var->type == ECPGt_descriptor)
1143 		{
1144 			/*
1145 			 * We create an additional variable list here, so the same logic
1146 			 * applies.
1147 			 */
1148 			struct variable desc_inlist;
1149 			struct descriptor *desc;
1150 			struct descriptor_item *desc_item;
1151 
1152 			desc = ecpg_find_desc(stmt->lineno, var->pointer);
1153 			if (desc == NULL)
1154 				return false;
1155 
1156 			desc_counter++;
1157 			for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
1158 			{
1159 				if (desc_item->num == desc_counter)
1160 				{
1161 					desc_inlist.type = ECPGt_char;
1162 					desc_inlist.value = desc_item->data;
1163 					desc_inlist.pointer = &(desc_item->data);
1164 					desc_inlist.varcharsize = strlen(desc_item->data);
1165 					desc_inlist.arrsize = 1;
1166 					desc_inlist.offset = 0;
1167 					if (!desc_item->indicator)
1168 					{
1169 						desc_inlist.ind_type = ECPGt_NO_INDICATOR;
1170 						desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
1171 						desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
1172 					}
1173 					else
1174 					{
1175 						desc_inlist.ind_type = ECPGt_int;
1176 						desc_inlist.ind_value = &(desc_item->indicator);
1177 						desc_inlist.ind_pointer = &(desc_inlist.ind_value);
1178 						desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
1179 						desc_inlist.ind_offset = 0;
1180 					}
1181 					if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
1182 						return false;
1183 
1184 					break;
1185 				}
1186 			}
1187 			if (desc->count == desc_counter)
1188 				desc_counter = 0;
1189 		}
1190 		else if (var->type == ECPGt_sqlda)
1191 		{
1192 			if (INFORMIX_MODE(stmt->compat))
1193 			{
1194 				struct sqlda_compat *sqlda = *(struct sqlda_compat **) var->pointer;
1195 				struct variable desc_inlist;
1196 				int			i;
1197 
1198 				if (sqlda == NULL)
1199 					return false;
1200 
1201 				desc_counter++;
1202 				for (i = 0; i < sqlda->sqld; i++)
1203 				{
1204 					if (i + 1 == desc_counter)
1205 					{
1206 						desc_inlist.type = sqlda->sqlvar[i].sqltype;
1207 						desc_inlist.value = sqlda->sqlvar[i].sqldata;
1208 						desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
1209 						switch (desc_inlist.type)
1210 						{
1211 							case ECPGt_char:
1212 							case ECPGt_varchar:
1213 								desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
1214 								break;
1215 							default:
1216 								desc_inlist.varcharsize = 0;
1217 								break;
1218 						}
1219 						desc_inlist.arrsize = 1;
1220 						desc_inlist.offset = 0;
1221 						if (sqlda->sqlvar[i].sqlind)
1222 						{
1223 							desc_inlist.ind_type = ECPGt_short;
1224 							/* ECPG expects indicator value < 0 */
1225 							if (*(sqlda->sqlvar[i].sqlind))
1226 								*(sqlda->sqlvar[i].sqlind) = -1;
1227 							desc_inlist.ind_value = sqlda->sqlvar[i].sqlind;
1228 							desc_inlist.ind_pointer = &(sqlda->sqlvar[i].sqlind);
1229 							desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
1230 							desc_inlist.ind_offset = 0;
1231 						}
1232 						else
1233 						{
1234 							desc_inlist.ind_type = ECPGt_NO_INDICATOR;
1235 							desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
1236 							desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
1237 						}
1238 						if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
1239 							return false;
1240 
1241 						break;
1242 					}
1243 				}
1244 				if (sqlda->sqld == desc_counter)
1245 					desc_counter = 0;
1246 			}
1247 			else
1248 			{
1249 				struct sqlda_struct *sqlda = *(struct sqlda_struct **) var->pointer;
1250 				struct variable desc_inlist;
1251 				int			i;
1252 
1253 				if (sqlda == NULL)
1254 					return false;
1255 
1256 				desc_counter++;
1257 				for (i = 0; i < sqlda->sqln; i++)
1258 				{
1259 					if (i + 1 == desc_counter)
1260 					{
1261 						desc_inlist.type = sqlda->sqlvar[i].sqltype;
1262 						desc_inlist.value = sqlda->sqlvar[i].sqldata;
1263 						desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
1264 						switch (desc_inlist.type)
1265 						{
1266 							case ECPGt_char:
1267 							case ECPGt_varchar:
1268 								desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
1269 								break;
1270 							default:
1271 								desc_inlist.varcharsize = 0;
1272 								break;
1273 						}
1274 						desc_inlist.arrsize = 1;
1275 						desc_inlist.offset = 0;
1276 						if (sqlda->sqlvar[i].sqlind)
1277 						{
1278 							desc_inlist.ind_type = ECPGt_short;
1279 							/* ECPG expects indicator value < 0 */
1280 							if (*(sqlda->sqlvar[i].sqlind))
1281 								*(sqlda->sqlvar[i].sqlind) = -1;
1282 							desc_inlist.ind_value = sqlda->sqlvar[i].sqlind;
1283 							desc_inlist.ind_pointer = &(sqlda->sqlvar[i].sqlind);
1284 							desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
1285 							desc_inlist.ind_offset = 0;
1286 						}
1287 						else
1288 						{
1289 							desc_inlist.ind_type = ECPGt_NO_INDICATOR;
1290 							desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
1291 							desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
1292 						}
1293 						if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
1294 							return false;
1295 
1296 						break;
1297 					}
1298 				}
1299 				if (sqlda->sqln == desc_counter)
1300 					desc_counter = 0;
1301 			}
1302 
1303 		}
1304 		else
1305 		{
1306 			if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false))
1307 				return false;
1308 		}
1309 
1310 		/*
1311 		 * now tobeinserted points to an area that contains the next
1312 		 * parameter; now find the position in the string where it belongs
1313 		 */
1314 		if ((position = next_insert(stmt->command, position, stmt->questionmarks, std_strings) + 1) == 0)
1315 		{
1316 			/*
1317 			 * We have an argument but we don't have the matched up
1318 			 * placeholder in the string
1319 			 */
1320 			ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
1321 					   ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
1322 					   NULL);
1323 			ecpg_free_params(stmt, false);
1324 			return false;
1325 		}
1326 
1327 		/*
1328 		 * if var->type=ECPGt_char_variable we have a dynamic cursor we have
1329 		 * to simulate a dynamic cursor because there is no backend
1330 		 * functionality for it
1331 		 */
1332 		if (var->type == ECPGt_char_variable)
1333 		{
1334 			int			ph_len = (stmt->command[position] == '?') ? strlen("?") : strlen("$1");
1335 
1336 			if (!insert_tobeinserted(position, ph_len, stmt, tobeinserted))
1337 			{
1338 				ecpg_free_params(stmt, false);
1339 				return false;
1340 			}
1341 			tobeinserted = NULL;
1342 		}
1343 
1344 		/*
1345 		 * if the placeholder is '$0' we have to replace it on the client side
1346 		 * this is for places we want to support variables at that are not
1347 		 * supported in the backend
1348 		 */
1349 		else if (stmt->command[position] == '0')
1350 		{
1351 			if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
1352 			{
1353 				ecpg_free_params(stmt, false);
1354 				return false;
1355 			}
1356 			tobeinserted = NULL;
1357 		}
1358 		else
1359 		{
1360 			char	  **paramvalues;
1361 
1362 			if (!(paramvalues = (char **) ecpg_realloc(stmt->paramvalues, sizeof(char *) * (stmt->nparams + 1), stmt->lineno)))
1363 			{
1364 				ecpg_free_params(stmt, false);
1365 				return false;
1366 			}
1367 
1368 			stmt->nparams++;
1369 			stmt->paramvalues = paramvalues;
1370 			stmt->paramvalues[stmt->nparams - 1] = tobeinserted;
1371 
1372 			/* let's see if this was an old style placeholder */
1373 			if (stmt->command[position] == '?')
1374 			{
1375 				/* yes, replace with new style */
1376 				int			buffersize = sizeof(int) * CHAR_BIT * 10 / 3;	/* a rough guess of the
1377 																			 * size we need */
1378 
1379 				if (!(tobeinserted = (char *) ecpg_alloc(buffersize, stmt->lineno)))
1380 				{
1381 					ecpg_free_params(stmt, false);
1382 					return false;
1383 				}
1384 
1385 				snprintf(tobeinserted, buffersize, "$%d", counter++);
1386 
1387 				if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
1388 				{
1389 					ecpg_free_params(stmt, false);
1390 					return false;
1391 				}
1392 				tobeinserted = NULL;
1393 			}
1394 		}
1395 
1396 		if (desc_counter == 0)
1397 			var = var->next;
1398 	}
1399 
1400 	/* Check if there are unmatched things left. */
1401 	if (next_insert(stmt->command, position, stmt->questionmarks, std_strings) >= 0)
1402 	{
1403 		ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS,
1404 				   ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
1405 		ecpg_free_params(stmt, false);
1406 		return false;
1407 	}
1408 
1409 	return true;
1410 }
1411 
1412 /*
1413  * ecpg_autostart_transaction
1414  *		If we are in non-autocommit mode, automatically start a transaction.
1415  */
1416 bool
ecpg_autostart_transaction(struct statement * stmt)1417 ecpg_autostart_transaction(struct statement *stmt)
1418 {
1419 	if (PQtransactionStatus(stmt->connection->connection) == PQTRANS_IDLE && !stmt->connection->autocommit)
1420 	{
1421 		stmt->results = PQexec(stmt->connection->connection, "begin transaction");
1422 		if (!ecpg_check_PQresult(stmt->results, stmt->lineno, stmt->connection->connection, stmt->compat))
1423 		{
1424 			ecpg_free_params(stmt, false);
1425 			return false;
1426 		}
1427 		PQclear(stmt->results);
1428 		stmt->results = NULL;
1429 	}
1430 	return true;
1431 }
1432 
1433 /*
1434  * ecpg_execute
1435  *		Execute the SQL statement.
1436  */
1437 bool
ecpg_execute(struct statement * stmt)1438 ecpg_execute(struct statement *stmt)
1439 {
1440 	ecpg_log("ecpg_execute on line %d: query: %s; with %d parameter(s) on connection %s\n", stmt->lineno, stmt->command, stmt->nparams, stmt->connection->name);
1441 	if (stmt->statement_type == ECPGst_execute)
1442 	{
1443 		stmt->results = PQexecPrepared(stmt->connection->connection, stmt->name, stmt->nparams, (const char *const *) stmt->paramvalues, NULL, NULL, 0);
1444 		ecpg_log("ecpg_execute on line %d: using PQexecPrepared for \"%s\"\n", stmt->lineno, stmt->command);
1445 	}
1446 	else
1447 	{
1448 		if (stmt->nparams == 0)
1449 		{
1450 			stmt->results = PQexec(stmt->connection->connection, stmt->command);
1451 			ecpg_log("ecpg_execute on line %d: using PQexec\n", stmt->lineno);
1452 		}
1453 		else
1454 		{
1455 			stmt->results = PQexecParams(stmt->connection->connection, stmt->command, stmt->nparams, NULL, (const char *const *) stmt->paramvalues, NULL, NULL, 0);
1456 			ecpg_log("ecpg_execute on line %d: using PQexecParams\n", stmt->lineno);
1457 		}
1458 	}
1459 
1460 	ecpg_free_params(stmt, true);
1461 
1462 	if (!ecpg_check_PQresult(stmt->results, stmt->lineno, stmt->connection->connection, stmt->compat))
1463 		return false;
1464 
1465 	return true;
1466 }
1467 
1468 /*-------
1469  * ecpg_process_output
1470  *
1471  *	Process the statement result and store it into application variables.  This
1472  *	function can be called repeatedly during the same statement in case cursor
1473  *	readahead is used and the application does FETCH N which overflows the
1474  *	readahead window.
1475  *
1476  * Parameters
1477  *	stmt	statement structure holding the PGresult and
1478  *			the list of output variables
1479  *	clear_result
1480  *			PQclear() the result upon returning from this function
1481  *
1482  * Returns success as boolean. Also an SQL error is raised in case of failure.
1483  *-------
1484  */
1485 bool
ecpg_process_output(struct statement * stmt,bool clear_result)1486 ecpg_process_output(struct statement *stmt, bool clear_result)
1487 {
1488 	struct variable *var;
1489 	bool		status = false;
1490 	char	   *cmdstat;
1491 	PGnotify   *notify;
1492 	struct sqlca_t *sqlca = ECPGget_sqlca();
1493 	int			nfields,
1494 				ntuples,
1495 				act_field;
1496 
1497 	if (sqlca == NULL)
1498 	{
1499 		ecpg_raise(stmt->lineno, ECPG_OUT_OF_MEMORY,
1500 				   ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
1501 		return (false);
1502 	}
1503 
1504 	var = stmt->outlist;
1505 	switch (PQresultStatus(stmt->results))
1506 	{
1507 		case PGRES_TUPLES_OK:
1508 			nfields = PQnfields(stmt->results);
1509 			sqlca->sqlerrd[2] = ntuples = PQntuples(stmt->results);
1510 
1511 			ecpg_log("ecpg_process_output on line %d: correctly got %d tuples with %d fields\n", stmt->lineno, ntuples, nfields);
1512 			status = true;
1513 
1514 			if (ntuples < 1)
1515 			{
1516 				if (ntuples)
1517 					ecpg_log("ecpg_process_output on line %d: incorrect number of matches (%d)\n",
1518 							 stmt->lineno, ntuples);
1519 				ecpg_raise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
1520 				status = false;
1521 				break;
1522 			}
1523 
1524 			if (var != NULL && var->type == ECPGt_descriptor)
1525 			{
1526 				struct descriptor *desc = ecpg_find_desc(stmt->lineno, var->pointer);
1527 
1528 				if (desc == NULL)
1529 					status = false;
1530 				else
1531 				{
1532 					if (desc->result)
1533 						PQclear(desc->result);
1534 					desc->result = stmt->results;
1535 					clear_result = false;
1536 					ecpg_log("ecpg_process_output on line %d: putting result (%d tuples) into descriptor %s\n",
1537 							 stmt->lineno, PQntuples(stmt->results), (const char *) var->pointer);
1538 				}
1539 				var = var->next;
1540 			}
1541 			else if (var != NULL && var->type == ECPGt_sqlda)
1542 			{
1543 				if (INFORMIX_MODE(stmt->compat))
1544 				{
1545 					struct sqlda_compat **_sqlda = (struct sqlda_compat **) var->pointer;
1546 					struct sqlda_compat *sqlda = *_sqlda;
1547 					struct sqlda_compat *sqlda_new;
1548 					int			i;
1549 
1550 					/*
1551 					 * If we are passed in a previously existing sqlda (chain)
1552 					 * then free it.
1553 					 */
1554 					while (sqlda)
1555 					{
1556 						sqlda_new = sqlda->desc_next;
1557 						free(sqlda);
1558 						sqlda = sqlda_new;
1559 					}
1560 					*_sqlda = sqlda = sqlda_new = NULL;
1561 					for (i = ntuples - 1; i >= 0; i--)
1562 					{
1563 						/*
1564 						 * Build a new sqlda structure. Note that only
1565 						 * fetching 1 record is supported
1566 						 */
1567 						sqlda_new = ecpg_build_compat_sqlda(stmt->lineno, stmt->results, i, stmt->compat);
1568 
1569 						if (!sqlda_new)
1570 						{
1571 							/* cleanup all SQLDAs we created up */
1572 							while (sqlda)
1573 							{
1574 								sqlda_new = sqlda->desc_next;
1575 								free(sqlda);
1576 								sqlda = sqlda_new;
1577 							}
1578 							*_sqlda = NULL;
1579 
1580 							ecpg_log("ecpg_process_output on line %d: out of memory allocating a new sqlda\n", stmt->lineno);
1581 							status = false;
1582 							break;
1583 						}
1584 						else
1585 						{
1586 							ecpg_log("ecpg_process_output on line %d: new sqlda was built\n", stmt->lineno);
1587 
1588 							*_sqlda = sqlda_new;
1589 
1590 							ecpg_set_compat_sqlda(stmt->lineno, _sqlda, stmt->results, i, stmt->compat);
1591 							ecpg_log("ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
1592 									 stmt->lineno, PQnfields(stmt->results));
1593 
1594 							sqlda_new->desc_next = sqlda;
1595 							sqlda = sqlda_new;
1596 						}
1597 					}
1598 				}
1599 				else
1600 				{
1601 					struct sqlda_struct **_sqlda = (struct sqlda_struct **) var->pointer;
1602 					struct sqlda_struct *sqlda = *_sqlda;
1603 					struct sqlda_struct *sqlda_new;
1604 					int			i;
1605 
1606 					/*
1607 					 * If we are passed in a previously existing sqlda (chain)
1608 					 * then free it.
1609 					 */
1610 					while (sqlda)
1611 					{
1612 						sqlda_new = sqlda->desc_next;
1613 						free(sqlda);
1614 						sqlda = sqlda_new;
1615 					}
1616 					*_sqlda = sqlda = sqlda_new = NULL;
1617 					for (i = ntuples - 1; i >= 0; i--)
1618 					{
1619 						/*
1620 						 * Build a new sqlda structure. Note that only
1621 						 * fetching 1 record is supported
1622 						 */
1623 						sqlda_new = ecpg_build_native_sqlda(stmt->lineno, stmt->results, i, stmt->compat);
1624 
1625 						if (!sqlda_new)
1626 						{
1627 							/* cleanup all SQLDAs we created up */
1628 							while (sqlda)
1629 							{
1630 								sqlda_new = sqlda->desc_next;
1631 								free(sqlda);
1632 								sqlda = sqlda_new;
1633 							}
1634 							*_sqlda = NULL;
1635 
1636 							ecpg_log("ecpg_process_output on line %d: out of memory allocating a new sqlda\n", stmt->lineno);
1637 							status = false;
1638 							break;
1639 						}
1640 						else
1641 						{
1642 							ecpg_log("ecpg_process_output on line %d: new sqlda was built\n", stmt->lineno);
1643 
1644 							*_sqlda = sqlda_new;
1645 
1646 							ecpg_set_native_sqlda(stmt->lineno, _sqlda, stmt->results, i, stmt->compat);
1647 							ecpg_log("ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
1648 									 stmt->lineno, PQnfields(stmt->results));
1649 
1650 							sqlda_new->desc_next = sqlda;
1651 							sqlda = sqlda_new;
1652 						}
1653 					}
1654 				}
1655 
1656 				var = var->next;
1657 			}
1658 			else
1659 				for (act_field = 0; act_field < nfields && status; act_field++)
1660 				{
1661 					if (var != NULL)
1662 					{
1663 						status = ecpg_store_result(stmt->results, act_field, stmt, var);
1664 						var = var->next;
1665 					}
1666 					else if (!INFORMIX_MODE(stmt->compat))
1667 					{
1668 						ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
1669 						return (false);
1670 					}
1671 				}
1672 
1673 			if (status && var != NULL)
1674 			{
1675 				ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
1676 				status = false;
1677 			}
1678 
1679 			break;
1680 		case PGRES_COMMAND_OK:
1681 			status = true;
1682 			cmdstat = PQcmdStatus(stmt->results);
1683 			sqlca->sqlerrd[1] = PQoidValue(stmt->results);
1684 			sqlca->sqlerrd[2] = atol(PQcmdTuples(stmt->results));
1685 			ecpg_log("ecpg_process_output on line %d: OK: %s\n", stmt->lineno, cmdstat);
1686 			if (stmt->compat != ECPG_COMPAT_INFORMIX_SE &&
1687 				!sqlca->sqlerrd[2] &&
1688 				(strncmp(cmdstat, "UPDATE", 6) == 0
1689 				 || strncmp(cmdstat, "INSERT", 6) == 0
1690 				 || strncmp(cmdstat, "DELETE", 6) == 0))
1691 				ecpg_raise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
1692 			break;
1693 		case PGRES_COPY_OUT:
1694 			{
1695 				char	   *buffer;
1696 				int			res;
1697 
1698 				ecpg_log("ecpg_process_output on line %d: COPY OUT data transfer in progress\n", stmt->lineno);
1699 				while ((res = PQgetCopyData(stmt->connection->connection,
1700 											&buffer, 0)) > 0)
1701 				{
1702 					printf("%s", buffer);
1703 					PQfreemem(buffer);
1704 				}
1705 				if (res == -1)
1706 				{
1707 					/* COPY done */
1708 					PQclear(stmt->results);
1709 					stmt->results = PQgetResult(stmt->connection->connection);
1710 					if (PQresultStatus(stmt->results) == PGRES_COMMAND_OK)
1711 						ecpg_log("ecpg_process_output on line %d: got PGRES_COMMAND_OK after PGRES_COPY_OUT\n", stmt->lineno);
1712 					else
1713 						ecpg_log("ecpg_process_output on line %d: got error after PGRES_COPY_OUT: %s", stmt->lineno, PQresultErrorMessage(stmt->results));
1714 				}
1715 				break;
1716 			}
1717 		default:
1718 
1719 			/*
1720 			 * execution should never reach this code because it is already
1721 			 * handled in ECPGcheck_PQresult()
1722 			 */
1723 			ecpg_log("ecpg_process_output on line %d: unknown execution status type\n",
1724 					 stmt->lineno);
1725 			ecpg_raise_backend(stmt->lineno, stmt->results, stmt->connection->connection, stmt->compat);
1726 			status = false;
1727 			break;
1728 	}
1729 
1730 	if (clear_result)
1731 	{
1732 		PQclear(stmt->results);
1733 		stmt->results = NULL;
1734 	}
1735 
1736 	/* check for asynchronous returns */
1737 	PQconsumeInput(stmt->connection->connection);
1738 	while ((notify = PQnotifies(stmt->connection->connection)) != NULL)
1739 	{
1740 		ecpg_log("ecpg_process_output on line %d: asynchronous notification of \"%s\" from backend PID %d received\n",
1741 				 stmt->lineno, notify->relname, notify->be_pid);
1742 		PQfreemem(notify);
1743 		PQconsumeInput(stmt->connection->connection);
1744 	}
1745 
1746 	return status;
1747 }
1748 
1749 /*
1750  * ecpg_do_prologue
1751  *
1752  * Initialize various infrastructure elements for executing the statement:
1753  *
1754  *	- create the statement structure
1755  *	- set the C numeric locale for communicating with the backend
1756  *	- preprocess the variable list of input/output parameters into
1757  *	  linked lists
1758  */
1759 bool
ecpg_do_prologue(int lineno,const int compat,const int force_indicator,const char * connection_name,const bool questionmarks,enum ECPG_statement_type statement_type,const char * query,va_list args,struct statement ** stmt_out)1760 ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
1761 				 const char *connection_name, const bool questionmarks,
1762 				 enum ECPG_statement_type statement_type, const char *query,
1763 				 va_list args, struct statement **stmt_out)
1764 {
1765 	struct statement *stmt;
1766 	struct connection *con;
1767 	enum ECPGttype type;
1768 	struct variable **list;
1769 	char	   *prepname;
1770 
1771 	*stmt_out = NULL;
1772 
1773 	if (!query)
1774 	{
1775 		ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
1776 		return false;
1777 	}
1778 
1779 	stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
1780 
1781 	if (stmt == NULL)
1782 		return false;
1783 
1784 	/*
1785 	 * Make sure we do NOT honor the locale for numeric input/output since the
1786 	 * database wants the standard decimal point.  If available, use
1787 	 * uselocale() for this because it's thread-safe.  Windows doesn't have
1788 	 * that, but it usually does have _configthreadlocale().  In some versions
1789 	 * of MinGW, _configthreadlocale() exists but always returns -1 --- so
1790 	 * treat that situation as if the function doesn't exist.
1791 	 */
1792 #ifdef HAVE_USELOCALE
1793 	stmt->clocale = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
1794 	if (stmt->clocale == (locale_t) 0)
1795 	{
1796 		ecpg_do_epilogue(stmt);
1797 		return false;
1798 	}
1799 	stmt->oldlocale = uselocale(stmt->clocale);
1800 	if (stmt->oldlocale == (locale_t) 0)
1801 	{
1802 		ecpg_do_epilogue(stmt);
1803 		return false;
1804 	}
1805 #else
1806 #ifdef HAVE__CONFIGTHREADLOCALE
1807 	stmt->oldthreadlocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
1808 #endif
1809 	stmt->oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
1810 	if (stmt->oldlocale == NULL)
1811 	{
1812 		ecpg_do_epilogue(stmt);
1813 		return false;
1814 	}
1815 	setlocale(LC_NUMERIC, "C");
1816 #endif
1817 
1818 #ifdef ENABLE_THREAD_SAFETY
1819 	ecpg_pthreads_init();
1820 #endif
1821 
1822 	con = ecpg_get_connection(connection_name);
1823 
1824 	if (!ecpg_init(con, connection_name, lineno))
1825 	{
1826 		ecpg_do_epilogue(stmt);
1827 		return false;
1828 	}
1829 
1830 	/*
1831 	 * If statement type is ECPGst_prepnormal we are supposed to prepare the
1832 	 * statement before executing them
1833 	 */
1834 	if (statement_type == ECPGst_prepnormal)
1835 	{
1836 		if (!ecpg_auto_prepare(lineno, connection_name, compat, &prepname, query))
1837 		{
1838 			ecpg_do_epilogue(stmt);
1839 			return false;
1840 		}
1841 
1842 		/*
1843 		 * statement is now prepared, so instead of the query we have to
1844 		 * execute the name
1845 		 */
1846 		stmt->command = prepname;
1847 		statement_type = ECPGst_execute;
1848 	}
1849 	else
1850 		stmt->command = ecpg_strdup(query, lineno);
1851 
1852 	stmt->name = NULL;
1853 
1854 	if (statement_type == ECPGst_execute)
1855 	{
1856 		/* if we have an EXECUTE command, only the name is send */
1857 		char	   *command = ecpg_prepared(stmt->command, con);
1858 
1859 		if (command)
1860 		{
1861 			stmt->name = stmt->command;
1862 			stmt->command = ecpg_strdup(command, lineno);
1863 		}
1864 		else
1865 		{
1866 			ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt->command);
1867 			ecpg_do_epilogue(stmt);
1868 			return (false);
1869 		}
1870 	}
1871 
1872 	stmt->connection = con;
1873 	stmt->lineno = lineno;
1874 	stmt->compat = compat;
1875 	stmt->force_indicator = force_indicator;
1876 	stmt->questionmarks = questionmarks;
1877 	stmt->statement_type = statement_type;
1878 
1879 	/*------
1880 	 * create a list of variables
1881 	 *
1882 	 * The variables are listed with input variables preceding outputvariables
1883 	 * The end of each group is marked by an end marker. per variable we list:
1884 	 *
1885 	 * type - as defined in ecpgtype.h
1886 	 * value - where to store the data
1887 	 * varcharsize - length of string in case we have a stringvariable, else 0
1888 	 * arraysize - 0 for pointer (we don't know the size of the array), 1 for
1889 	 * simple variable, size for arrays
1890 	 * offset - offset between ith and (i+1)th entry in an array, normally
1891 	 * that means sizeof(type)
1892 	 * ind_type - type of indicator variable
1893 	 * ind_value - pointer to indicator variable
1894 	 * ind_varcharsize - empty
1895 	 * ind_arraysize - arraysize of indicator array
1896 	 * ind_offset - indicator offset
1897 	 *------
1898 	 */
1899 
1900 	list = &(stmt->inlist);
1901 
1902 	type = va_arg(args, enum ECPGttype);
1903 
1904 	while (type != ECPGt_EORT)
1905 	{
1906 		if (type == ECPGt_EOIT)
1907 			list = &(stmt->outlist);
1908 		else
1909 		{
1910 			struct variable *var,
1911 					   *ptr;
1912 
1913 			if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
1914 			{
1915 				ecpg_do_epilogue(stmt);
1916 				return false;
1917 			}
1918 
1919 			var->type = type;
1920 			var->pointer = va_arg(args, char *);
1921 
1922 			var->varcharsize = va_arg(args, long);
1923 			var->arrsize = va_arg(args, long);
1924 			var->offset = va_arg(args, long);
1925 
1926 			/*
1927 			 * Unknown array size means pointer to an array. Unknown
1928 			 * varcharsize usually also means pointer. But if the type is
1929 			 * character and the array size is known, it is an array of
1930 			 * pointers to char, so use var->pointer as it is.
1931 			 */
1932 			if (var->arrsize == 0 ||
1933 				(var->varcharsize == 0 && ((var->type != ECPGt_char && var->type != ECPGt_unsigned_char) || (var->arrsize <= 1))))
1934 				var->value = *((char **) (var->pointer));
1935 			else
1936 				var->value = var->pointer;
1937 
1938 			/*
1939 			 * negative values are used to indicate an array without given
1940 			 * bounds
1941 			 */
1942 			/* reset to zero for us */
1943 			if (var->arrsize < 0)
1944 				var->arrsize = 0;
1945 			if (var->varcharsize < 0)
1946 				var->varcharsize = 0;
1947 
1948 			var->next = NULL;
1949 
1950 			var->ind_type = va_arg(args, enum ECPGttype);
1951 			var->ind_pointer = va_arg(args, char *);
1952 			var->ind_varcharsize = va_arg(args, long);
1953 			var->ind_arrsize = va_arg(args, long);
1954 			var->ind_offset = va_arg(args, long);
1955 
1956 			if (var->ind_type != ECPGt_NO_INDICATOR
1957 				&& (var->ind_arrsize == 0 || var->ind_varcharsize == 0))
1958 				var->ind_value = *((char **) (var->ind_pointer));
1959 			else
1960 				var->ind_value = var->ind_pointer;
1961 
1962 			/*
1963 			 * negative values are used to indicate an array without given
1964 			 * bounds
1965 			 */
1966 			/* reset to zero for us */
1967 			if (var->ind_arrsize < 0)
1968 				var->ind_arrsize = 0;
1969 			if (var->ind_varcharsize < 0)
1970 				var->ind_varcharsize = 0;
1971 
1972 			/* if variable is NULL, the statement hasn't been prepared */
1973 			if (var->pointer == NULL)
1974 			{
1975 				ecpg_raise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, NULL);
1976 				ecpg_free(var);
1977 				ecpg_do_epilogue(stmt);
1978 				return false;
1979 			}
1980 
1981 			for (ptr = *list; ptr && ptr->next; ptr = ptr->next)
1982 				;
1983 
1984 			if (ptr == NULL)
1985 				*list = var;
1986 			else
1987 				ptr->next = var;
1988 		}
1989 
1990 		type = va_arg(args, enum ECPGttype);
1991 	}
1992 
1993 	/* are we connected? */
1994 	if (con == NULL || con->connection == NULL)
1995 	{
1996 		ecpg_raise(lineno, ECPG_NOT_CONN, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (con) ? con->name : ecpg_gettext("<empty>"));
1997 		ecpg_do_epilogue(stmt);
1998 		return false;
1999 	}
2000 
2001 	/* initialize auto_mem struct */
2002 	ecpg_clear_auto_mem();
2003 
2004 	*stmt_out = stmt;
2005 
2006 	return true;
2007 }
2008 
2009 /*
2010  * ecpg_do_epilogue
2011  *	  Restore the application locale and free the statement structure.
2012  */
2013 void
ecpg_do_epilogue(struct statement * stmt)2014 ecpg_do_epilogue(struct statement *stmt)
2015 {
2016 	if (stmt == NULL)
2017 		return;
2018 
2019 #ifdef HAVE_USELOCALE
2020 	if (stmt->oldlocale != (locale_t) 0)
2021 		uselocale(stmt->oldlocale);
2022 #else
2023 	if (stmt->oldlocale)
2024 		setlocale(LC_NUMERIC, stmt->oldlocale);
2025 #ifdef HAVE__CONFIGTHREADLOCALE
2026 
2027 	/*
2028 	 * This is a bit trickier than it looks: if we failed partway through
2029 	 * statement initialization, oldthreadlocale could still be 0.  But that's
2030 	 * okay because a call with 0 is defined to be a no-op.
2031 	 */
2032 	if (stmt->oldthreadlocale != -1)
2033 		(void) _configthreadlocale(stmt->oldthreadlocale);
2034 #endif
2035 #endif
2036 
2037 	free_statement(stmt);
2038 }
2039 
2040 /*
2041  * Execute SQL statements in the backend.
2042  * The input/output parameters (variable argument list) are passed
2043  * in a va_list, so other functions can use this interface.
2044  */
2045 bool
ecpg_do(const int lineno,const int compat,const int force_indicator,const char * connection_name,const bool questionmarks,const int st,const char * query,va_list args)2046 ecpg_do(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *query, va_list args)
2047 {
2048 	struct statement *stmt = NULL;
2049 
2050 	if (!ecpg_do_prologue(lineno, compat, force_indicator, connection_name,
2051 						  questionmarks, (enum ECPG_statement_type) st,
2052 						  query, args, &stmt))
2053 		goto fail;
2054 
2055 	if (!ecpg_build_params(stmt))
2056 		goto fail;
2057 
2058 	if (!ecpg_autostart_transaction(stmt))
2059 		goto fail;
2060 
2061 	if (!ecpg_execute(stmt))
2062 		goto fail;
2063 
2064 	if (!ecpg_process_output(stmt, true))
2065 		goto fail;
2066 
2067 	ecpg_do_epilogue(stmt);
2068 	return true;
2069 
2070 fail:
2071 	ecpg_do_epilogue(stmt);
2072 	return false;
2073 }
2074 
2075 /*
2076  * Execute SQL statements in the backend.
2077  * The input/output parameters are passed as variable-length argument list.
2078  */
2079 bool
ECPGdo(const int lineno,const int compat,const int force_indicator,const char * connection_name,const bool questionmarks,const int st,const char * query,...)2080 ECPGdo(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *query,...)
2081 {
2082 	va_list		args;
2083 	bool		ret;
2084 
2085 	va_start(args, query);
2086 	ret = ecpg_do(lineno, compat, force_indicator, connection_name,
2087 				  questionmarks, st, query, args);
2088 	va_end(args);
2089 
2090 	return ret;
2091 }
2092 
2093 /* old descriptor interface */
2094 bool
ECPGdo_descriptor(int line,const char * connection,const char * descriptor,const char * query)2095 ECPGdo_descriptor(int line, const char *connection,
2096 				  const char *descriptor, const char *query)
2097 {
2098 	return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, '\0', 0, query, ECPGt_EOIT,
2099 				  ECPGt_descriptor, descriptor, 0L, 0L, 0L,
2100 				  ECPGt_NO_INDICATOR, NULL, 0L, 0L, 0L, ECPGt_EORT);
2101 }
2102