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