diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c index 96da3b10e4..e4e0391942 100644 --- a/src/interfaces/ecpg/lib/ecpglib.c +++ b/src/interfaces/ecpg/lib/ecpglib.c @@ -113,7 +113,7 @@ register_error(long code, char *fmt,...) va_end(args); sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc); - /* free all memory we allocate for the user */ + /* free all memory we have allocated for the user */ for (am = auto_allocs; am;) { struct auto_mem *act = am; @@ -178,7 +178,7 @@ ECPGfinish(struct connection * act) static char * ecpg_alloc(long size, int lineno) { - char *new = (char *) malloc(size); + char *new = (char *) calloc(1L, size); if (!new) { @@ -344,7 +344,7 @@ create_statement(int lineno, struct connection *connection, struct statement ** 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 @@ -710,6 +710,8 @@ ECPGexecute(struct statement * stmt) */ if (var->arrsize == 0 || var->varcharsize == 0) { + int len = 0; + switch(var->type) { case ECPGt_char: @@ -720,38 +722,26 @@ ECPGexecute(struct statement * stmt) /* check strlen for each tuple */ for (act_tuple = 0; act_tuple < ntuples; act_tuple++) { - int len = strlen(PQgetvalue(results, act_tuple, act_field)); + int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1; 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); + len = var->offset * ntuples; } 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); - } - } + if (var->value == NULL) + len = ntuples * (var->varcharsize + sizeof (int)); 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); + len = var->offset * ntuples; break; } + + add_mem((void *)(var->value) = *((void **)(var->pointer)) = (void *) ecpg_alloc(len, stmt->lineno), stmt->lineno); } for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++) diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index a24b91b11e..b60cfdb184 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -573,6 +573,9 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim *dimension = type_dimension; } + if (*length >= 0 && *dimension >= 0 && pointer) + yyerror("No multi-dimensional array support"); + switch (type_enum) { case ECPGt_struct: @@ -589,9 +592,9 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim break; case ECPGt_varchar: - /* pointer has to get length 0 */ + /* pointer has to get dimension 0 */ if (pointer) - *length=0; + *dimension = 0; /* one index is the string length */ if (*length < 0) @@ -3721,11 +3724,11 @@ a_expr: attr opt_indirection } | a_expr IN '(' in_expr ')' { - $$ = make4_str($1, make1_str("in ("), $4, make1_str(")")); + $$ = make4_str($1, make1_str(" in ("), $4, make1_str(")")); } | a_expr NOT IN '(' not_in_expr ')' { - $$ = make4_str($1, make1_str("not in ("), $5, make1_str(")")); + $$ = make4_str($1, make1_str(" not in ("), $5, make1_str(")")); } | a_expr Op '(' SubSelect ')' { @@ -4838,7 +4841,8 @@ type: simple_type { $$.type_str = $1; $$.type_enum = ECPGt_int; - $$.type_dimension = -1; + + $$.type_dimension = -1; $$.type_index = -1; } | symbol @@ -4846,7 +4850,7 @@ type: simple_type /* this is for typedef'ed types */ struct typedefs *this = get_typedef($1); - $$.type_str = mm_strdup(this->name); + $$.type_str = (this->type->type_enum == ECPGt_varchar) ? make1_str("") : mm_strdup(this->name); $$.type_enum = this->type->type_enum; $$.type_dimension = this->type->type_dimension; $$.type_index = this->type->type_index; @@ -4945,8 +4949,6 @@ variable: opt_pointer symbol opt_array_bounds opt_initializer switch(dimension) { case 0: - strcpy(dim, "[]"); - break; case -1: case 1: *dim = '\0'; @@ -4957,11 +4959,14 @@ variable: opt_pointer symbol opt_array_bounds opt_initializer } sprintf(ascii_len, "%d", length); - if (length > 0) - $$ = make4_str(make5_str(mm_strdup(actual_storage[struct_level]), make1_str(" struct varchar_"), mm_strdup($2), make1_str(" { int len; char arr["), mm_strdup(ascii_len)), make1_str("]; } "), mm_strdup($2), mm_strdup(dim)); - else - yyerror ("pointer to varchar are not implemented yet"); -/* $$ = make4_str(make3_str(mm_strdup(actual_storage[struct_level]), make1_str(" struct varchar_"), mm_strdup($2)), make1_str(" { int len; char *arr; }"), mm_strdup($2), mm_strdup(dim));*/ + if (length == 0) + yyerror ("pointer to varchar are not implemented"); + + if (dimension == 0) + $$ = make4_str(make5_str(mm_strdup(actual_storage[struct_level]), make1_str(" struct varchar_"), mm_strdup($2), make1_str(" { int len; char arr["), mm_strdup(ascii_len)), make1_str("]; } *"), mm_strdup($2), $4); + else + $$ = make5_str(make5_str(mm_strdup(actual_storage[struct_level]), make1_str(" struct varchar_"), mm_strdup($2), make1_str(" { int len; char arr["), mm_strdup(ascii_len)), make1_str("]; } "), mm_strdup($2), mm_strdup(dim), $4); + break; case ECPGt_char: case ECPGt_unsigned_char: diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile index 2c4ba01ee0..23bda07a3b 100644 --- a/src/interfaces/ecpg/test/Makefile +++ b/src/interfaces/ecpg/test/Makefile @@ -1,4 +1,4 @@ -all: test1 test2 perftest +all: test1 test2 test3 perftest LDFLAGS=-g -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg -lpq -lcrypt @@ -10,9 +10,13 @@ test2: test2.c test2.c: test2.pgc /usr/local/pgsql/bin/ecpg $? +test3: test3.c +test3.c: test3.pgc + /usr/local/pgsql/bin/ecpg $? + perftest: perftest.c perftest.c:perftest.pgc /usr/local/pgsql/bin/ecpg $? clean: - -/bin/rm test1 test2 perftest *.c log + -/bin/rm test1 test2 test3 perftest *.c log diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc index f50a9d5100..3853b8c33e 100644 --- a/src/interfaces/ecpg/test/test2.pgc +++ b/src/interfaces/ecpg/test/test2.pgc @@ -8,19 +8,21 @@ typedef char* c; exec sql type ind is union { int integer; short smallint; }; typedef union { int integer; short smallint; } ind; +exec sql type str is varchar[8]; + int main () { typedef struct { long born; short age; } birthinfo; exec sql type birthinfo is struct { long born; short age; }; exec sql begin declare section; - struct personal_struct { varchar name[8]; + struct personal_struct { str name; birthinfo birth; } personal; struct personal_indicator { int ind_name; birthinfo ind_birth; } ind_personal; - int ind_married; + float ind_married; ind children; ind ind_children; char *married = NULL; @@ -68,8 +70,8 @@ exec sql end declare section; printf(", born %d", personal.birth.born); if (ind_personal.ind_birth.age >= 0) printf(", age = %d", personal.birth.age); - if (ind_married >= 0) - printf(", married %10.10s", married); + if ((long)ind_married >= 0) + printf(", married %s", married); if (ind_children.smallint >= 0) printf(", children = %d", children.integer); putchar('\n'); @@ -98,8 +100,8 @@ exec sql end declare section; printf(", born %d", personal.birth.born); if (ind_personal.ind_birth.age >= 0) printf(", age = %d", personal.birth.age); - if (ind_married >= 0) - printf(", married %10.10s", married); + if ((long)ind_married >= 0) + printf(", married %s", married); if (ind_children.smallint >= 0) printf(", children = %d", children.integer); putchar('\n');