Commit d077c614 authored by Marc G. Fournier's avatar Marc G. Fournier

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.
parent 51f0f6dd
...@@ -475,5 +475,17 @@ Mon Feb 22 19:47:45 CET 1999 ...@@ -475,5 +475,17 @@ Mon Feb 22 19:47:45 CET 1999
requires me to increase the major version number. requires me to increase the major version number.
- Synced pgc.l with scan.l. - Synced pgc.l with scan.l.
- Added support for unions. - Added support for unions.
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.
- Set library version to 3.0.0 - Set library version to 3.0.0
- Set ecpg version to 3.0.0 - Set ecpg version to 3.0.0
...@@ -11,9 +11,11 @@ DESCRIPTOR statement will be ignored. ...@@ -11,9 +11,11 @@ DESCRIPTOR statement will be ignored.
it would be nice to be able to use :var[:index] as cvariable it would be nice to be able to use :var[:index] as cvariable
support for dynamic SQL with unknown number of variables with SQLDA structure it would also be nice to be able to work with varchar * (inculding automatic
allocating)
allocate memory for pointers as C input variables support for dynamic SQL with unknown number of variables with SQLDA structure
or something similar
Missing statements: Missing statements:
- exec sql allocate - exec sql allocate
......
...@@ -43,6 +43,7 @@ extern "C" ...@@ -43,6 +43,7 @@ extern "C"
ECPGt_varchar, ECPGt_varchar2, ECPGt_varchar, ECPGt_varchar2,
ECPGt_array, ECPGt_array,
ECPGt_struct, ECPGt_struct,
ECPGt_union,
ECPGt_char_variable, ECPGt_char_variable,
ECPGt_EOIT, /* End of insert types. */ ECPGt_EOIT, /* End of insert types. */
ECPGt_EORT, /* End of result types. */ ECPGt_EORT, /* End of result types. */
......
...@@ -64,6 +64,7 @@ struct variable ...@@ -64,6 +64,7 @@ struct variable
{ {
enum ECPGttype type; enum ECPGttype type;
void *value; void *value;
void *pointer;
long varcharsize; long varcharsize;
long arrsize; long arrsize;
long offset; long offset;
...@@ -91,6 +92,12 @@ struct prepared_statement ...@@ -91,6 +92,12 @@ struct prepared_statement
struct prepared_statement *next; struct prepared_statement *next;
} *prep_stmts = NULL; } *prep_stmts = NULL;
struct auto_mem
{
void *pointer;
struct auto_mem *next;
} *auto_allocs = NULL;
static int simple_debug = 0; static int simple_debug = 0;
static FILE *debugstream = NULL; static FILE *debugstream = NULL;
...@@ -98,12 +105,25 @@ static void ...@@ -98,12 +105,25 @@ static void
register_error(long code, char *fmt,...) register_error(long code, char *fmt,...)
{ {
va_list args; va_list args;
struct auto_mem *am;
sqlca.sqlcode = code; sqlca.sqlcode = code;
va_start(args, fmt); va_start(args, fmt);
vsprintf(sqlca.sqlerrm.sqlerrmc, fmt, args); vsprintf(sqlca.sqlerrm.sqlerrmc, fmt, args);
va_end(args); va_end(args);
sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc); 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 * static struct connection *
...@@ -166,7 +186,7 @@ ecpg_alloc(long size, int lineno) ...@@ -166,7 +186,7 @@ ecpg_alloc(long size, int lineno)
register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno); register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
return NULL; return NULL;
} }
memset(new, '\0', size); memset(new, '\0', size);
return (new); return (new);
} }
...@@ -186,6 +206,15 @@ ecpg_strdup(const char *string, int lineno) ...@@ -186,6 +206,15 @@ ecpg_strdup(const char *string, int lineno)
return (new); 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 \ /* This function returns a newly malloced string that has the ' and \
in the argument quoted with \. in the argument quoted with \.
*/ */
...@@ -301,10 +330,26 @@ create_statement(int lineno, struct connection *connection, struct statement ** ...@@ -301,10 +330,26 @@ create_statement(int lineno, struct connection *connection, struct statement **
return false; return false;
var->type = type; 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->varcharsize = va_arg(ap, long);
var->arrsize = va_arg(ap, long); var->arrsize = va_arg(ap, long);
var->offset = 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_type = va_arg(ap, enum ECPGttype);
var->ind_value = va_arg(ap, void *); var->ind_value = va_arg(ap, void *);
var->ind_varcharsize = va_arg(ap, long); var->ind_varcharsize = va_arg(ap, long);
...@@ -312,15 +357,6 @@ create_statement(int lineno, struct connection *connection, struct statement ** ...@@ -312,15 +357,6 @@ create_statement(int lineno, struct connection *connection, struct statement **
var->ind_offset = va_arg(ap, long); var->ind_offset = va_arg(ap, long);
var->next = NULL; 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); for (ptr = *list; ptr && ptr->next; ptr = ptr->next);
if (ptr == NULL) if (ptr == NULL)
...@@ -478,8 +514,7 @@ ECPGexecute(struct statement * stmt) ...@@ -478,8 +514,7 @@ ECPGexecute(struct statement * stmt)
break; break;
case ECPGt_char_variable: case ECPGt_char_variable:
{ {
/* set slen to string length if type is char * */ int slen = strlen((char *) var->value);
int slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
char *tmp; char *tmp;
if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno))) if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno)))
...@@ -632,13 +667,6 @@ ECPGexecute(struct statement * stmt) ...@@ -632,13 +667,6 @@ ECPGexecute(struct statement * stmt)
act_field; act_field;
case PGRES_TUPLES_OK: 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); nfields = PQnfields(results);
sqlca.sqlerrd[2] = ntuples = PQntuples(results); sqlca.sqlerrd[2] = ntuples = PQntuples(results);
status = true; status = true;
...@@ -676,18 +704,67 @@ ECPGexecute(struct statement * stmt) ...@@ -676,18 +704,67 @@ ECPGexecute(struct statement * stmt)
status = false; status = false;
break; 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); pval = PQgetvalue(results, act_tuple, act_field);
ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : ""); ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : "");
/* Now the pval is a pointer to the var->value. */ /* Now the pval is a pointer to the value. */
/* We will have to decode the var->value */ /* We will have to decode the value */
/* /*
* check for null var->value and set indicator * check for null value and set indicator
* accordingly * accordingly
*/ */
switch (var->ind_type) switch (var->ind_type)
...@@ -840,37 +917,28 @@ ECPGexecute(struct statement * stmt) ...@@ -840,37 +917,28 @@ ECPGexecute(struct statement * stmt)
case ECPGt_char: case ECPGt_char:
case ECPGt_unsigned_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* */ /* truncation */
strncpy(((char **) var->value)[act_tuple], pval, strlen(pval)); switch (var->ind_type)
(((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 */ case ECPGt_short:
switch (var->ind_type) case ECPGt_unsigned_short:
{ ((short *) var->ind_value)[act_tuple] = var->varcharsize;
case ECPGt_short: break;
case ECPGt_unsigned_short: case ECPGt_int:
((short *) var->ind_value)[act_tuple] = var->varcharsize; case ECPGt_unsigned_int:
break; ((int *) var->ind_value)[act_tuple] = var->varcharsize;
case ECPGt_int: break;
case ECPGt_unsigned_int: case ECPGt_long:
((int *) var->ind_value)[act_tuple] = var->varcharsize; case ECPGt_unsigned_long:
break; ((long *) var->ind_value)[act_tuple] = var->varcharsize;
case ECPGt_long: break;
case ECPGt_unsigned_long: default:
((long *) var->ind_value)[act_tuple] = var->varcharsize; break;
break;
default:
break;
}
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
} }
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
} }
} }
break; break;
...@@ -914,8 +982,7 @@ ECPGexecute(struct statement * stmt) ...@@ -914,8 +982,7 @@ ECPGexecute(struct statement * stmt)
break; break;
default: default:
register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.", register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.", ECPGtype_name(var->type), stmt->lineno);
ECPGtype_name(var->type), stmt->lineno);
status = false; status = false;
break; break;
} }
......
...@@ -20,7 +20,7 @@ preproc.c preproc.h: preproc.y ...@@ -20,7 +20,7 @@ preproc.c preproc.h: preproc.y
mv y.tab.h preproc.h mv y.tab.h preproc.h
clean: clean:
rm -f *.o core a.out ecpg$(X) *~ rm -f *.o core a.out ecpg$(X) *~ *.output *.tab.?
install: all install: all
$(INSTALL) $(INSTL_EXE_OPTS) ecpg$(X) $(DESTDIR)$(BINDIR) $(INSTALL) $(INSTL_EXE_OPTS) ecpg$(X) $(DESTDIR)$(BINDIR)
......
This diff is collapsed.
This diff is collapsed.
typedef union {
double dval;
int ival;
char * str;
struct when action;
struct index index;
int tagname;
struct this_type type;
enum ECPGttype type_enum;
} YYSTYPE;
#define SQL_AT 257
#define SQL_BOOL 258
#define SQL_BREAK 259
#define SQL_CALL 260
#define SQL_CONNECT 261
#define SQL_CONNECTION 262
#define SQL_CONTINUE 263
#define SQL_DEALLOCATE 264
#define SQL_DISCONNECT 265
#define SQL_ENUM 266
#define SQL_FOUND 267
#define SQL_FREE 268
#define SQL_GO 269
#define SQL_GOTO 270
#define SQL_IDENTIFIED 271
#define SQL_IMMEDIATE 272
#define SQL_INDICATOR 273
#define SQL_INT 274
#define SQL_LONG 275
#define SQL_OPEN 276
#define SQL_PREPARE 277
#define SQL_RELEASE 278
#define SQL_REFERENCE 279
#define SQL_SECTION 280
#define SQL_SEMI 281
#define SQL_SHORT 282
#define SQL_SIGNED 283
#define SQL_SQLERROR 284
#define SQL_SQLPRINT 285
#define SQL_SQLWARNING 286
#define SQL_START 287
#define SQL_STOP 288
#define SQL_STRUCT 289
#define SQL_UNSIGNED 290
#define SQL_VAR 291
#define SQL_WHENEVER 292
#define S_ANYTHING 293
#define S_AUTO 294
#define S_BOOL 295
#define S_CHAR 296
#define S_CONST 297
#define S_DOUBLE 298
#define S_ENUM 299
#define S_EXTERN 300
#define S_FLOAT 301
#define S_INT 302
#define S 303
#define S_LONG 304
#define S_REGISTER 305
#define S_SHORT 306
#define S_SIGNED 307
#define S_STATIC 308
#define S_STRUCT 309
#define S_UNION 310
#define S_UNSIGNED 311
#define S_VARCHAR 312
#define TYPECAST 313
#define ABSOLUTE 314
#define ACTION 315
#define ADD 316
#define ALL 317
#define ALTER 318
#define AND 319
#define ANY 320
#define AS 321
#define ASC 322
#define BEGIN_TRANS 323
#define BETWEEN 324
#define BOTH 325
#define BY 326
#define CASCADE 327
#define CASE 328
#define CAST 329
#define CHAR 330
#define CHARACTER 331
#define CHECK 332
#define CLOSE 333
#define COALESCE 334
#define COLLATE 335
#define COLUMN 336
#define COMMIT 337
#define CONSTRAINT 338
#define CREATE 339
#define CROSS 340
#define CURRENT 341
#define CURRENT_DATE 342
#define CURRENT_TIME 343
#define CURRENT_TIMESTAMP 344
#define CURRENT_USER 345
#define CURSOR 346
#define DAY_P 347
#define DECIMAL 348
#define DECLARE 349
#define DEFAULT 350
#define DELETE 351
#define DESC 352
#define DISTINCT 353
#define DOUBLE 354
#define DROP 355
#define ELSE 356
#define END_TRANS 357
#define EXCEPT 358
#define EXECUTE 359
#define EXISTS 360
#define EXTRACT 361
#define FALSE_P 362
#define FETCH 363
#define FLOAT 364
#define FOR 365
#define FOREIGN 366
#define FROM 367
#define FULL 368
#define GRANT 369
#define GROUP 370
#define HAVING 371
#define HOUR_P 372
#define IN 373
#define INNER_P 374
#define INSENSITIVE 375
#define INSERT 376
#define INTERSECT 377
#define INTERVAL 378
#define INTO 379
#define IS 380
#define ISOLATION 381
#define JOIN 382
#define KEY 383
#define LANGUAGE 384
#define LEADING 385
#define LEFT 386
#define LEVEL 387
#define LIKE 388
#define LOCAL 389
#define MATCH 390
#define MINUTE_P 391
#define MONTH_P 392
#define NAMES 393
#define NATIONAL 394
#define NATURAL 395
#define NCHAR 396
#define NEXT 397
#define NO 398
#define NOT 399
#define NULLIF 400
#define NULL_P 401
#define NUMERIC 402
#define OF 403
#define ON 404
#define ONLY 405
#define OPTION 406
#define OR 407
#define ORDER 408
#define OUTER_P 409
#define PARTIAL 410
#define POSITION 411
#define PRECISION 412
#define PRIMARY 413
#define PRIOR 414
#define PRIVILEGES 415
#define PROCEDURE 416
#define PUBLIC 417
#define READ 418
#define REFERENCES 419
#define RELATIVE 420
#define REVOKE 421
#define RIGHT 422
#define ROLLBACK 423
#define SCROLL 424
#define SECOND_P 425
#define SELECT 426
#define SET 427
#define SUBSTRING 428
#define TABLE 429
#define TEMP 430
#define THEN 431
#define TIME 432
#define TIMESTAMP 433
#define TIMEZONE_HOUR 434
#define TIMEZONE_MINUTE 435
#define TO 436
#define TRAILING 437
#define TRANSACTION 438
#define TRIM 439
#define TRUE_P 440
#define UNION 441
#define UNIQUE 442
#define UPDATE 443
#define USER 444
#define USING 445
#define VALUES 446
#define VARCHAR 447
#define VARYING 448
#define VIEW 449
#define WHEN 450
#define WHERE 451
#define WITH 452
#define WORK 453
#define YEAR_P 454
#define ZONE 455
#define TRIGGER 456
#define TYPE_P 457
#define ABORT_TRANS 458
#define AFTER 459
#define AGGREGATE 460
#define ANALYZE 461
#define BACKWARD 462
#define BEFORE 463
#define BINARY 464
#define CACHE 465
#define CLUSTER 466
#define COPY 467
#define CREATEDB 468
#define CREATEUSER 469
#define CYCLE 470
#define DATABASE 471
#define DELIMITERS 472
#define DO 473
#define EACH 474
#define ENCODING 475
#define EXPLAIN 476
#define EXTEND 477
#define FORWARD 478
#define FUNCTION 479
#define HANDLER 480
#define INCREMENT 481
#define INDEX 482
#define INHERITS 483
#define INSTEAD 484
#define ISNULL 485
#define LANCOMPILER 486
#define LIMIT 487
#define LISTEN 488
#define UNLISTEN 489
#define LOAD 490
#define LOCATION 491
#define LOCK_P 492
#define MAXVALUE 493
#define MINVALUE 494
#define MOVE 495
#define NEW 496
#define NOCREATEDB 497
#define NOCREATEUSER 498
#define NONE 499
#define NOTHING 500
#define NOTIFY 501
#define NOTNULL 502
#define OFFSET 503
#define OIDS 504
#define OPERATOR 505
#define PASSWORD 506
#define PROCEDURAL 507
#define RECIPE 508
#define RENAME 509
#define RESET 510
#define RETURNS 511
#define ROW 512
#define RULE 513
#define SERIAL 514
#define SEQUENCE 515
#define SETOF 516
#define SHOW 517
#define START 518
#define STATEMENT 519
#define STDIN 520
#define STDOUT 521
#define TRUSTED 522
#define UNTIL 523
#define VACUUM 524
#define VALID 525
#define VERBOSE 526
#define VERSION 527
#define IDENT 528
#define SCONST 529
#define Op 530
#define CSTRING 531
#define CVARIABLE 532
#define CPP_LINE 533
#define ICONST 534
#define PARAM 535
#define FCONST 536
#define OP 537
#define UMINUS 538
extern YYSTYPE yylval;
This diff is collapsed.
...@@ -47,7 +47,8 @@ ECPGstruct_member_dup(struct ECPGstruct_member * rm) ...@@ -47,7 +47,8 @@ ECPGstruct_member_dup(struct ECPGstruct_member * rm)
switch (rm->typ->typ) switch (rm->typ->typ)
{ {
case ECPGt_struct: case ECPGt_struct:
type = ECPGmake_struct_type(rm->typ->u.members); case ECPGt_union:
type = ECPGmake_struct_type(rm->typ->u.members, rm->typ->typ);
break; break;
case ECPGt_array: 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->typ->u.element->typ, rm->typ->u.element->size), rm->typ->size);
...@@ -108,9 +109,9 @@ ECPGmake_array_type(struct ECPGtype * typ, long siz) ...@@ -108,9 +109,9 @@ ECPGmake_array_type(struct ECPGtype * typ, long siz)
} }
struct ECPGtype * struct ECPGtype *
ECPGmake_struct_type(struct ECPGstruct_member * rm) ECPGmake_struct_type(struct ECPGstruct_member * rm, enum ECPGttype type)
{ {
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1); struct ECPGtype *ne = ECPGmake_simple_type(type, 1);
ne->u.members = ECPGstruct_member_dup(rm); ne->u.members = ECPGstruct_member_dup(rm);
...@@ -122,7 +123,7 @@ get_type(enum ECPGttype typ) ...@@ -122,7 +123,7 @@ get_type(enum ECPGttype typ)
{ {
switch (typ) switch (typ)
{ {
case ECPGt_char: case ECPGt_char:
return ("ECPGt_char"); return ("ECPGt_char");
break; break;
case ECPGt_unsigned_char: case ECPGt_unsigned_char:
...@@ -167,6 +168,8 @@ get_type(enum ECPGttype typ) ...@@ -167,6 +168,8 @@ get_type(enum ECPGttype typ)
sprintf(errortext, "illegal variable type %d\n", typ); sprintf(errortext, "illegal variable type %d\n", typ);
yyerror(errortext); yyerror(errortext);
} }
return NULL;
} }
/* Dump a type. /* Dump a type.
...@@ -202,38 +205,45 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in ...@@ -202,38 +205,45 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
switch (typ->typ) switch (typ->typ)
{ {
case ECPGt_array: case ECPGt_array:
if (IS_SIMPLE_TYPE(typ->u.element->typ)) switch (typ->u.element->typ)
{ {
ECPGdump_a_simple(o, name, typ->u.element->typ, case ECPGt_array:
yyerror("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);
break;
default:
if (!IS_SIMPLE_TYPE(typ->u.element->typ))
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); typ->u.element->size, typ->size, NULL, prefix);
if (ind_typ->typ == ECPGt_NO_INDICATOR) if (ind_typ->typ == ECPGt_NO_INDICATOR)
ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix);
else else
{
if (ind_typ->typ != ECPGt_array)
{ {
fprintf(stderr, "Indicator for an array has to be array too.\n"); if (ind_typ->typ != ECPGt_array)
exit(INDICATOR_NOT_ARRAY); {
} fprintf(stderr, "Indicator for an array has to be array too.\n");
ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ, exit(INDICATOR_NOT_ARRAY);
}
ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ,
ind_typ->u.element->size, ind_typ->size, NULL, prefix); ind_typ->u.element->size, ind_typ->size, NULL, prefix);
} }
}
else if (typ->u.element->typ == ECPGt_array)
{
yyerror("No nested arrays allowed (except strings)"); /* array of array */
}
else if (typ->u.element->typ == ECPGt_struct)
{
/* Array of structs */
ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, NULL, prefix, ind_prefix);
} }
else
yyerror("Internal error: unknown datatype, please inform pgsql-bugs@postgresql.org");
break; break;
case ECPGt_struct: case ECPGt_struct:
ECPGdump_a_struct(o, name, ind_name, 1, typ, ind_typ, NULL, prefix, ind_prefix); ECPGdump_a_struct(o, name, ind_name, 1, typ, ind_typ, NULL, prefix, ind_prefix);
break; break;
case ECPGt_union: /* cannot dump a complete union */
yyerror("Type of union has to be specified");
break;
case ECPGt_char_variable:
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);
break;
default: default:
ECPGdump_a_simple(o, name, typ->typ, typ->size, -1, NULL, prefix); ECPGdump_a_simple(o, name, typ->typ, typ->size, -1, NULL, prefix);
ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix);
...@@ -259,7 +269,9 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, ...@@ -259,7 +269,9 @@ 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 *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
char *offset = (char *) mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1); char *offset = (char *) mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1);
if (varcharsize == 0 || arrsize >= 0) /* if (varcharsize == 0 || arrsize >= 0)*/
/* we have to use the pointer except for arrays with given bounds */
if (arrsize > 0)
sprintf(variable, "(%s%s)", prefix ? prefix : "", name); sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
else else
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name); sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
...@@ -272,7 +284,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, ...@@ -272,7 +284,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
case ECPGt_char: case ECPGt_char:
case ECPGt_unsigned_char: case ECPGt_unsigned_char:
case ECPGt_char_variable: case ECPGt_char_variable:
sprintf(offset, "%ld*sizeof(char)", varcharsize); sprintf(offset, "%ld*sizeof(char)", varcharsize == 0 ? 1 : varcharsize);
break; break;
default: default:
sprintf(offset, "sizeof(%s)", ECPGtype_name(typ)); sprintf(offset, "sizeof(%s)", ECPGtype_name(typ));
...@@ -353,34 +365,36 @@ ECPGfree_type(struct ECPGtype * typ) ...@@ -353,34 +365,36 @@ ECPGfree_type(struct ECPGtype * typ)
{ {
if (!IS_SIMPLE_TYPE(typ->typ)) if (!IS_SIMPLE_TYPE(typ->typ))
{ {
if (typ->typ == ECPGt_array) switch(typ->typ)
{ {
if (IS_SIMPLE_TYPE(typ->u.element->typ)) case ECPGt_array:
free(typ->u.element); switch (typ->u.element->typ)
else if (typ->u.element->typ == ECPGt_array) {
/* Array of array, */ case ECPGt_array:
yyerror("internal error, found multi-dimensional array\n"); yyerror("internal error, found multi-dimensional array\n");
else if (typ->u.element->typ == ECPGt_struct) break;
{ case ECPGt_struct:
/* Array of structs. */ case ECPGt_union:
ECPGfree_struct_member(typ->u.element->u.members); /* Array of structs. */
ECPGfree_struct_member(typ->u.element->u.members);
free(typ->u.members);
break;
default:
if (!IS_SIMPLE_TYPE(typ->u.element->typ))
yyerror("Internal error: unknown datatype, please inform pgsql-bugs@postgresql.org");
free(typ->u.element);
}
break;
case ECPGt_struct:
case ECPGt_union:
ECPGfree_struct_member(typ->u.members);
free(typ->u.members); free(typ->u.members);
} break;
else default:
{ sprintf(errortext, "illegal variable type %d\n", typ->typ);
sprintf(errortext, "illegal variable type %d\n", typ);
yyerror(errortext); yyerror(errortext);
} break;
}
else if (typ->typ == ECPGt_struct)
{
ECPGfree_struct_member(typ->u.members);
free(typ->u.members);
}
else
{
sprintf(errortext, "illegal variable type %d\n", typ);
yyerror(errortext);
} }
} }
free(typ); free(typ);
......
...@@ -29,7 +29,7 @@ void ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member ...@@ -29,7 +29,7 @@ void ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member
struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, long); struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, long);
struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long); struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long);
struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, long); struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, long);
struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *); struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *, enum ECPGttype type);
struct ECPGstruct_member * ECPGstruct_member_dup(struct ECPGstruct_member *); struct ECPGstruct_member * ECPGstruct_member_dup(struct ECPGstruct_member *);
/* Frees a type. */ /* Frees a type. */
......
...@@ -5,8 +5,8 @@ exec sql include header_test; ...@@ -5,8 +5,8 @@ exec sql include header_test;
exec sql type c is char reference; exec sql type c is char reference;
typedef char* c; typedef char* c;
exec sql type ind is union { int integer; short smallinteger; }; exec sql type ind is union { int integer; short smallint; };
typedef union { int integer; short smallinteger; } ind; typedef union { int integer; short smallint; } ind;
int int
main () main ()
...@@ -23,7 +23,7 @@ exec sql begin declare section; ...@@ -23,7 +23,7 @@ exec sql begin declare section;
int ind_married; int ind_married;
ind children; ind children;
ind ind_children; ind ind_children;
char married[9]; char *married = NULL;
c testname="Petra"; c testname="Petra";
char *query="select name, born, age, married, children from meskes where name = :var1"; char *query="select name, born, age, married, children from meskes where name = :var1";
exec sql end declare section; exec sql end declare section;
...@@ -43,7 +43,7 @@ exec sql end declare section; ...@@ -43,7 +43,7 @@ exec sql end declare section;
exec sql connect to unix:postgresql://localhost:5432/mm; exec sql connect to unix:postgresql://localhost:5432/mm;
strcpy(msg, "create"); strcpy(msg, "create");
exec sql create table meskes(name char(8), born integer, age smallint, married char(8), children integer); exec sql create table meskes(name char(8), born integer, age smallint, married date, children integer);
strcpy(msg, "insert"); strcpy(msg, "insert");
exec sql insert into meskes(name, married, children) values ('Petra', '19900404', 3); exec sql insert into meskes(name, married, children) values ('Petra', '19900404', 3);
...@@ -62,17 +62,20 @@ exec sql end declare section; ...@@ -62,17 +62,20 @@ exec sql end declare section;
while (1) { while (1) {
strcpy(msg, "fetch"); strcpy(msg, "fetch");
exec sql fetch in cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallinteger; exec sql fetch in cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallint;
printf("%8.8s", personal.name.arr); printf("%8.8s", personal.name.arr);
if (!ind_personal.ind_birth.born) if (ind_personal.ind_birth.born >= 0)
printf(", born %d", personal.birth.born); printf(", born %d", personal.birth.born);
if (!ind_personal.ind_birth.age) if (ind_personal.ind_birth.age >= 0)
printf(", age = %d", personal.birth.age); printf(", age = %d", personal.birth.age);
if (!ind_married) if (ind_married >= 0)
printf(", married %s", married); printf(", married %10.10s", married);
if (!ind_children.smallinteger) if (ind_children.smallint >= 0)
printf(", children = %d", children.integer); printf(", children = %d", children.integer);
putchar('\n'); putchar('\n');
free(married);
married = NULL;
} }
strcpy(msg, "close"); strcpy(msg, "close");
...@@ -89,19 +92,21 @@ exec sql end declare section; ...@@ -89,19 +92,21 @@ exec sql end declare section;
while (1) { while (1) {
strcpy(msg, "fetch"); strcpy(msg, "fetch");
exec sql fetch in prep into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallinteger; exec sql fetch in prep into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallint;
printf("%8.8s", personal.name.arr); printf("%8.8s", personal.name.arr);
if (!ind_personal.ind_birth.born) if (ind_personal.ind_birth.born >= 0)
printf(", born %d", personal.birth.born); printf(", born %d", personal.birth.born);
if (!ind_personal.ind_birth.age) if (ind_personal.ind_birth.age >= 0)
printf(", age = %d", personal.birth.age); printf(", age = %d", personal.birth.age);
if (!ind_married) if (ind_married >= 0)
printf(", married %s", married); printf(", married %10.10s", married);
if (!ind_children.smallinteger) if (ind_children.smallint >= 0)
printf(", children = %d", children.integer); printf(", children = %d", children.integer);
putchar('\n'); putchar('\n');
} }
free(married);
strcpy(msg, "close"); strcpy(msg, "close");
exec sql close prep; exec sql close prep;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment