diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 454ddcd2bd7fa0057b88d06ca9758bc5ec0bad34..2c31f330003fa986aab19d03146d8bab4a3b9730 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -1175,5 +1175,14 @@ Sun Dec 9 16:21:30 CET 2001 - Fixed several bugs concerning indicators and added error messages instead of segfaults. + +Thu Dec 20 14:15:56 CET 2001 + + - Removed space_or_nl and line_end from pgc.l. + +Sun Dec 23 13:08:36 CET 2001 + + - Fixed several bugs concerning arrays of structs including a memory + allocation bug. - Set ecpg version to 2.9.0. - Set library version to 3.3.0. diff --git a/src/interfaces/ecpg/include/ecpgerrno.h b/src/interfaces/ecpg/include/ecpgerrno.h index 5723e1262109a6e484022622347f0dc56f5aa380..189f1db9102c880f6181bcf96c2d70a1f08a31a1 100644 --- a/src/interfaces/ecpg/include/ecpgerrno.h +++ b/src/interfaces/ecpg/include/ecpgerrno.h @@ -25,6 +25,7 @@ #define ECPG_MISSING_INDICATOR -209 #define ECPG_NO_ARRAY -210 #define ECPG_DATA_NOT_ARRAY -211 +#define ECPG_ARRAY_INSERT -212 #define ECPG_NO_CONN -220 #define ECPG_NOT_CONN -221 diff --git a/src/interfaces/ecpg/lib/Makefile b/src/interfaces/ecpg/lib/Makefile index d69b0215e4ca4651e62961430a43e703716f34d1..e512d3047647c7cadbba41b54f9c388d7b20de9a 100644 --- a/src/interfaces/ecpg/lib/Makefile +++ b/src/interfaces/ecpg/lib/Makefile @@ -4,7 +4,7 @@ # # Copyright (c) 1994, Regents of the University of California # -# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile,v 1.13 2001/09/19 14:09:32 meskes Exp $ +# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile,v 1.14 2001/12/23 12:17:41 meskes Exp $ # #------------------------------------------------------------------------- @@ -12,6 +12,8 @@ subdir = src/interfaces/ecpg/lib top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global +CFLAGS=-g + NAME= ecpg SO_MAJOR_VERSION= 3 SO_MINOR_VERSION= 3.0 diff --git a/src/interfaces/ecpg/lib/connect.c b/src/interfaces/ecpg/lib/connect.c index 4520e1bf609c876035b78deb5334213e48104108..cb35a08ca256b2eef78c8f601546556e587f73b0 100644 --- a/src/interfaces/ecpg/lib/connect.c +++ b/src/interfaces/ecpg/lib/connect.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/connect.c,v 1.16 2001/12/05 15:32:06 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/connect.c,v 1.17 2001/12/23 12:17:41 meskes Exp $ */ #include "postgres_fe.h" @@ -52,9 +52,9 @@ ecpg_finish(struct connection * act) if (actual_connection == act) actual_connection = all_connections; - for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, free(ptr)); - free(act->name); - free(act); + for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, ECPGfree(ptr)); + ECPGfree(act->name); + ECPGfree(act); } else ECPGlog("ecpg_finish: called an extra time.\n"); @@ -348,15 +348,15 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd, ECPGlog("connect: socketname %s given for TCP connection in line %d\n", host, lineno); ECPGraise(lineno, ECPG_CONNECT, realname ? realname : ""); if (host) - free(host); + ECPGfree(host); if (port) - free(port); + ECPGfree(port); if (options) - free(options); + ECPGfree(options); if (realname) - free(realname); + ECPGfree(realname); if (dbname) - free(dbname); + ECPGfree(dbname); return false; } } @@ -371,15 +371,15 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd, ECPGlog("connect: non-localhost access via sockets in line %d\n", lineno); ECPGraise(lineno, ECPG_CONNECT, realname ? realname : ""); if (host) - free(host); + ECPGfree(host); if (port) - free(port); + ECPGfree(port); if (options) - free(options); + ECPGfree(options); if (realname) - free(realname); + ECPGfree(realname); if (dbname) - free(dbname); + ECPGfree(dbname); return false; } } @@ -431,28 +431,28 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd, lineno); ECPGraise(lineno, ECPG_CONNECT, realname ? realname : ""); if (host) - free(host); + ECPGfree(host); if (port) - free(port); + ECPGfree(port); if (options) - free(options); + ECPGfree(options); if (realname) - free(realname); + ECPGfree(realname); if (dbname) - free(dbname); + ECPGfree(dbname); return false; } if (host) - free(host); + ECPGfree(host); if (port) - free(port); + ECPGfree(port); if (options) - free(options); + ECPGfree(options); if (realname) - free(realname); + ECPGfree(realname); if (dbname) - free(dbname); + ECPGfree(dbname); this->committed = true; this->autocommit = autocommit; diff --git a/src/interfaces/ecpg/lib/data.c b/src/interfaces/ecpg/lib/data.c index b0d91b9453a67f78a45baf83481f99e33fd4420e..678dde39a79b0651d3e9251f251bff4915ca5054 100644 --- a/src/interfaces/ecpg/lib/data.c +++ b/src/interfaces/ecpg/lib/data.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/data.c,v 1.20 2001/12/05 15:32:06 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/data.c,v 1.21 2001/12/23 12:17:41 meskes Exp $ */ #include "postgres_fe.h" @@ -15,11 +15,11 @@ bool ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, enum ECPGttype type, enum ECPGttype ind_type, void *var, void *ind, long varcharsize, long offset, - bool isarray) + long ind_offset, bool isarray) { char *pval = (char *) PQgetvalue(results, act_tuple, act_field); - ECPGlog("ECPGget_data line %d: RESULT: %s\n", lineno, pval ? pval : ""); + ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld\n", lineno, pval ? pval : "", offset); /* pval is a pointer to the value */ /* let's check is it really is an array if it should be one */ @@ -53,23 +53,28 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, { case ECPGt_short: case ECPGt_unsigned_short: - ((short *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); +/* ((short *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);*/ + *((short *) (ind + ind_offset*act_tuple)) = -PQgetisnull(results, act_tuple, act_field); break; case ECPGt_int: case ECPGt_unsigned_int: - ((int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); +/* ((int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);*/ + *((int *) (ind + ind_offset*act_tuple)) = -PQgetisnull(results, act_tuple, act_field); break; case ECPGt_long: case ECPGt_unsigned_long: - ((long *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); +/* ((long *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);*/ + *((long *) (ind + ind_offset*act_tuple)) = -PQgetisnull(results, act_tuple, act_field); break; #ifdef HAVE_LONG_LONG_INT_64 case ECPGt_long_long: - ((long long int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); - break; case ECPGt_unsigned_long_long: - ((unsigned long long int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); +/* ((long long int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);*/ + *((long long int *) (ind + ind_offset*act_tuple)) = -PQgetisnull(results, act_tuple, act_field); break; +/* case ECPGt_unsigned_long_long: + ((unsigned long long int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); + break;*/ #endif /* HAVE_LONG_LONG_INT_64 */ case ECPGt_NO_INDICATOR: if (PQgetisnull(results, act_tuple, act_field)) @@ -112,13 +117,16 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, switch (type) { case ECPGt_short: - ((short *) var)[act_tuple] = (short) res; +/* ((short *) var)[act_tuple] = (short) res;*/ + *((short *) (var + offset*act_tuple)) = (short) res; break; case ECPGt_int: - ((int *) var)[act_tuple] = (int) res; +/* ((int *) var)[act_tuple] = (int) res;*/ + *((int *) (var + offset*act_tuple)) = (int) res; break; case ECPGt_long: - ((long *) var)[act_tuple] = res; +/* ((long *) var)[act_tuple] = res;*/ + *((long *) (var + offset*act_tuple)) = (long) res; break; default: /* Cannot happen */ @@ -145,13 +153,16 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, switch (type) { case ECPGt_unsigned_short: - ((unsigned short *) var)[act_tuple] = (unsigned short) ures; +/* ((unsigned short *) var)[act_tuple] = (unsigned short) ures;*/ + *((unsigned short *) (var + offset*act_tuple)) = (unsigned short) res; break; case ECPGt_unsigned_int: - ((unsigned int *) var)[act_tuple] = (unsigned int) ures; +/* ((unsigned int *) var)[act_tuple] = (unsigned int) ures;*/ + *((unsigned int *) (var + offset*act_tuple)) = (unsigned int) res; break; case ECPGt_unsigned_long: - ((unsigned long *) var)[act_tuple] = ures; +/* ((unsigned long *) var)[act_tuple] = ures;*/ + *((unsigned long *) (var + offset*act_tuple)) = (unsigned long) res; break; default: /* Cannot happen */ @@ -164,7 +175,8 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, case ECPGt_long_long: if (pval) { - ((long long int *) var)[act_tuple] = strtoll(pval, &scan_length, 10); +/* ((long long int *) var)[act_tuple] = strtoll(pval, &scan_length, 10);*/ + *((long long int *) (var + offset*act_tuple)) = strtoll(pval, &scan_length, 10); if ((isarray && *scan_length != ',' && *scan_length != '}') || (!isarray && *scan_length != '\0')) /* Garbage left */ { @@ -173,7 +185,8 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, } } else - ((long long int *) var)[act_tuple] = (long long) 0; +/* ((long long int *) var)[act_tuple] = (long long) 0;*/ + *((long long int *) (var + offset*act_tuple)) = (long long) 0; break; #endif /* HAVE_STRTOLL */ @@ -181,7 +194,8 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, case ECPGt_unsigned_long_long: if (pval) { - ((unsigned long long int *) var)[act_tuple] = strtoull(pval, &scan_length, 10); +/* ((unsigned long long int *) var)[act_tuple] = strtoull(pval, &scan_length, 10);*/ + *((unsigned long long int *) (var + offset*act_tuple)) = strtoull(pval, &scan_length, 10); if ((isarray && *scan_length != ',' && *scan_length != '}') || (!isarray && *scan_length != '\0')) /* Garbage left */ { @@ -190,7 +204,8 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, } } else - ((unsigned long long int *) var)[act_tuple] = (long long) 0; +/* ((unsigned long long int *) var)[act_tuple] = (long long) 0;*/ + *((unsigned long long int *) (var + offset*act_tuple)) = (long long) 0; break; #endif /* HAVE_STRTOULL */ @@ -221,10 +236,12 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, switch (type) { case ECPGt_float: - ((float *) var)[act_tuple] = dres; +/* ((float *) var)[act_tuple] = dres;*/ + *((float *) (var + offset*act_tuple)) = dres; break; case ECPGt_double: - ((double *) var)[act_tuple] = dres; +/* ((double *) var)[act_tuple] = dres;*/ + *((double *) (var + offset*act_tuple)) = dres; break; default: /* Cannot happen */ @@ -238,9 +255,11 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, if (pval[0] == 'f' && pval[1] == '\0') { if (offset == sizeof(char)) - ((char *) var)[act_tuple] = false; +/* ((char *) var)[act_tuple] = false;*/ + *((char *) (var + offset*act_tuple)) = false; else if (offset == sizeof(int)) - ((int *) var)[act_tuple] = false; +/* ((int *) var)[act_tuple] = false;*/ + *((int *) (var + offset*act_tuple)) = false; else ECPGraise(lineno, ECPG_CONVERT_BOOL, "different size"); break; @@ -248,9 +267,11 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, else if (pval[0] == 't' && pval[1] == '\0') { if (offset == sizeof(char)) - ((char *) var)[act_tuple] = true; +/* ((char *) var)[act_tuple] = true;*/ + *((char *) (var + offset*act_tuple)) = true; else if (offset == sizeof(int)) - ((int *) var)[act_tuple] = true; +/* ((int *) var)[act_tuple] = true;*/ + *((int *) (var + offset*act_tuple)) = true; else ECPGraise(lineno, ECPG_CONVERT_BOOL, "different size"); break; @@ -277,16 +298,25 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, { case ECPGt_short: case ECPGt_unsigned_short: - ((short *) ind)[act_tuple] = strlen(pval); +/* ((short *) ind)[act_tuple] = strlen(pval);*/ + *((short *) (ind + ind_offset*act_tuple)) = strlen(pval); break; case ECPGt_int: case ECPGt_unsigned_int: - ((int *) ind)[act_tuple] = strlen(pval); +/* ((int *) ind)[act_tuple] = strlen(pval);*/ + *((int *) (ind + ind_offset*act_tuple)) = strlen(pval); break; case ECPGt_long: case ECPGt_unsigned_long: - ((long *) ind)[act_tuple] = strlen(pval); +/* ((long *) ind)[act_tuple] = strlen(pval);*/ + *((long *) (ind + ind_offset*act_tuple)) = strlen(pval); + break; +#ifdef HAVE_LONG_LONG_INT_64 + case ECPGt_long_long: + case ECPGt_unsigned_long_long: + *((long long int *) (ind + ind_offset*act_tuple)) = strlen(pval); break; +#endif /* HAVE_LONG_LONG_INT_64 */ default: break; } @@ -313,16 +343,25 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, { case ECPGt_short: case ECPGt_unsigned_short: - ((short *) ind)[act_tuple] = variable->len; +/* ((short *) ind)[act_tuple] = variable->len;*/ + *((short *) (ind + offset*act_tuple)) = variable->len; break; case ECPGt_int: case ECPGt_unsigned_int: - ((int *) ind)[act_tuple] = variable->len; +/* ((int *) ind)[act_tuple] = variable->len;*/ + *((int *) (ind + offset*act_tuple)) = variable->len; break; case ECPGt_long: case ECPGt_unsigned_long: - ((long *) ind)[act_tuple] = variable->len; +/* ((long *) ind)[act_tuple] = variable->len;*/ + *((long *) (ind + offset*act_tuple)) = variable->len; + break; +#ifdef HAVE_LONG_LONG_INT_64 + case ECPGt_long_long: + case ECPGt_unsigned_long_long: + *((long long int *) (ind + ind_offset*act_tuple)) = variable->len; break; +#endif /* HAVE_LONG_LONG_INT_64 */ default: break; } diff --git a/src/interfaces/ecpg/lib/descriptor.c b/src/interfaces/ecpg/lib/descriptor.c index 533bdcea5a45640a158111e6bbf76371326b5113..66fb6b1d86193f44b7b25d64948e5c658513e2db 100644 --- a/src/interfaces/ecpg/lib/descriptor.c +++ b/src/interfaces/ecpg/lib/descriptor.c @@ -1,6 +1,6 @@ /* dynamic SQL support routines * - * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/descriptor.c,v 1.19 2001/11/14 11:11:49 meskes Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/descriptor.c,v 1.20 2001/12/23 12:17:41 meskes Exp $ */ #include "postgres_fe.h" @@ -374,9 +374,9 @@ ECPGdeallocate_desc(int line, const char *name) if (!strcmp(name, i->name)) { *lastptr = i->next; - free(i->name); + ECPGfree(i->name); PQclear(i->result); - free(i); + ECPGfree(i); return true; } } diff --git a/src/interfaces/ecpg/lib/error.c b/src/interfaces/ecpg/lib/error.c index 56dd42fbed9c942e3d7937814a884e8fe737330c..e92f8f142ee0e80d91ae8c81e897b1d0f8bcea42 100644 --- a/src/interfaces/ecpg/lib/error.c +++ b/src/interfaces/ecpg/lib/error.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/error.c,v 1.13 2001/11/14 11:11:49 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/error.c,v 1.14 2001/12/23 12:17:41 meskes Exp $ */ #include "postgres_fe.h" @@ -82,6 +82,11 @@ ECPGraise(int line, int code, const char *str) "Data read from backend is not an array in line %d.", line); break; + case ECPG_ARRAY_INSERT: + snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), + "Trying to insert an array of variables in line %d.", line); + break; + case ECPG_NO_CONN: snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), "No such connection %s in line %d.", str, line); diff --git a/src/interfaces/ecpg/lib/execute.c b/src/interfaces/ecpg/lib/execute.c index d37af5f61f112f2031e1b40b06b47f3fb256220a..c2f1e6bda48ae06464711d988b8b7b59f79b3c83 100644 --- a/src/interfaces/ecpg/lib/execute.c +++ b/src/interfaces/ecpg/lib/execute.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.33 2001/11/21 22:57:01 tgl Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.34 2001/12/23 12:17:41 meskes Exp $ */ /* * The aim is to get a simpler inteface to the database routines. @@ -55,40 +55,6 @@ struct sqlca sqlca = } }; -/* keep a list of memory we allocated for the user */ -static struct auto_mem -{ - void *pointer; - struct auto_mem *next; -} *auto_allocs = NULL; - -void -ECPGadd_mem(void *ptr, int lineno) -{ - struct auto_mem *am = (struct auto_mem *) ECPGalloc(sizeof(struct auto_mem), lineno); - am->pointer = ptr; - am->next = auto_allocs; - auto_allocs = am; -} - -void -ECPGfree_auto_mem(void) -{ - struct auto_mem *am; - - /* free all memory we have allocated for the user */ - for (am = auto_allocs; am;) - { - struct auto_mem *act = am; - - am = am->next; - free(act->pointer); - free(act); - } - - auto_allocs = NULL; -} - /* This function returns a newly malloced string that has the \ in the argument quoted with \ and the ' quote with ' as SQL92 says. */ @@ -182,7 +148,7 @@ create_statement(int lineno, struct connection * connection, struct statement ** if (var->pointer == NULL) { ECPGraise(lineno, ECPG_INVALID_STMT, NULL); - free(var); + ECPGfree(var); return false; } @@ -202,7 +168,7 @@ create_statement(int lineno, struct connection * connection, struct statement ** var->ind_offset = va_arg(ap, long); var->next = NULL; - if (var->ind_type!=ECPGt_NO_INDICATOR + if (var->ind_type != ECPGt_NO_INDICATOR && (var->ind_arrsize == 0 || var->ind_varcharsize == 0)) var->ind_value = *((void **) (var->ind_pointer)); else @@ -230,13 +196,13 @@ free_variable(struct variable * var) if (var == (struct variable *) NULL) return; var_next = var->next; - free(var); + ECPGfree(var); while (var_next) { var = var_next; var_next = var->next; - free(var); + ECPGfree(var); } } @@ -247,7 +213,7 @@ free_statement(struct statement * stmt) return; free_variable(stmt->inlist); free_variable(stmt->outlist); - free(stmt); + ECPGfree(stmt); } static char * @@ -354,7 +320,7 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia array_query = (char *) ECPGalloc(strlen("select typelem from pg_type where oid=") + 11, stmt->lineno); sprintf(array_query, "select typelem from pg_type where oid=%d", type); query = PQexec(stmt->connection->connection, array_query); - free(array_query); + ECPGfree(array_query); if (PQresultStatus(query) == PGRES_TUPLES_OK) { isarray = atol((char *) PQgetvalue(query, 0, 0)); @@ -460,6 +426,7 @@ ECPGstore_result(const PGresult *results, int act_field, *((void **) var->pointer) = var->value; ECPGadd_mem(var->value, stmt->lineno); } + /* allocate indicator variable if needed */ if ((var->ind_arrsize == 0 || var->ind_varcharsize == 0) && var->ind_value == NULL && var->ind_pointer!=NULL) { @@ -470,7 +437,6 @@ ECPGstore_result(const PGresult *results, int act_field, } /* fill the variable with the tuple(s) */ - if (!var->varcharsize && !var->arrsize && (var->type==ECPGt_char || var->type==ECPGt_unsigned_char)) { @@ -486,7 +452,7 @@ ECPGstore_result(const PGresult *results, int act_field, int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1; if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno, var->type, var->ind_type, current_data_location, - var->ind_value, len, 0, isarray)) + var->ind_value, len, 0, 0, isarray)) status = false; else { @@ -505,7 +471,7 @@ ECPGstore_result(const PGresult *results, int act_field, { if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno, var->type, var->ind_type, var->value, - var->ind_value, var->varcharsize, var->offset, isarray)) + var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray)) status = false; } } @@ -519,6 +485,16 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, char *mallocedval = NULL; char *newcopy = NULL; + /* + * arrays are not possible + */ + + if (var->arrsize > 1) + { + ECPGraise(stmt->lineno, ECPG_ARRAY_INSERT, NULL); + return false; + } + /* * Some special treatment is needed for records since we want their * contents to arrive in a comma-separated list on insert (I think). @@ -816,7 +792,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, if (!mallocedval) return false; - free(newcopy); + ECPGfree(newcopy); *tobeinserted_p = mallocedval; *malloced_p = true; @@ -851,7 +827,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, if (!mallocedval) return false; - free(newcopy); + ECPGfree(newcopy); *tobeinserted_p = mallocedval; *malloced_p = true; @@ -936,11 +912,11 @@ ECPGexecute(struct statement * stmt) */ if (malloced) { - free((char *) tobeinserted); + ECPGfree((char *) tobeinserted); tobeinserted = NULL; } - free(copiedquery); + ECPGfree(copiedquery); copiedquery = newcopy; var = var->next; @@ -968,7 +944,7 @@ ECPGexecute(struct statement * stmt) ECPGlog("ECPGexecute line %d: QUERY: %s on connection %s\n", stmt->lineno, copiedquery, stmt->connection->name); results = PQexec(stmt->connection->connection, copiedquery); - free(copiedquery); + ECPGfree(copiedquery); if (results == NULL) { @@ -1091,7 +1067,7 @@ ECPGexecute(struct statement * stmt) { ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n", stmt->lineno, notify->relname, notify->be_pid); - free(notify); + ECPGfree(notify); } return status; @@ -1114,15 +1090,16 @@ ECPGdo(int lineno, const char *connection_name, char *query,...) if (!ECPGinit(con, connection_name, lineno)) { setlocale(LC_NUMERIC, oldlocale); - free(oldlocale); + ECPGfree(oldlocale); return (false); } + /* construct statement in our own structure */ va_start(args, query); if (create_statement(lineno, con, &stmt, query, args) == false) { setlocale(LC_NUMERIC, oldlocale); - free(oldlocale); + ECPGfree(oldlocale); return (false); } va_end(args); @@ -1133,16 +1110,19 @@ ECPGdo(int lineno, const char *connection_name, char *query,...) free_statement(stmt); ECPGraise(lineno, ECPG_NOT_CONN, (con) ? con->name : ""); setlocale(LC_NUMERIC, oldlocale); - free(oldlocale); + ECPGfree(oldlocale); return false; } + /* initialize auto_mem struct */ + ECPGclear_auto_mem(); + status = ECPGexecute(stmt); free_statement(stmt); /* and reset locale value so our application is not affected */ setlocale(LC_NUMERIC, oldlocale); - free(oldlocale); + ECPGfree(oldlocale); return (status); } diff --git a/src/interfaces/ecpg/lib/extern.h b/src/interfaces/ecpg/lib/extern.h index 3759751555bb27ec6f2cae5dafda1f85849fc0a0..478ec4b99f2ff02091707cc614bb974bd79a29b2 100644 --- a/src/interfaces/ecpg/lib/extern.h +++ b/src/interfaces/ecpg/lib/extern.h @@ -6,15 +6,17 @@ void ECPGadd_mem(void *ptr, int lineno); bool ECPGget_data(const PGresult *, int, int, int, enum ECPGttype type, - enum ECPGttype, void *, void *, long, long, bool); + enum ECPGttype, void *, void *, long, long, long, bool); struct connection *ECPGget_connection(const char *); void ECPGinit_sqlca(void); char *ECPGalloc(long, int); +void ECPGfree(void *); bool ECPGinit(const struct connection *, const char *, const int); char *ECPGstrdup(const char *, int); const char *ECPGtype_name(enum ECPGttype); unsigned int ECPGDynamicType(Oid); - +void ECPGfree_auto_mem(void); +void ECPGclear_auto_mem(void); /* A generic varchar type. */ struct ECPGgeneric_varchar diff --git a/src/interfaces/ecpg/lib/memory.c b/src/interfaces/ecpg/lib/memory.c index e1bc12eef3f8cb493e4b084743e5a28fb09a116e..5e85261332c412f4a67857119b868efbd31781f4 100644 --- a/src/interfaces/ecpg/lib/memory.c +++ b/src/interfaces/ecpg/lib/memory.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/memory.c,v 1.7 2001/11/14 11:11:49 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/memory.c,v 1.8 2001/12/23 12:17:41 meskes Exp $ */ #include "postgres_fe.h" @@ -7,6 +7,12 @@ #include "ecpgerrno.h" #include "extern.h" +void +ECPGfree(void *ptr) +{ + free(ptr); +} + char * ECPGalloc(long size, int lineno) { @@ -35,3 +41,54 @@ ECPGstrdup(const char *string, int lineno) return (new); } + +/* keep a list of memory we allocated for the user */ +static struct auto_mem +{ + void *pointer; + struct auto_mem *next; +} *auto_allocs = NULL; + +void +ECPGadd_mem(void *ptr, int lineno) +{ + struct auto_mem *am = (struct auto_mem *) ECPGalloc(sizeof(struct auto_mem), lineno); + am->pointer = ptr; + am->next = auto_allocs; + auto_allocs = am; +} + +void +ECPGfree_auto_mem(void) +{ + struct auto_mem *am; + + /* free all memory we have allocated for the user */ + for (am = auto_allocs; am;) + { + struct auto_mem *act = am; + + am = am->next; + ECPGfree(act->pointer); + ECPGfree(act); + } + + auto_allocs = NULL; +} + +void +ECPGclear_auto_mem(void) +{ + struct auto_mem *am; + + /* free just our own structure */ + for (am = auto_allocs; am;) + { + struct auto_mem *act = am; + + am = am->next; + ECPGfree(act); + } + + auto_allocs = NULL; +} diff --git a/src/interfaces/ecpg/lib/misc.c b/src/interfaces/ecpg/lib/misc.c index 1a74cf46d309a88649cba34451b1cc5300188540..a3dd727cbd699f479988802e1fa03bbca797d673 100644 --- a/src/interfaces/ecpg/lib/misc.c +++ b/src/interfaces/ecpg/lib/misc.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/misc.c,v 1.10 2001/11/14 11:11:49 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/misc.c,v 1.11 2001/12/23 12:17:41 meskes Exp $ */ #include "postgres_fe.h" @@ -137,6 +137,6 @@ ECPGlog(const char *format,...) vfprintf(debugstream, f, ap); va_end(ap); - free(f); + ECPGfree(f); } } diff --git a/src/interfaces/ecpg/lib/prepare.c b/src/interfaces/ecpg/lib/prepare.c index 4117454835e533cdfaea5856fbff5ad375029019..740afb5978edd12938c0948056b114551250d200 100644 --- a/src/interfaces/ecpg/lib/prepare.c +++ b/src/interfaces/ecpg/lib/prepare.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/prepare.c,v 1.11 2001/11/14 11:11:49 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/prepare.c,v 1.12 2001/12/23 12:17:41 meskes Exp $ */ #include "postgres_fe.h" @@ -76,7 +76,7 @@ ECPGprepare(int lineno, char *name, char *variable) stmt = (struct statement *) ECPGalloc(sizeof(struct statement), lineno); if (!stmt) { - free(this); + ECPGfree(this); return false; } @@ -114,15 +114,15 @@ ECPGdeallocate(int lineno, char *name) if (this) { /* okay, free all the resources */ - free(this->name); - free(this->stmt->command); - free(this->stmt); + ECPGfree(this->name); + ECPGfree(this->stmt->command); + ECPGfree(this->stmt); if (prev != NULL) prev->next = this->next; else prep_stmts = this->next; - free(this); + ECPGfree(this); return true; } ECPGraise(lineno, ECPG_INVALID_STMT, name); diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index 2c280f7ab7ae152e6e2d908219c904b66fce3c49..209b9184c7c5cc77ff0ae60f8502000ae6d18975 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -1,9 +1,11 @@ -# $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.78 2001/11/16 16:32:33 petere Exp $ +# $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.79 2001/12/23 12:17:41 meskes Exp $ subdir = src/interfaces/ecpg/preproc top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global +CFLAGS+=-g + MAJOR_VERSION=2 MINOR_VERSION=9 PATCHLEVEL=0 diff --git a/src/interfaces/ecpg/preproc/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c index 2b491ac036c43ff462294e1281163cfdd7859892..e542bcece08957b36c91ec0ffbf7e566e9ebdd3a 100644 --- a/src/interfaces/ecpg/preproc/descriptor.c +++ b/src/interfaces/ecpg/preproc/descriptor.c @@ -45,7 +45,7 @@ ECPGnumeric_lvalue(FILE *f, char *name) { const struct variable *v = find_variable(name); - switch (v->type->typ) + switch (v->type->type) { case ECPGt_short: case ECPGt_int: @@ -192,7 +192,7 @@ output_get_descr(char *desc_name, char *index) break; } fprintf(yyout, "%s,", get_dtype(results->value)); - ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL); + ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL, 0L, NULL, NULL); } drop_assignments(); fputs("ECPGd_EODT);\n", yyout); diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 95898478e2ab2427be4e26b53694e17d0487fca1..79b5c4c16fac92b9ca0e2ef290df0b151b2dd59e 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.82 2001/12/09 15:27:49 meskes Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.83 2001/12/23 12:17:41 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -219,9 +219,7 @@ param \${integer} ccomment "//".*\n -space [ \t\r\f] -space_or_nl [ \t\r\f\n] -line_end {space}*\n +space [ \t\n\r\f] horiz_space [ \t\f] newline [\n\r] non_newline [^\n\r] @@ -254,12 +252,12 @@ else [eE][lL][sS][eE] elif [eE][lL][iI][fF] endif [eE][nN][dD][iI][fF] -exec_sql {exec}{space_or_nl}*{sql}{space_or_nl}* +exec_sql {exec}{space}*{sql}{space}* ipdigit ({digit}|{digit}{digit}|{digit}{digit}{digit}) ip {ipdigit}\.{ipdigit}\.{ipdigit}\.{ipdigit} /* Take care of cpp continuation lines */ -cppline {space}*#(.*\\{line_end})*.* +cppline {space}*#(.*\\{space})*.* /* DO NOT PUT ANY COMMENTS IN THE FOLLOWING SECTION. * AT&T lex does not properly handle C-style comments in this second lex block. @@ -655,7 +653,7 @@ cppline {space}*#(.*\\{line_end})*.* "-" { return('-'); } "(" { return('('); } ")" { return(')'); } -{space_or_nl} { ECHO; } +{space} { ECHO; } \{ { return('{'); } \} { return('}'); } \[ { return('['); } @@ -679,13 +677,13 @@ cppline {space}*#(.*\\{line_end})*.* ".*" { return(S_DOTPOINT); } {other} { return S_ANYTHING; } -{exec_sql}{define}{space_or_nl}* { BEGIN(def_ident); } -{exec_sql}{include}{space_or_nl}* { BEGIN(incl); } +{exec_sql}{define}{space}* { BEGIN(def_ident); } +{exec_sql}{include}{space}* { BEGIN(incl); } -{exec_sql}{ifdef}{space_or_nl}* { ifcond = TRUE; BEGIN(xcond); } -{exec_sql}{ifndef}{space_or_nl}* { ifcond = FALSE; BEGIN(xcond); } +{exec_sql}{ifdef}{space}* { ifcond = TRUE; BEGIN(xcond); } +{exec_sql}{ifndef}{space}* { ifcond = FALSE; BEGIN(xcond); } -{exec_sql}{elif}{space_or_nl}* { /* pop stack */ +{exec_sql}{elif}{space}* { /* pop stack */ if ( preproc_tos == 0 ) { mmerror(PARSE_ERROR, ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'"); } @@ -699,7 +697,7 @@ cppline {space}*#(.*\\{line_end})*.* ifcond = TRUE; BEGIN(xcond); } -{exec_sql}{else}{space_or_nl}*";" { /* only exec sql endif pops the stack, so take care of duplicated 'else' */ +{exec_sql}{else}{space}*";" { /* only exec sql endif pops the stack, so take care of duplicated 'else' */ if ( stacked_if_value[preproc_tos].else_branch ) { mmerror(PARSE_ERROR, ET_FATAL, "Duplicated 'EXEC SQL ELSE;'"); } @@ -717,7 +715,7 @@ cppline {space}*#(.*\\{line_end})*.* } } } -{exec_sql}{endif}{space_or_nl}*";" { +{exec_sql}{endif}{space}*";" { if ( preproc_tos == 0 ) { mmerror(PARSE_ERROR, ET_FATAL, "Unmatched 'EXEC SQL ENDIF;'"); } @@ -735,7 +733,7 @@ cppline {space}*#(.*\\{line_end})*.* {other} { /* ignore */ } -{identifier}{space_or_nl}*";" { +{identifier}{space}*";" { if ( preproc_tos >= MAX_NESTED_IF-1 ) { mmerror(PARSE_ERROR, ET_FATAL, "Too many nested 'EXEC SQL IFDEF' conditions"); } @@ -773,7 +771,7 @@ cppline {space}*#(.*\\{line_end})*.* BEGIN(def); startlit(); } -{space_or_nl}*";" { +{space}*";" { struct _defines *ptr, *this; for (ptr = defines; ptr != NULL; ptr = ptr->next) diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 4884ae6b615d650cf6949f6c44afaf29b46a7953..d1d0f8db813f0b38d461b11798fb6dc8ab73a309 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -22,10 +22,13 @@ static char *actual_startline[STRUCT_DEPTH]; /* temporarily store struct members while creating the data structure */ struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL }; -struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, {NULL}}; +/* also store struct type so we can do a sizeof() later */ +static char *ECPGstruct_sizeof = NULL; + +struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, NULL, {NULL}}; struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL}; -struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, {NULL}}; +struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, NULL, {NULL}}; /* * Handle parsing errors and warnings @@ -3914,14 +3917,14 @@ connection_target: database_name opt_server opt_port $$ = $1; else if (strcmp($1, "?") == 0) /* variable */ { - enum ECPGttype typ = argsinsert->variable->type->typ; + enum ECPGttype type = argsinsert->variable->type->type; /* if array see what's inside */ - if (typ == ECPGt_array) - typ = argsinsert->variable->type->u.element->typ; + if (type == ECPGt_array) + type = argsinsert->variable->type->u.element->type; /* handle varchars */ - if (typ == ECPGt_varchar) + if (type == ECPGt_varchar) $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr")); else $$ = mm_strdup(argsinsert->variable->name); @@ -4002,14 +4005,14 @@ user_name: UserId { $$ = $1; else if (strcmp($1, "?") == 0) /* variable */ { - enum ECPGttype typ = argsinsert->variable->type->typ; + enum ECPGttype type = argsinsert->variable->type->type; /* if array see what's inside */ - if (typ == ECPGt_array) - typ = argsinsert->variable->type->u.element->typ; + if (type == ECPGt_array) + type = argsinsert->variable->type->u.element->type; /* handle varchars */ - if (typ == ECPGt_varchar) + if (type == ECPGt_varchar) $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr")); else $$ = mm_strdup(argsinsert->variable->name); @@ -4021,13 +4024,13 @@ user_name: UserId { char_variable: cvariable { /* check if we have a char variable */ struct variable *p = find_variable($1); - enum ECPGttype typ = p->type->typ; + enum ECPGttype type = p->type->type; /* if array see what's inside */ - if (typ == ECPGt_array) - typ = p->type->u.element->typ; + if (type == ECPGt_array) + type = p->type->u.element->type; - switch (typ) + switch (type) { case ECPGt_char: case ECPGt_unsigned_char: @@ -4267,10 +4270,10 @@ union_type: s_union '{' variable_declarations '}' s_struct: SQL_STRUCT opt_symbol { struct_member_list[struct_level++] = NULL; + $$ = cat2_str(make_str("struct"), $2); + ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), strdup($$), make_str(")")); if (struct_level >= STRUCT_DEPTH) mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure definition"); - - $$ = cat2_str(make_str("struct"), $2); }; s_union: UNION opt_symbol @@ -4360,9 +4363,9 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_initializer case ECPGt_struct: case ECPGt_union: if (dimension < 0) - type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum); + type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, ECPGstruct_sizeof); else - type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum), dimension); + type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, ECPGstruct_sizeof), dimension); $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4); break; @@ -4783,9 +4786,9 @@ ECPGVar: SQL_VAR case ECPGt_struct: case ECPGt_union: if (dimension < 0) - type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum); + type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, ECPGstruct_sizeof); else - type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum), dimension); + type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, ECPGstruct_sizeof), dimension); break; case ECPGt_varchar: if (dimension == -1) @@ -5337,7 +5340,7 @@ coutputvariable: cvariable indicator civarind: cvariable indicator { - if ($2 != NULL && (find_variable($2))->type->typ == ECPGt_array) + if ($2 != NULL && (find_variable($2))->type->type == ECPGt_array) mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input"); add_variable(&argsinsert, find_variable($1), ($2 == NULL) ? &no_indicator : find_variable($2)); diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index 8d2b7a59257aa766765cfd7befc8b4934f4dcf4e..6f6a6ff8d3a7d8d1c007f5ff4f5d06892817226c 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -2,7 +2,7 @@ #include "extern.h" -#define indicator_set ind_typ != NULL && ind_typ->typ != ECPGt_NO_INDICATOR +#define indicator_set ind_type != NULL && ind_type->type != ECPGt_NO_INDICATOR struct ECPGstruct_member struct_no_indicator = {"no_indicator", &ecpg_no_indicator, NULL}; @@ -40,17 +40,17 @@ ECPGstruct_member_dup(struct ECPGstruct_member * rm) { struct ECPGtype *type; - switch (rm->typ->typ) + switch (rm->type->type) { case ECPGt_struct: case ECPGt_union: - type = ECPGmake_struct_type(rm->typ->u.members, rm->typ->typ); + type = ECPGmake_struct_type(rm->type->u.members, rm->type->type, rm->type->struct_sizeof); break; case ECPGt_array: - type = ECPGmake_array_type(ECPGmake_simple_type(rm->typ->u.element->typ, rm->typ->u.element->size), rm->typ->size); + type = ECPGmake_array_type(ECPGmake_simple_type(rm->type->u.element->type, rm->type->u.element->size), rm->type->size); break; default: - type = ECPGmake_simple_type(rm->typ->typ, rm->typ->size); + type = ECPGmake_simple_type(rm->type->type, rm->type->size); break; } @@ -71,7 +71,7 @@ ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_mem (struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member)); ne->name = strdup(name); - ne->typ = type; + ne->type = type; ne->next = NULL; for (ptr = *start; ptr && ptr->next; ptr = ptr->next); @@ -83,41 +83,43 @@ ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_mem } struct ECPGtype * -ECPGmake_simple_type(enum ECPGttype typ, long siz) +ECPGmake_simple_type(enum ECPGttype type, long size) { struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype)); - ne->typ = typ; - ne->size = siz; + ne->type = type; + ne->size = size; ne->u.element = 0; + ne->struct_sizeof = NULL; return ne; } struct ECPGtype * -ECPGmake_array_type(struct ECPGtype * typ, long siz) +ECPGmake_array_type(struct ECPGtype * type, long size) { - struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, siz); + struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, size); - ne->u.element = typ; + ne->u.element = type; return ne; } struct ECPGtype * -ECPGmake_struct_type(struct ECPGstruct_member * rm, enum ECPGttype type) +ECPGmake_struct_type(struct ECPGstruct_member * rm, enum ECPGttype type, char *struct_sizeof) { struct ECPGtype *ne = ECPGmake_simple_type(type, 1); ne->u.members = ECPGstruct_member_dup(rm); + ne->struct_sizeof = struct_sizeof; return ne; } static const char * -get_type(enum ECPGttype typ) +get_type(enum ECPGttype type) { - switch (typ) + switch (type) { case ECPGt_char: return ("ECPGt_char"); @@ -171,7 +173,7 @@ get_type(enum ECPGttype typ) return ("ECPGt_descriptor"); break; default: - sprintf(errortext, "illegal variable type %d\n", typ); + sprintf(errortext, "illegal variable type %d\n", type); yyerror(errortext); } @@ -192,76 +194,76 @@ get_type(enum ECPGttype typ) size is the maxsize in case it is a varchar. Otherwise it is the size of the variable (required to do array fetches of structs). */ -static void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, +static void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type, long varcharsize, long arrsiz, const char *siz, const char *prefix); static void ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz, - struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offset, const char *prefix, const char *ind_prefix); + struct ECPGtype * type, struct ECPGtype * ind_type, const char *offset, const char *prefix, const char *ind_prefix); void -ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *ind_name, struct ECPGtype * ind_typ, const char *prefix, const char *ind_prefix) +ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type, const char *ind_name, struct ECPGtype * ind_type, const char *prefix, const char *ind_prefix, const long arr_str_siz, const char *struct_sizeof, const char *ind_struct_sizeof) { - switch (typ->typ) + switch (type->type) { case ECPGt_array: - if (indicator_set && ind_typ->typ != ECPGt_array) + if (indicator_set && ind_type->type != ECPGt_array) mmerror(INDICATOR_NOT_ARRAY, ET_FATAL, "Indicator for array/pointer has to be array/pointer.\n"); - switch (typ->u.element->typ) + switch (type->u.element->type) { case ECPGt_array: mmerror(PARSE_ERROR, ET_ERROR, "No nested arrays allowed (except strings)"); /* array of array */ break; case ECPGt_struct: case ECPGt_union: - ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, NULL, prefix, ind_prefix); + ECPGdump_a_struct(o, name, ind_name, type->size, type->u.element, (ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element, NULL, prefix, ind_prefix); break; default: - if (!IS_SIMPLE_TYPE(typ->u.element->typ)) + if (!IS_SIMPLE_TYPE(type->u.element->type)) yyerror("Internal error: unknown datatype, please inform pgsql-bugs@postgresql.org"); - ECPGdump_a_simple(o, name, typ->u.element->typ, - typ->u.element->size, typ->size, NULL, prefix); - if (ind_typ != NULL) + ECPGdump_a_simple(o, name, type->u.element->type, + type->u.element->size, type->size, NULL, prefix); + if (ind_type != NULL) { - if (ind_typ->typ == ECPGt_NO_INDICATOR) - ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); + if (ind_type->type == ECPGt_NO_INDICATOR) + ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, -1, NULL, ind_prefix); else - ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ, - ind_typ->u.element->size, ind_typ->size, NULL, prefix); + ECPGdump_a_simple(o, ind_name, ind_type->u.element->type, + ind_type->u.element->size, ind_type->size, NULL, prefix); } } break; case ECPGt_struct: - if (indicator_set && ind_typ->typ != ECPGt_struct) + if (indicator_set && ind_type->type != ECPGt_struct) mmerror(INDICATOR_NOT_STRUCT, ET_FATAL, "Indicator for struct has to be struct.\n"); - ECPGdump_a_struct(o, name, ind_name, 1, typ, ind_typ, NULL, prefix, ind_prefix); + ECPGdump_a_struct(o, name, ind_name, 1, type, ind_type, NULL, prefix, ind_prefix); break; case ECPGt_union: /* cannot dump a complete union */ yyerror("Type of union has to be specified"); break; case ECPGt_char_variable: - if (indicator_set && (ind_typ->typ == ECPGt_struct || ind_typ->typ == ECPGt_array)) + if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array)) mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "Indicator for simple datatype has to be simple.\n"); - ECPGdump_a_simple(o, name, typ->typ, 1, 1, NULL, prefix); - ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); + ECPGdump_a_simple(o, name, type->type, 1, arr_str_siz ? arr_str_siz : 1, struct_sizeof, prefix); + ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, arr_str_siz ? arr_str_siz : -1, ind_struct_sizeof, ind_prefix); break; case ECPGt_descriptor: - if (indicator_set && (ind_typ->typ == ECPGt_struct || ind_typ->typ == ECPGt_array)) + if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array)) mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "Indicator for simple datatype has to be simple.\n"); - ECPGdump_a_simple(o, name, typ->typ, 0, -1, NULL, prefix); - ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); + ECPGdump_a_simple(o, name, type->type, 0, -1, NULL, prefix); + ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, -1, NULL, ind_prefix); break; default: - if (indicator_set && (ind_typ->typ == ECPGt_struct || ind_typ->typ == ECPGt_array)) + if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array)) mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "Indicator for simple datatype has to be simple.\n"); - ECPGdump_a_simple(o, name, typ->typ, typ->size, -1, NULL, prefix); - if (ind_typ != NULL) - ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); + ECPGdump_a_simple(o, name, type->type, type->size, arr_str_siz ? arr_str_siz : -1, struct_sizeof, prefix); + if (ind_type != NULL) + ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, arr_str_siz ? arr_str_siz : -1, ind_struct_sizeof, ind_prefix); break; } } @@ -270,16 +272,16 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in /* If siz is NULL, then the offset is 0, if not use siz as a string, it represents the offset needed if we are in an array of structs. */ static void -ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, +ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type, long varcharsize, long arrsize, const char *siz, const char *prefix ) { - if (typ == ECPGt_NO_INDICATOR) + if (type == ECPGt_NO_INDICATOR) fprintf(o, "\n\tECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, "); - else if (typ == ECPGt_descriptor) + else if (type == ECPGt_descriptor) /* remember that name here already contains quotes (if needed) */ fprintf(o, "\n\tECPGt_descriptor, %s, 0L, 0L, 0L, ", name); else @@ -287,7 +289,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, char *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4); char *offset = (char *) mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1); - switch (typ) + switch (type) { case ECPGt_varchar: @@ -295,7 +297,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, * we have to use the pointer except for arrays with given * bounds */ - if (arrsize > 0) + if (arrsize > 0 && siz == NULL) sprintf(variable, "(%s%s)", prefix ? prefix : "", name); else sprintf(variable, "&(%s%s)", prefix ? prefix : "", name); @@ -310,7 +312,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, * we have to use the pointer except for arrays with given * bounds */ - if (varcharsize > 1 || arrsize > 0) + if ((varcharsize > 1 || arrsize > 0) && siz == NULL) sprintf(variable, "(%s%s)", prefix ? prefix : "", name); else sprintf(variable, "&(%s%s)", prefix ? prefix : "", name); @@ -323,22 +325,22 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, * we have to use the pointer except for arrays with given * bounds */ - if (arrsize > 0) + if (arrsize > 0 && siz== NULL) sprintf(variable, "(%s%s)", prefix ? prefix : "", name); else sprintf(variable, "&(%s%s)", prefix ? prefix : "", name); - sprintf(offset, "sizeof(%s)", ECPGtype_name(typ)); + sprintf(offset, "sizeof(%s)", ECPGtype_name(type)); break; } if (arrsize < 0) arrsize = 1; - if (siz == NULL) - fprintf(o, "\n\t%s,%s,%ldL,%ldL,%s, ", get_type(typ), variable, varcharsize, arrsize, offset); + if (siz == NULL || arrsize <= 1) + fprintf(o, "\n\t%s,%s,%ldL,%ldL,%s, ", get_type(type), variable, varcharsize, arrsize, offset); else - fprintf(o, "\n\t%s,%s,%ldL,%ldL,%s, ", get_type(typ), variable, varcharsize, arrsize, siz); + fprintf(o, "\n\t%s,%s,%ldL,%ldL,%s, ", get_type(type), variable, varcharsize, arrsize, siz); free(variable); free(offset); @@ -348,7 +350,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, /* Penetrate a struct and dump the contents. */ static void -ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix) +ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz, struct ECPGtype * type, struct ECPGtype * ind_type, const char *offsetarg, const char *prefix, const char *ind_prefix) { /* * If offset is NULL, then this is the first recursive level. If not @@ -370,31 +372,31 @@ ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz, else offset = offsetarg; - if (arrsiz != 0) + if (arrsiz == 1) sprintf(pbuf, "%s%s.", prefix ? prefix : "", name); else sprintf(pbuf, "%s%s->", prefix ? prefix : "", name); prefix = pbuf; - if (ind_typ == &ecpg_no_indicator) + if (ind_type == &ecpg_no_indicator) { ind_p = &struct_no_indicator; } - else if (ind_typ != NULL) + else if (ind_type != NULL) { - if (arrsiz != 0) + if (arrsiz == 1) sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name); else sprintf(ind_pbuf, "%s%s->", ind_prefix ? ind_prefix : "", ind_name); ind_prefix = ind_pbuf; - ind_p = ind_typ->u.members; + ind_p = ind_type->u.members; } - for (p = typ->u.members; p; p = p->next) + for (p = type->u.members; p; p = p->next) { - ECPGdump_a_type(o, p->name, p->typ, (ind_p != NULL) ? ind_p->name : NULL, (ind_p != NULL) ? ind_p->typ : NULL, prefix, ind_prefix); + ECPGdump_a_type(o, p->name, p->type, (ind_p != NULL) ? ind_p->name : NULL, (ind_p != NULL) ? ind_p->type : NULL, prefix, ind_prefix, arrsiz, type->struct_sizeof, (ind_p != NULL) ? ind_type->struct_sizeof : NULL); if (ind_p != NULL && ind_p != &struct_no_indicator) ind_p = ind_p->next; } @@ -409,20 +411,20 @@ ECPGfree_struct_member(struct ECPGstruct_member * rm) rm = rm->next; free(p->name); - free(p->typ); + free(p->type); free(p); } } void -ECPGfree_type(struct ECPGtype * typ) +ECPGfree_type(struct ECPGtype * type) { - if (!IS_SIMPLE_TYPE(typ->typ)) + if (!IS_SIMPLE_TYPE(type->type)) { - switch (typ->typ) + switch (type->type) { case ECPGt_array: - switch (typ->u.element->typ) + switch (type->u.element->type) { case ECPGt_array: yyerror("internal error, found multi-dimensional array\n"); @@ -430,33 +432,33 @@ ECPGfree_type(struct ECPGtype * typ) case ECPGt_struct: case ECPGt_union: /* Array of structs. */ - ECPGfree_struct_member(typ->u.element->u.members); - free(typ->u.element); + ECPGfree_struct_member(type->u.element->u.members); + free(type->u.element); break; default: - if (!IS_SIMPLE_TYPE(typ->u.element->typ)) + if (!IS_SIMPLE_TYPE(type->u.element->type)) yyerror("Internal error: unknown datatype, please inform pgsql-bugs@postgresql.org"); - free(typ->u.element); + free(type->u.element); } break; case ECPGt_struct: case ECPGt_union: - ECPGfree_struct_member(typ->u.members); + ECPGfree_struct_member(type->u.members); break; default: - sprintf(errortext, "illegal variable type %d\n", typ->typ); + sprintf(errortext, "illegal variable type %d\n", type->type); yyerror(errortext); break; } } - free(typ); + free(type); } const char * -get_dtype(enum ECPGdtype typ) +get_dtype(enum ECPGdtype type) { - switch (typ) + switch (type) { case ECPGd_count: return ("ECPGd_countr"); @@ -505,7 +507,7 @@ get_dtype(enum ECPGdtype typ) case ECPGd_cardinality: return ("ECPGd_cardinality"); default: - sprintf(errortext, "illegal descriptor item %d\n", typ); + sprintf(errortext, "illegal descriptor item %d\n", type); yyerror(errortext); } diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index 12e45ab43ac263181ac5b1175c03e0f7f97a9c17..e07dfc54f36fc7b23516062226356cd0d29e42e5 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -4,16 +4,17 @@ struct ECPGtype; struct ECPGstruct_member { char *name; - struct ECPGtype *typ; + struct ECPGtype *type; struct ECPGstruct_member *next; }; struct ECPGtype { - enum ECPGttype typ; + enum ECPGttype type; long size; /* For array it is the number of elements. * For varchar it is the maxsize of the * area. */ + char *struct_sizeof; /* For a struct this is the sizeof() type as string */ union { struct ECPGtype *element; /* For an array this is the type @@ -29,7 +30,7 @@ void ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, long); struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long); struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, long); -struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *, enum ECPGttype type); +struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *, enum ECPGttype, char *); struct ECPGstruct_member *ECPGstruct_member_dup(struct ECPGstruct_member *); /* Frees a type. */ @@ -46,16 +47,16 @@ void ECPGfree_type(struct ECPGtype *); size is the maxsize in case it is a varchar. Otherwise it is the size of the variable (required to do array fetches of structs). */ -void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const char *, struct ECPGtype *, const char *, const char *); +void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const char *, struct ECPGtype *, const char *, const char *, const long, const char *, const char *); /* A simple struct to keep a variable and its type. */ struct ECPGtemp_type { - struct ECPGtype *typ; + struct ECPGtype *type; const char *name; }; -extern const char *ECPGtype_name(enum ECPGttype typ); +extern const char *ECPGtype_name(enum ECPGttype type); /* some stuff for whenever statements */ enum WHEN_TYPE diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c index 4bb3748b63d7012852df52dcdaab988c9857f157..3131a76592adc7459d7f9d40395f5d71794fc73a 100644 --- a/src/interfaces/ecpg/preproc/variable.c +++ b/src/interfaces/ecpg/preproc/variable.c @@ -38,15 +38,15 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members) if (c == '\0') { /* found the end */ - switch (members->typ->typ) + switch (members->type->type) { case ECPGt_array: - return (new_variable(name, ECPGmake_array_type(members->typ->u.element, members->typ->size))); + return (new_variable(name, ECPGmake_array_type(members->type->u.element, members->type->size))); case ECPGt_struct: case ECPGt_union: - return (new_variable(name, ECPGmake_struct_type(members->typ->u.members, members->typ->typ))); + return (new_variable(name, ECPGmake_struct_type(members->type->u.members, members->type->type, members->type->struct_sizeof))); default: - return (new_variable(name, ECPGmake_simple_type(members->typ->typ, members->typ->size))); + return (new_variable(name, ECPGmake_simple_type(members->type->type, members->type->size))); } } else @@ -55,10 +55,10 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members) if (c == '-') { next++; - return (find_struct_member(name, next, members->typ->u.element->u.members)); + return (find_struct_member(name, next, members->type->u.element->u.members)); } else - return (find_struct_member(name, next, members->typ->u.members)); + return (find_struct_member(name, next, members->type->u.members)); } } } @@ -78,13 +78,13 @@ find_struct(char *name, char *next) if (c == '-') { - if (p->type->typ != ECPGt_array) + if (p->type->type != ECPGt_array) { sprintf(errortext, "variable %s is not a pointer", name); mmerror(PARSE_ERROR, ET_FATAL, errortext); } - if (p->type->u.element->typ != ECPGt_struct && p->type->u.element->typ != ECPGt_union) + if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union) { sprintf(errortext, "variable %s is not a pointer to a structure or a union", name); mmerror(PARSE_ERROR, ET_FATAL, errortext); @@ -98,7 +98,7 @@ find_struct(char *name, char *next) } else { - if (p->type->typ != ECPGt_struct && p->type->typ != ECPGt_union) + if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union) { sprintf(errortext, "variable %s is neither a structure nor a union", name); mmerror(PARSE_ERROR, ET_FATAL, errortext); @@ -242,7 +242,7 @@ dump_variables(struct arguments * list, int mode) /* Then the current element and its indicator */ ECPGdump_a_type(yyout, list->variable->name, list->variable->type, - list->indicator->name, list->indicator->type, NULL, NULL); + list->indicator->name, list->indicator->type, NULL, NULL, 0, NULL, NULL); /* Then release the list element. */ if (mode != 0) @@ -253,7 +253,7 @@ void check_indicator(struct ECPGtype * var) { /* make sure this is a valid indicator variable */ - switch (var->typ) + switch (var->type) { struct ECPGstruct_member *p; @@ -270,7 +270,7 @@ check_indicator(struct ECPGtype * var) case ECPGt_struct: case ECPGt_union: for (p = var->u.members; p; p = p->next) - check_indicator(p->typ); + check_indicator(p->type); break; case ECPGt_array: diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile index 5ce77ef9b7fa97d70df332b888fe46bf19ba21ef..c5b50c6e0fa0ee95ebe46a33fbbd07677ef4cc9c 100644 --- a/src/interfaces/ecpg/test/Makefile +++ b/src/interfaces/ecpg/test/Makefile @@ -1,10 +1,10 @@ -# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.32 2001/11/14 11:11:49 meskes Exp $ +# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.33 2001/12/23 12:17:41 meskes Exp $ subdir = src/interfaces/ecpg/test top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global -override CPPFLAGS := -I$(srcdir)/../include $(CPPFLAGS) +override CPPFLAGS := -I$(srcdir)/../include $(CPPFLAGS) -g ECPG = ../preproc/ecpg -I$(srcdir)/../include diff --git a/src/interfaces/ecpg/test/test1.pgc b/src/interfaces/ecpg/test/test1.pgc index d29b21df43b0b29dc3503a5e055dfcdfde36d425..c0b55b24b0dce2bf2db6ae6d4059bdccd0e7014e 100644 --- a/src/interfaces/ecpg/test/test1.pgc +++ b/src/interfaces/ecpg/test/test1.pgc @@ -1,4 +1,4 @@ -#include + #include exec sql include sqlca; @@ -34,6 +34,18 @@ exec sql begin declare section; int increment=100; char name[AMOUNT][8]; char letter[AMOUNT][1]; + struct name_letter_struct + { + char name[8]; + int amount; + char letter; + } name_letter[AMOUNT]; + struct ind_struct + { + short a; + short b; + short c; + } ind[AMOUNT]; char command[128]; char *connection="pm"; exec sql end declare section; @@ -113,16 +125,28 @@ exec sql end declare section; exec sql at pm insert into "Test" (name, amount, letter) values (:n, :a, :l); } + strcpy(msg, "commit"); + exec sql at pm commit; + strcpy(msg, "select"); exec sql at :connection select name, amount, letter into :name, :amount, :letter from "Test"; - printf("Database: pm\n"); + printf("Database: %s\n", connection); for (i=0, j=sqlca.sqlerrd[2]; i= 0) + if (i->ind_birth.born >= 0) printf(", born %ld", personal.birth.born); - if (ind_personal.ind_birth.age >= 0) + if (i->ind_birth.age >= 0) printf(", age = %d", personal.birth.age); if ((long)ind_married >= 0) printf(", married %s", married);