diff options
author | Marc G. Fournier <scrappy@hub.org> | 1999-02-28 07:25:34 +0000 |
---|---|---|
committer | Marc G. Fournier <scrappy@hub.org> | 1999-02-28 07:25:34 +0000 |
commit | d077c6149269701d0831634e8800b53c528d13ac (patch) | |
tree | ffca34f22c5fec39ebcd11c671003e9b11a4f103 /src/interfaces/ecpg/lib/ecpglib.c | |
parent | 51f0f6ddc8359d088a6d4892eec0ce90b485b501 (diff) | |
download | postgresql-d077c6149269701d0831634e8800b53c528d13ac.tar.gz postgresql-d077c6149269701d0831634e8800b53c528d13ac.zip |
From: Michael Meskes <Michael_Meskes@topmail.de>
+
+ Tue Feb 23 17:32:25 CET 1999
+
+ - Other than a struct a union itself cannot be specified as variable.
+
+ Fri Feb 26 07:18:25 CET 1999
+
+ - Synced preproc.y with gram.y.
+
+ Sat Feb 27 20:30:03 CET 1999
+
+ - Added automatic allocating for NULL pointers.
Diffstat (limited to 'src/interfaces/ecpg/lib/ecpglib.c')
-rw-r--r-- | src/interfaces/ecpg/lib/ecpglib.c | 179 |
1 files changed, 123 insertions, 56 deletions
diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c index e686edd512d..96da3b10e4e 100644 --- a/src/interfaces/ecpg/lib/ecpglib.c +++ b/src/interfaces/ecpg/lib/ecpglib.c @@ -64,6 +64,7 @@ struct variable { enum ECPGttype type; void *value; + void *pointer; long varcharsize; long arrsize; long offset; @@ -91,6 +92,12 @@ struct prepared_statement struct prepared_statement *next; } *prep_stmts = NULL; +struct auto_mem +{ + void *pointer; + struct auto_mem *next; +} *auto_allocs = NULL; + static int simple_debug = 0; static FILE *debugstream = NULL; @@ -98,12 +105,25 @@ static void register_error(long code, char *fmt,...) { va_list args; - + struct auto_mem *am; + sqlca.sqlcode = code; va_start(args, fmt); vsprintf(sqlca.sqlerrm.sqlerrmc, fmt, args); va_end(args); sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc); + + /* free all memory we allocate for the user */ + for (am = auto_allocs; am;) + { + struct auto_mem *act = am; + + am = am->next; + free(act->pointer); + free(act); + } + + auto_allocs = NULL; } static struct connection * @@ -166,7 +186,7 @@ ecpg_alloc(long size, int lineno) register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno); return NULL; } - + memset(new, '\0', size); return (new); } @@ -186,6 +206,15 @@ ecpg_strdup(const char *string, int lineno) return (new); } +static void +add_mem(void *ptr, int lineno) +{ + struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno); + + am->next = auto_allocs; + auto_allocs = am; +} + /* This function returns a newly malloced string that has the ' and \ in the argument quoted with \. */ @@ -301,10 +330,26 @@ create_statement(int lineno, struct connection *connection, struct statement ** return false; var->type = type; - var->value = va_arg(ap, void *); + var->pointer = va_arg(ap, void *); + + /* if variable is NULL, the statement hasn't been prepared */ + if (var->pointer == NULL) + { + ECPGlog("create_statement: invalid statement name\n"); + register_error(ECPG_INVALID_STMT, "Invalid statement name in line %d", lineno); + free(var); + return false; + } + var->varcharsize = va_arg(ap, long); var->arrsize = va_arg(ap, long); var->offset = va_arg(ap, long); + + if (var->arrsize == 0 || var->varcharsize == 0) + var->value = *((void **)(var->pointer)); + else + var->value = var->pointer; + var->ind_type = va_arg(ap, enum ECPGttype); var->ind_value = va_arg(ap, void *); var->ind_varcharsize = va_arg(ap, long); @@ -312,15 +357,6 @@ create_statement(int lineno, struct connection *connection, struct statement ** var->ind_offset = va_arg(ap, long); var->next = NULL; - /* if variable is NULL, the statement hasn't been prepared */ - if (var->value == NULL) - { - ECPGlog("create_statement: invalid statement name\n"); - register_error(ECPG_INVALID_STMT, "Invalid statement name in line %d", lineno); - free(var); - return false; - } - for (ptr = *list; ptr && ptr->next; ptr = ptr->next); if (ptr == NULL) @@ -478,8 +514,7 @@ ECPGexecute(struct statement * stmt) break; case ECPGt_char_variable: { - /* set slen to string length if type is char * */ - int slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize; + int slen = strlen((char *) var->value); char *tmp; if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno))) @@ -632,13 +667,6 @@ ECPGexecute(struct statement * stmt) act_field; case PGRES_TUPLES_OK: - - /* - * XXX Cheap Hack. For now, we see only the last group of - * tuples. This is clearly not the right way to do things - * !! - */ - nfields = PQnfields(results); sqlca.sqlerrd[2] = ntuples = PQntuples(results); status = true; @@ -676,18 +704,67 @@ ECPGexecute(struct statement * stmt) status = false; break; } - - for (act_tuple = 0; act_tuple < ntuples; act_tuple++) + + /* + * allocate memory for NULL pointers + */ + if (var->arrsize == 0 || var->varcharsize == 0) + { + switch(var->type) + { + case ECPGt_char: + case ECPGt_unsigned_char: + if (var->value == NULL) + { + var->varcharsize = 0; + /* check strlen for each tuple */ + for (act_tuple = 0; act_tuple < ntuples; act_tuple++) + { + int len = strlen(PQgetvalue(results, act_tuple, act_field)); + + if (len > var->varcharsize) + var->varcharsize = len; + } + var->offset *= var->varcharsize; + add_mem((void *)(var->value) = *((void **)(var->pointer)) = (void *) ecpg_alloc(var->offset * ntuples, stmt->lineno), stmt->lineno); + } + break; +#if 0 + case ECPGt_varchar: + if (((struct ECPGgeneric_varchar *)var->value)->arr == NULL) + { + var->varcharsize = 0; + /* check strlen for each tuple */ + for (act_tuple = 0; act_tuple < ntuples; act_tuple++) + { + int len = strlen(PQgetvalue(results, act_tuple, act_field)); + + if (len > var->varcharsize) + var->varcharsize = len; + + ((struct ECPGgeneric_varchar *) ((long) var->value + var->offset * act_tuple))->arr = (char *) ecpg_alloc(len, stmt->lineno); + } + } + break; +#endif + default: + if (var->value == NULL) + add_mem((void *)(var->value) = *((void **)(var->pointer)) = (void *) ecpg_alloc(var->offset * ntuples, stmt->lineno), stmt->lineno); + break; + } + } + + for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++) { pval = PQgetvalue(results, act_tuple, act_field); ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : ""); - /* Now the pval is a pointer to the var->value. */ - /* We will have to decode the var->value */ + /* Now the pval is a pointer to the value. */ + /* We will have to decode the value */ /* - * check for null var->value and set indicator + * check for null value and set indicator * accordingly */ switch (var->ind_type) @@ -840,37 +917,28 @@ ECPGexecute(struct statement * stmt) case ECPGt_char: case ECPGt_unsigned_char: { - if (var->varcharsize == 0) + strncpy((char *) ((long) var->value + var->offset * act_tuple), pval, var->varcharsize); + if (var->varcharsize && var->varcharsize < strlen(pval)) { - /* char* */ - strncpy(((char **) var->value)[act_tuple], pval, strlen(pval)); - (((char **) var->value)[act_tuple])[strlen(pval)] = '\0'; - } - else - { - strncpy((char *) ((long) var->value + var->offset * act_tuple), pval, var->varcharsize); - if (var->varcharsize < strlen(pval)) + /* truncation */ + switch (var->ind_type) { - /* truncation */ - switch (var->ind_type) - { - case ECPGt_short: - case ECPGt_unsigned_short: - ((short *) var->ind_value)[act_tuple] = var->varcharsize; - break; - case ECPGt_int: - case ECPGt_unsigned_int: - ((int *) var->ind_value)[act_tuple] = var->varcharsize; - break; - case ECPGt_long: - case ECPGt_unsigned_long: - ((long *) var->ind_value)[act_tuple] = var->varcharsize; - break; - default: - break; - } - sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W'; + case ECPGt_short: + case ECPGt_unsigned_short: + ((short *) var->ind_value)[act_tuple] = var->varcharsize; + break; + case ECPGt_int: + case ECPGt_unsigned_int: + ((int *) var->ind_value)[act_tuple] = var->varcharsize; + break; + case ECPGt_long: + case ECPGt_unsigned_long: + ((long *) var->ind_value)[act_tuple] = var->varcharsize; + break; + default: + break; } + sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W'; } } break; @@ -914,8 +982,7 @@ ECPGexecute(struct statement * stmt) break; default: - register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.", - ECPGtype_name(var->type), stmt->lineno); + register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.", ECPGtype_name(var->type), stmt->lineno); status = false; break; } |