16 #define POSTGRES_ECPG_INTERNAL
21 #include "catalog/pg_type_d.h"
56 buffer_len = 2 * length + 1;
61 if (length == escaped_len)
63 res[0] =
res[escaped_len + 1] =
'\'';
64 res[escaped_len + 2] =
'\0';
72 memmove(
res + 2,
res + 1, escaped_len);
74 res[1] =
res[escaped_len + 2] =
'\'';
75 res[escaped_len + 3] =
'\0';
104 #ifdef HAVE_USELOCALE
106 freelocale(stmt->clocale);
119 for (;
text[p] !=
'\0'; p++)
121 if (
string && !std_strings &&
text[p] ==
'\\')
123 else if (
text[p] ==
'\'')
124 string =
string ?
false :
true;
127 if (
text[p] ==
'$' && isdigit((
unsigned char)
text[p + 1]))
132 for (
i = p + 1; isdigit((
unsigned char)
text[
i]);
i++)
134 if (!isalpha((
unsigned char)
text[
i]) &&
135 isascii((
unsigned char)
text[
i]) &&
text[
i] !=
'_')
156 if (new_entry == NULL)
161 new_entry->
next = *cache;
180 #define not_an_array_in_ecpg ECPG_ARRAY_NONE
269 array_query = (
char *)
ecpg_alloc(strlen(
"select typlen from pg_type where oid= and typelem<>0") + 11, stmt->
lineno);
270 if (array_query == NULL)
273 sprintf(array_query,
"select typlen from pg_type where oid=%d and typelem<>0",
type);
327 ecpg_log(
"ecpg_store_result on line %d: incorrect number of matches; %d don't fit into array of %ld\n",
362 for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
363 len += strlen(
PQgetvalue(results, act_tuple, act_field)) + 1;
365 len += (ntuples + 1) *
sizeof(
char *);
371 for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
373 int len = strlen(
PQgetvalue(results, act_tuple, act_field)) + 1;
392 for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
396 ecpg_log(
"ecpg_store_result on line %d: allocating memory for %d tuples\n", stmt->
lineno, ntuples);
421 char **current_string = (
char **) var->
value;
424 char *current_data_location = (
char *) ¤t_string[ntuples + 1];
426 for (act_tuple = 0; act_tuple < ntuples &&
status; act_tuple++)
428 int len = strlen(
PQgetvalue(results, act_tuple, act_field)) + 1;
436 *current_string = current_data_location;
437 current_data_location +=
len;
443 *current_string = NULL;
447 for (act_tuple = 0; act_tuple < ntuples &&
status; act_tuple++)
462 sprintf(ptr,
"%s%s",
"NaN", delim);
463 else if (isinf(
value))
466 sprintf(ptr,
"%s%s",
"-Infinity", delim);
468 sprintf(ptr,
"%s%s",
"Infinity", delim);
478 sprintf(ptr,
"%s%s",
"NaN", delim);
479 else if (isinf(
value))
482 sprintf(ptr,
"%s%s",
"-Infinity", delim);
484 sprintf(ptr,
"%s%s",
"Infinity", delim);
501 strcpy(to_data,
"'\\x");
510 char **tobeinserted_p,
bool quote)
512 char *mallocedval = NULL;
513 char *newcopy = NULL;
526 *tobeinserted_p =
"";
534 *tobeinserted_p = NULL;
539 *tobeinserted_p = NULL;
544 *tobeinserted_p = NULL;
548 if (*(
long long int *) var->
ind_value < (
long long) 0)
549 *tobeinserted_p = NULL;
555 *tobeinserted_p = NULL;
561 if (*tobeinserted_p != NULL)
570 if (!(mallocedval =
ecpg_alloc(asize * 20, lineno)))
575 strcpy(mallocedval,
"{");
580 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
585 *tobeinserted_p = mallocedval;
589 if (!(mallocedval =
ecpg_alloc(asize * 20, lineno)))
594 strcpy(mallocedval,
"{");
599 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
604 *tobeinserted_p = mallocedval;
608 if (!(mallocedval =
ecpg_alloc(asize * 20, lineno)))
613 strcpy(mallocedval,
"{");
616 sprintf(mallocedval + strlen(mallocedval),
"%hu,", ((
unsigned short *) var->
value)[
element]);
618 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
621 sprintf(mallocedval,
"%hu", *((
unsigned short *) var->
value));
623 *tobeinserted_p = mallocedval;
627 if (!(mallocedval =
ecpg_alloc(asize * 20, lineno)))
632 strcpy(mallocedval,
"{");
637 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
640 sprintf(mallocedval,
"%u", *((
unsigned int *) var->
value));
642 *tobeinserted_p = mallocedval;
646 if (!(mallocedval =
ecpg_alloc(asize * 20, lineno)))
651 strcpy(mallocedval,
"{");
656 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
661 *tobeinserted_p = mallocedval;
665 if (!(mallocedval =
ecpg_alloc(asize * 20, lineno)))
670 strcpy(mallocedval,
"{");
673 sprintf(mallocedval + strlen(mallocedval),
"%lu,", ((
unsigned long *) var->
value)[
element]);
675 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
678 sprintf(mallocedval,
"%lu", *((
unsigned long *) var->
value));
680 *tobeinserted_p = mallocedval;
684 if (!(mallocedval =
ecpg_alloc(asize * 30, lineno)))
689 strcpy(mallocedval,
"{");
692 sprintf(mallocedval + strlen(mallocedval),
"%lld,", ((
long long int *) var->
value)[
element]);
694 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
697 sprintf(mallocedval,
"%lld", *((
long long int *) var->
value));
699 *tobeinserted_p = mallocedval;
703 if (!(mallocedval =
ecpg_alloc(asize * 30, lineno)))
708 strcpy(mallocedval,
"{");
711 sprintf(mallocedval + strlen(mallocedval),
"%llu,", ((
unsigned long long int *) var->
value)[
element]);
713 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
716 sprintf(mallocedval,
"%llu", *((
unsigned long long int *) var->
value));
718 *tobeinserted_p = mallocedval;
722 if (!(mallocedval =
ecpg_alloc(asize * 25, lineno)))
727 strcpy(mallocedval,
"{");
732 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
737 *tobeinserted_p = mallocedval;
741 if (!(mallocedval =
ecpg_alloc(asize * 25, lineno)))
746 strcpy(mallocedval,
"{");
751 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
756 *tobeinserted_p = mallocedval;
765 strcpy(mallocedval,
"{");
768 sprintf(mallocedval + strlen(mallocedval),
"%c,", (((
bool *) var->
value)[
element]) ?
't' :
'f');
770 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
774 if (var->
offset ==
sizeof(
char))
775 sprintf(mallocedval,
"%c", (*((
char *) var->
value)) ?
't' :
'f');
776 else if (var->
offset ==
sizeof(
int))
777 sprintf(mallocedval,
"%c", (*((
int *) var->
value)) ?
't' :
'f');
782 *tobeinserted_p = mallocedval;
792 if (!(newcopy =
ecpg_alloc(slen + 1, lineno)))
795 strncpy(newcopy, (
char *) var->
value, slen);
796 newcopy[slen] =
'\0';
805 *tobeinserted_p = mallocedval;
811 int slen = strlen((
char *) var->
value);
813 if (!(mallocedval =
ecpg_alloc(slen + 1, lineno)))
816 strncpy(mallocedval, (
char *) var->
value, slen);
817 mallocedval[slen] =
'\0';
819 *tobeinserted_p = mallocedval;
832 *tobeinserted_p = mallocedval;
854 *tobeinserted_p = mallocedval;
900 if (!(newcopy =
ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
906 mallocedval = newcopy;
909 memcpy(mallocedval + strlen(mallocedval),
str, slen + 1);
911 strcpy(mallocedval + strlen(mallocedval),
",");
917 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
919 *tobeinserted_p = mallocedval;
947 if (!(newcopy =
ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
953 mallocedval = newcopy;
956 memcpy(mallocedval + strlen(mallocedval),
str, slen + 1);
958 strcpy(mallocedval + strlen(mallocedval),
",");
964 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
966 *tobeinserted_p = mallocedval;
994 if (!(newcopy =
ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
1000 mallocedval = newcopy;
1003 memcpy(mallocedval + strlen(mallocedval),
str, slen + 1);
1005 strcpy(mallocedval + strlen(mallocedval),
",");
1011 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
1013 *tobeinserted_p = mallocedval;
1041 if (!(newcopy =
ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
1047 mallocedval = newcopy;
1050 memcpy(mallocedval + strlen(mallocedval),
str, slen + 1);
1052 strcpy(mallocedval + strlen(mallocedval),
",");
1058 strcpy(mallocedval + strlen(mallocedval) - 1,
"}");
1060 *tobeinserted_p = mallocedval;
1082 bool malloced =
false;
1086 else if (!is_binary)
1091 if (value_s != NULL)
1098 value_s =
"no memory for logging of parameter";
1101 ecpg_log(
"ecpg_free_params on line %d: parameter %d = %s\n",
1102 lineno, nth, value_s);
1113 for (n = 0; n < stmt->
nparams; n++)
1135 + strlen(tobeinserted)
1142 strcpy(newcopy, stmt->
command);
1143 strcpy(newcopy + position - 1, tobeinserted);
1163 char **tobeinserted)
1176 memcpy(*tobeinserted, desc_item->
data, desc_item->
data_len);
1219 int desc_counter = 0;
1222 bool std_strings =
false;
1243 tobeinserted = NULL;
1245 binary_format =
false;
1265 for (desc_item = desc->
items; desc_item; desc_item = desc_item->
next)
1267 if (desc_item->
num != desc_counter)
1275 binary_length = desc_item->
data_len;
1276 binary_format =
true;
1280 if (desc->
count == desc_counter)
1295 for (
i = 0;
i < sqlda->
sqld;
i++)
1297 if (
i + 1 == desc_counter)
1302 switch (desc_inlist.type)
1309 desc_inlist.varcharsize = 0;
1312 desc_inlist.arrsize = 1;
1313 desc_inlist.offset = 0;
1322 desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
1323 desc_inlist.ind_offset = 0;
1328 desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
1329 desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
1337 if (sqlda->
sqld == desc_counter)
1350 for (
i = 0;
i < sqlda->
sqln;
i++)
1352 if (
i + 1 == desc_counter)
1357 switch (desc_inlist.type)
1364 desc_inlist.varcharsize = 0;
1367 desc_inlist.arrsize = 1;
1368 desc_inlist.offset = 0;
1377 desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
1378 desc_inlist.ind_offset = 0;
1383 desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
1384 desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
1392 if (sqlda->
sqln == desc_counter)
1404 binary_format =
true;
1433 int ph_len = (stmt->
command[position] ==
'?') ? strlen(
"?") : strlen(
"$1");
1440 tobeinserted = NULL;
1448 else if (stmt->
command[position] ==
'0')
1473 tobeinserted = NULL;
1497 tobeinserted = NULL;
1501 bool realloc_failed =
false;
1502 char **newparamvalues;
1503 int *newparamlengths;
1504 int *newparamformats;
1510 realloc_failed =
true;
1515 realloc_failed =
true;
1520 realloc_failed =
true;
1536 if (stmt->
command[position] ==
'?')
1539 int buffersize =
sizeof(int) * CHAR_BIT * 10 / 3;
1548 snprintf(tobeinserted, buffersize,
"$%d", counter++);
1555 tobeinserted = NULL;
1559 if (desc_counter == 0)
1617 ecpg_log(
"ecpg_execute on line %d: using PQexecPrepared for \"%s\"\n", stmt->
lineno, stmt->
command);
1624 ecpg_log(
"ecpg_execute on line %d: using PQexec\n", stmt->
lineno);
1635 ecpg_log(
"ecpg_execute on line %d: using PQexecParams\n", stmt->
lineno);
1699 ecpg_log(
"ecpg_process_output on line %d: correctly got %d tuples with %d fields\n", stmt->
lineno, ntuples, nfields);
1705 ecpg_log(
"ecpg_process_output on line %d: incorrect number of matches (%d)\n",
1723 clear_result =
false;
1724 ecpg_log(
"ecpg_process_output on line %d: putting result (%d tuples) into descriptor %s\n",
1744 sqlda_new = sqlda->desc_next;
1748 *_sqlda = sqlda = sqlda_new = NULL;
1749 for (
i = ntuples - 1;
i >= 0;
i--)
1762 sqlda_new = sqlda->desc_next;
1768 ecpg_log(
"ecpg_process_output on line %d: out of memory allocating a new sqlda\n", stmt->
lineno);
1774 ecpg_log(
"ecpg_process_output on line %d: new sqlda was built\n", stmt->
lineno);
1776 *_sqlda = sqlda_new;
1779 ecpg_log(
"ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
1782 sqlda_new->desc_next = sqlda;
1800 sqlda_new = sqlda->desc_next;
1804 *_sqlda = sqlda = sqlda_new = NULL;
1805 for (
i = ntuples - 1;
i >= 0;
i--)
1818 sqlda_new = sqlda->desc_next;
1824 ecpg_log(
"ecpg_process_output on line %d: out of memory allocating a new sqlda\n", stmt->
lineno);
1830 ecpg_log(
"ecpg_process_output on line %d: new sqlda was built\n", stmt->
lineno);
1832 *_sqlda = sqlda_new;
1835 ecpg_log(
"ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
1838 sqlda_new->desc_next = sqlda;
1847 for (act_field = 0; act_field < nfields &&
status; act_field++)
1861 if (
status && var != NULL)
1873 ecpg_log(
"ecpg_process_output on line %d: OK: %s\n", stmt->
lineno, cmdstat);
1875 !
sqlca->sqlerrd[2] &&
1876 (strncmp(cmdstat,
"UPDATE", 6) == 0
1877 || strncmp(cmdstat,
"INSERT", 6) == 0
1878 || strncmp(cmdstat,
"DELETE", 6) == 0))
1886 ecpg_log(
"ecpg_process_output on line %d: COPY OUT data transfer in progress\n", stmt->
lineno);
1899 ecpg_log(
"ecpg_process_output on line %d: got PGRES_COMMAND_OK after PGRES_COPY_OUT\n", stmt->
lineno);
1911 ecpg_log(
"ecpg_process_output on line %d: unknown execution status type\n",
1928 ecpg_log(
"ecpg_process_output on line %d: asynchronous notification of \"%s\" from backend PID %d received\n",
1958 bool is_prepared_name_set;
1981 #ifdef HAVE_USELOCALE
1982 stmt->clocale = newlocale(LC_NUMERIC_MASK,
"C", (
locale_t) 0);
1988 stmt->
oldlocale = uselocale(stmt->clocale);
1995 #ifdef HAVE__CONFIGTHREADLOCALE
1996 stmt->oldthreadlocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
2007 #ifdef ENABLE_THREAD_SAFETY
2008 ecpg_pthreads_init();
2091 is_prepared_name_set =
false;
2185 is_prepared_name_set =
true;
2225 #ifdef HAVE_USELOCALE
2231 #ifdef HAVE__CONFIGTHREADLOCALE
2238 if (stmt->oldthreadlocale != -1)
2239 (void) _configthreadlocale(stmt->oldthreadlocale);
2258 query,
args, &stmt))
void print(const void *obj)
#define ESCAPE_STRING_SYNTAX
struct connection * ecpg_get_connection(const char *connection_name)
unsigned ecpg_hex_enc_len(unsigned srclen)
bool ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno, enum ECPGttype type, enum ECPGttype ind_type, char *var, char *ind, long varcharsize, long offset, long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator)
unsigned ecpg_hex_encode(const char *src, unsigned len, char *dst)
static void PGresult * res
#define ECPG_CONVERT_BOOL
#define ECPG_TOO_MANY_ARGUMENTS
#define ECPG_TOO_FEW_ARGUMENTS
#define ECPG_INVALID_STMT
#define ECPG_INFORMIX_SUBSELECT_NOT_ONE
#define ECPG_TOO_MANY_MATCHES
#define ECPG_OUT_OF_MEMORY
struct descriptor * ecpg_find_desc(int line, const char *name)
bool ecpg_check_PQresult(PGresult *, int, PGconn *, enum COMPAT_MODE)
char * ecpg_alloc(long, int)
#define ECPG_SQLSTATE_NO_DATA
char * ecpg_prepared(const char *, struct connection *)
#define ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY
@ ECPG_COMPAT_INFORMIX_SE
char * ecpg_auto_alloc(long, int)
bool ecpg_register_prepared_stmt(struct statement *)
#define ECPG_SQLSTATE_ECPG_INTERNAL_ERROR
int ecpg_dynamic_type(Oid)
void ecpg_set_native_sqlda(int, struct sqlda_struct **, const PGresult *, int, enum COMPAT_MODE)
char * ecpg_realloc(void *, long, int)
void ecpg_log(const char *format,...) pg_attribute_printf(1
void ecpg_clear_auto_mem(void)
struct sqlda_compat * ecpg_build_compat_sqlda(int, PGresult *, int, enum COMPAT_MODE)
struct sqlda_struct * ecpg_build_native_sqlda(int, PGresult *, int, enum COMPAT_MODE)
#define ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS
bool ecpg_init(const struct connection *, const char *, const int)
#define ECPG_SQLSTATE_CARDINALITY_VIOLATION
const char * ecpg_type_name(enum ECPGttype)
#define ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS
void ecpg_set_compat_sqlda(int, struct sqlda_compat **, const PGresult *, int, enum COMPAT_MODE)
#define ECPG_SQLSTATE_DATATYPE_MISMATCH
void ecpg_raise(int line, int code, const char *sqlstate, const char *str)
void ecpg_raise_backend(int line, PGresult *result, PGconn *conn, int compat)
char * ecpg_strdup(const char *, int)
#define ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME
void bool ecpg_auto_prepare(int, const char *, const int, char **, const char *)
@ ECPGst_exec_with_exprlist
@ ECPGt_unsigned_long_long
static bool ecpg_type_infocache_push(struct ECPGtype_information_cache **cache, int oid, enum ARRAY_TYPE isarray, int lineno)
bool ecpg_build_params(struct statement *stmt)
bool ecpg_store_result(const PGresult *results, int act_field, const struct statement *stmt, struct variable *var)
static void sprintf_double_value(char *ptr, double value, const char *delim)
static void print_param_value(char *value, int len, int is_binary, int lineno, int nth)
static bool insert_tobeinserted(int position, int ph_len, struct statement *stmt, char *tobeinserted)
static char * quote_postgres(char *arg, bool quote, int lineno)
bool ecpg_execute(struct statement *stmt)
void ecpg_free_params(struct statement *stmt, bool print)
static enum ARRAY_TYPE ecpg_is_type_an_array(int type, const struct statement *stmt, const struct variable *var)
bool ecpg_store_input(const int lineno, const bool force_indicator, const struct variable *var, char **tobeinserted_p, bool quote)
static bool store_input_from_desc(struct statement *stmt, struct descriptor_item *desc_item, char **tobeinserted)
static void sprintf_float_value(char *ptr, float value, const char *delim)
void ecpg_do_epilogue(struct statement *stmt)
static char * convert_bytea_to_string(char *from_data, int from_len, int lineno)
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)
static void free_variable(struct variable *var)
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)
bool ecpg_process_output(struct statement *stmt, bool clear_result)
bool ecpg_autostart_transaction(struct statement *stmt)
bool ECPGdo_descriptor(int line, const char *connection, const char *descriptor, const char *query)
static void free_statement(struct statement *stmt)
#define not_an_array_in_ecpg
static int next_insert(char *text, int pos, bool questionmarks, bool std_strings)
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,...)
const char * PQparameterStatus(const PGconn *conn, const char *paramName)
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
int PQgetlength(const PGresult *res, int tup_num, int field_num)
void PQfreemem(void *ptr)
PGnotify * PQnotifies(PGconn *conn)
Oid PQftype(const PGresult *res, int field_num)
PGresult * PQexecParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
ExecStatusType PQresultStatus(const PGresult *res)
void PQclear(PGresult *res)
char * PQcmdTuples(PGresult *res)
char * PQresultErrorMessage(const PGresult *res)
int PQfformat(const PGresult *res, int field_num)
int PQntuples(const PGresult *res)
PGresult * PQexecPrepared(PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
PGresult * PQexec(PGconn *conn, const char *query)
size_t PQescapeString(char *to, const char *from, size_t length)
int PQconsumeInput(PGconn *conn)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
char * PQcmdStatus(PGresult *res)
Oid PQoidValue(const PGresult *res)
int PQnfields(const PGresult *res)
PGresult * PQgetResult(PGconn *conn)
int PQgetCopyData(PGconn *conn, char **buffer, int async)
bool ECPGis_noind_null(enum ECPGttype type, const void *ptr)
struct sqlca_t * ECPGget_sqlca(void)
static void static void status(const char *fmt,...) pg_attribute_printf(1
char * PGTYPESdate_to_asc(date)
char * PGTYPESinterval_to_asc(interval *)
int PGTYPESnumeric_from_decimal(decimal *, numeric *)
char * PGTYPESnumeric_to_asc(numeric *, int)
int PGTYPESnumeric_copy(numeric *, numeric *)
numeric * PGTYPESnumeric_new(void)
void PGTYPESnumeric_free(numeric *)
char * PGTYPEStimestamp_to_asc(timestamp)
static chr element(struct vars *v, const chr *startp, const chr *endp)
struct ECPGtype_information_cache * cache_head
struct descriptor_item * next
struct descriptor_item * items
struct sqlvar_compat * sqlvar
struct sqlvar_struct sqlvar[1]
struct variable * outlist
struct connection * connection
enum ECPG_statement_type statement_type