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

From: Michael Meskes <Michael_Meskes@topmail.de>

+
+ Son Feb 21 14:10:47 CET 1999
+
+       - Fixed variable detection in libecpg.
+
+ Mon Feb 22 19:47:45 CET 1999
+
+       - Added 'at <db_connection>' option to all commands it is apllicable
+         to. Due to changing the API of some libecpg functions this
+         requires me to increase the major version number.
+       - Synced pgc.l with scan.l.
+       - Added support for unions.
+       - Set library version to 3.0.0
+       - Set ecpg version to 3.0.0
parent e17d8448
......@@ -463,3 +463,17 @@ Fri Feb 19 21:40:14 CET 1999
- Fixed bug in libecpg that caused it to start transactions only for
the first connection.
- Set library version to 2.7.1
Son Feb 21 14:10:47 CET 1999
- Fixed variable detection in libecpg.
Mon Feb 22 19:47:45 CET 1999
- Added 'at <db_connection>' option to all commands it is apllicable
to. Due to changing the API of some libecpg functions this
requires me to increase the major version number.
- Synced pgc.l with scan.l.
- Added support for unions.
- Set library version to 3.0.0
- Set ecpg version to 3.0.0
......@@ -11,9 +11,9 @@ DESCRIPTOR statement will be ignored.
it would be nice to be able to use :var[:index] as cvariable
'at DB connection' is missing for several commands (is this standard?)
support for dynamic SQL with unknown number of variables with SQLDA structure
support for unions
allocate memory for pointers as C input variables
Missing statements:
- exec sql allocate
......
......@@ -8,8 +8,8 @@ extern "C"
void ECPGdebug(int, FILE *);
bool ECPGsetconn(int, const char *);
bool ECPGconnect(int, const char *, const char *, const char *, const char *);
bool ECPGdo(int, char *,...);
bool ECPGtrans(int, const char *);
bool ECPGdo(int, const char *, char *,...);
bool ECPGtrans(int, const char *, const char *);
bool ECPGdisconnect(int, const char *);
bool ECPGprepare(int, char *, char *);
bool ECPGdeallocate(int, char *);
......
......@@ -43,10 +43,10 @@ extern "C"
ECPGt_varchar, ECPGt_varchar2,
ECPGt_array,
ECPGt_struct,
ECPGt_char_variable,
ECPGt_EOIT, /* End of insert types. */
ECPGt_EORT, /* End of result types. */
ECPGt_NO_INDICATOR, /* no indicator */
ECPGt_char_variable
ECPGt_NO_INDICATOR /* no indicator */
};
#define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_varchar2)
......
......@@ -6,13 +6,13 @@
# Copyright (c) 1994, Regents of the University of California
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.42 1999/02/21 03:02:35 scrappy Exp $
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.43 1999/02/23 12:56:55 scrappy Exp $
#
#-------------------------------------------------------------------------
NAME= ecpg
SO_MAJOR_VERSION= 2
SO_MINOR_VERSION= 7.1
SO_MAJOR_VERSION= 3
SO_MINOR_VERSION= 0.0
SRCDIR= @top_srcdir@
include $(SRCDIR)/Makefile.global
......
This diff is collapsed.
SRCDIR= ../../..
include $(SRCDIR)/Makefile.global
MAJOR_VERSION=2
MINOR_VERSION=5
MAJOR_VERSION=3
MINOR_VERSION=0
PATCHLEVEL=0
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
......
......@@ -36,6 +36,7 @@ static ScanKeyword ScanKeywords[] = {
{"signed", S_SIGNED},
{"static", S_STATIC},
{"struct", S_STRUCT},
{"union", S_UNION},
{"unsigned", S_UNSIGNED},
{"varchar", S_VARCHAR},
};
......
......@@ -165,6 +165,7 @@ main(int argc, char *const argv[])
struct arguments *l1, *l2;
free(ptr->command);
free(ptr->connection);
free(ptr->name);
for (l1 = ptr->argsinsert; l1; l1 = l2)
{
......
......@@ -20,6 +20,7 @@
*/
static ScanKeyword ScanKeywords[] = {
/* name value */
{"at", SQL_AT},
{"bool", SQL_BOOL},
{"break", SQL_BREAK},
{"call", SQL_CALL},
......
......@@ -6,7 +6,7 @@
extern int braces_open,
no_auto_trans, struct_level;
extern char *yytext;
extern char *yytext, errortext[128];
extern int yylineno,
yyleng;
extern FILE *yyin,
......
......@@ -105,7 +105,6 @@ xqstart {quote}
xqstop {quote}
xqdouble {quote}{quote}
xqinside [^\\']*
xqembedded "\\'"
xqliteral [\\](.|\n)
xqcat {quote}{space}*\n{space}*{quote}
......@@ -244,22 +243,9 @@ cppline {space}*#.*(\\{space}*\n)*\n*
return SCONST;
}
<xq>{xqdouble} |
<xq>{xqinside} {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
yyerror("ERROR: quoted string parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng;
}
<xq>{xqembedded} {
if ((llen+yyleng-1) > (MAX_PARSE_BUFFER - 1))
yyerror("ERROR: quoted string parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
*(literal+llen) = '\'';
llen += yyleng;
}
<xq>{xqinside} |
<xq>{xqliteral} {
if ((llen+yyleng-1) > (MAX_PARSE_BUFFER - 1))
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
yyerror("ERROR: quoted string parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng;
......
......@@ -18,7 +18,8 @@
* Variables containing simple states.
*/
int struct_level = 0;
static char errortext[128];
char errortext[128];
static char *connection = NULL;
static int QueryIsRule = 0, ForUpdateNotAllowed = 0;
static struct this_type actual_type[STRUCT_DEPTH];
static char *actual_storage[STRUCT_DEPTH];
......@@ -489,7 +490,7 @@ output_statement(char * stmt, int mode)
{
int i, j=strlen(stmt);
fputs("ECPGdo(__LINE__, \"", yyout);
fprintf(yyout, "ECPGdo(__LINE__, %s, \"", connection ? connection : "NULL");
/* do this char by char as we have to filter '\"' */
for (i = 0;i < j; i++)
......@@ -504,6 +505,8 @@ output_statement(char * stmt, int mode)
fputs("ECPGt_EORT);", yyout);
whenever_action(mode);
free(stmt);
if (connection != NULL)
free(connection);
}
static struct typedefs *
......@@ -612,7 +615,7 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
}
/* special embedded SQL token */
%token SQL_BOOL SQL_BREAK
%token SQL_AT SQL_BOOL SQL_BREAK
%token SQL_CALL SQL_CONNECT SQL_CONNECTION SQL_CONTINUE
%token SQL_DEALLOCATE SQL_DISCONNECT SQL_ENUM
%token SQL_FOUND SQL_FREE SQL_GO SQL_GOTO
......@@ -625,8 +628,8 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
/* C token */
%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_ENUM S_EXTERN
%token S_FLOAT S_INT S
%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
%token S_UNSIGNED S_VARCHAR
%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
%token S_UNION S_UNSIGNED S_VARCHAR
/* I need this and don't know where it is defined inside the backend */
%token TYPECAST
......@@ -785,8 +788,9 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
%type <str> ECPGSetConnection c_line cpp_line s_enum ECPGTypedef
%type <str> enum_type civariableonly ECPGCursorStmt ECPGDeallocate
%type <str> ECPGFree ECPGDeclare ECPGVar sql_variable_declarations
%type <str> sql_declaration sql_variable_list sql_variable
%type <str> sql_declaration sql_variable_list sql_variable opt_at
%type <str> struct_type s_struct declaration variable_declarations
%type <str> s_struct_or_union sql_struct_or_union
%type <type_enum> simple_type varchar_type
......@@ -803,13 +807,16 @@ prog: statements;
statements: /* empty */
| statements statement
statement: ecpgstart stmt SQL_SEMI
statement: ecpgstart opt_at stmt SQL_SEMI { connection = NULL; }
| ecpgstart stmt SQL_SEMI
| ECPGDeclaration
| c_thing { fprintf(yyout, "%s", $1); free($1); }
| cpp_line { fprintf(yyout, "%s", $1); free($1); }
| blockstart { fputs($1, yyout); free($1); }
| blockend { fputs($1, yyout); free($1); }
opt_at: SQL_AT connection_target { connection = $2; }
stmt: AddAttrStmt { output_statement($1, 0); }
| AlterUserStmt { output_statement($1, 0); }
| ClosePortalStmt { output_statement($1, 0); }
......@@ -853,7 +860,7 @@ stmt: AddAttrStmt { output_statement($1, 0); }
}
| RuleStmt { output_statement($1, 0); }
| TransactionStmt {
fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $1);
fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
whenever_action(0);
free($1);
}
......@@ -866,6 +873,9 @@ stmt: AddAttrStmt { output_statement($1, 0); }
| VariableShowStmt { output_statement($1, 0); }
| VariableResetStmt { output_statement($1, 0); }
| ECPGConnect {
if (connection)
yyerror("no at option for connect statement.\n");
fprintf(yyout, "no_auto_trans = %d;\n", no_auto_trans);
fprintf(yyout, "ECPGconnect(__LINE__, %s);", $1);
whenever_action(0);
......@@ -876,6 +886,9 @@ stmt: AddAttrStmt { output_statement($1, 0); }
free($1);
}
| ECPGDeallocate {
if (connection)
yyerror("no at option for connect statement.\n");
fputs($1, yyout);
whenever_action(0);
free($1);
......@@ -885,6 +898,9 @@ stmt: AddAttrStmt { output_statement($1, 0); }
free($1);
}
| ECPGDisconnect {
if (connection)
yyerror("no at option for disconnect statement.\n");
fprintf(yyout, "ECPGdisconnect(__LINE__, \"%s\");", $1);
whenever_action(0);
free($1);
......@@ -893,7 +909,7 @@ stmt: AddAttrStmt { output_statement($1, 0); }
output_statement($1, 0);
}
| ECPGFree {
fprintf(yyout, "ECPGdeallocate(__LINE__, \"%s\");", $1);
fprintf(yyout, "ECPGdeallocate(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
whenever_action(0);
free($1);
}
......@@ -912,7 +928,7 @@ stmt: AddAttrStmt { output_statement($1, 0); }
yyerror(errortext);
}
fprintf(yyout, "ECPGdo(__LINE__, \"%s\",", ptr->command);
fprintf(yyout, "ECPGdo(__LINE__, %s, \"%s\",", ptr->connection ? ptr->connection : "NULL", ptr->command);
/* dump variables to C file*/
dump_variables(ptr->argsinsert, 0);
dump_variables(argsinsert, 0);
......@@ -923,25 +939,40 @@ stmt: AddAttrStmt { output_statement($1, 0); }
free($1);
}
| ECPGPrepare {
if (connection)
yyerror("no at option for set connection statement.\n");
fprintf(yyout, "ECPGprepare(__LINE__, %s);", $1);
whenever_action(0);
free($1);
}
| ECPGRelease { /* output already done */ }
| ECPGSetConnection {
if (connection)
yyerror("no at option for set connection statement.\n");
fprintf(yyout, "ECPGsetconn(__LINE__, %s);", $1);
whenever_action(0);
free($1);
}
| ECPGTypedef {
if (connection)
yyerror("no at option for typedef statement.\n");
fputs($1, yyout);
free($1);
}
| ECPGVar {
if (connection)
yyerror("no at option for var statement.\n");
fputs($1, yyout);
free($1);
}
| ECPGWhenever {
if (connection)
yyerror("no at option for whenever statement.\n");
fputs($1, yyout);
output_line_number();
free($1);
......@@ -2727,6 +2758,7 @@ CursorStmt: DECLARE name opt_cursor CURSOR FOR SelectStmt cursor_clause
/* initial definition */
this->next = cur;
this->name = $2;
this->connection = connection;
this->command = cat2_str(cat5_str(make1_str("declare"), mm_strdup($2), $3, make1_str("cursor for"), $6), $7);
this->argsinsert = argsinsert;
this->argsresult = argsresult;
......@@ -3103,6 +3135,7 @@ Generic: generic
generic: ident { $$ = $1; }
| TYPE_P { $$ = make1_str("type"); }
| SQL_AT { $$ = make1_str("at"); }
| SQL_BOOL { $$ = make1_str("bool"); }
| SQL_BREAK { $$ = make1_str("break"); }
| SQL_CALL { $$ = make1_str("call"); }
......@@ -4306,6 +4339,7 @@ ColId: ident { $$ = $1; }
| VALID { $$ = make1_str("valid"); }
| VERSION { $$ = make1_str("version"); }
| ZONE { $$ = make1_str("zone"); }
| SQL_AT { $$ = make1_str("at"); }
| SQL_BOOL { $$ = make1_str("bool"); }
| SQL_BREAK { $$ = make1_str("break"); }
| SQL_CALL { $$ = make1_str("call"); }
......@@ -4602,6 +4636,7 @@ ECPGCursorStmt: DECLARE name opt_cursor CURSOR FOR ident cursor_clause
/* initial definition */
this->next = cur;
this->name = $2;
this->connection = connection;
this->command = cat5_str(make1_str("declare"), mm_strdup($2), $3, make1_str("cursor for ;;"), $7);
this->argsresult = NULL;
......@@ -4731,14 +4766,17 @@ struct_type: s_struct '{' variable_declarations '}'
$$ = cat4_str($1, make1_str("{"), $3, make1_str("}"));
}
s_struct : S_STRUCT opt_symbol
s_struct : s_struct_or_union opt_symbol
{
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
yyerror("Too many levels in nested structure definition");
$$ = cat2_str(make1_str("struct"), $2);
$$ = cat2_str($1, $2);
}
s_struct_or_union: S_STRUCT { $$ = make1_str("struct"); }
| S_UNION { $$ = make1_str("union"); }
opt_symbol: /* empty */ { $$ = make1_str(""); }
| symbol { $$ = $1; }
......@@ -4940,7 +4978,7 @@ ECPGRelease: TransactionStmt SQL_RELEASE
if (strncmp($1, "begin", 5) == 0)
yyerror("RELEASE does not make sense when beginning a transaction");
fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $1);
fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");", connection, $1);
whenever_action(0);
fprintf(yyout, "ECPGdisconnect(\"\");");
whenever_action(0);
......@@ -5151,7 +5189,7 @@ ctype: CHAR
$$.type_index = -1;
$$.type_dimension = -1;
}
| SQL_STRUCT
| sql_struct_or_union
{
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
......@@ -5159,7 +5197,7 @@ ctype: CHAR
} '{' sql_variable_declarations '}'
{
ECPGfree_struct_member(struct_member_list[struct_level--]);
$$.type_str = cat3_str(make1_str("struct {"), $4, make1_str("}"));
$$.type_str = cat4_str($1, make1_str("{"), $4, make1_str("}"));
$$.type_enum = ECPGt_struct;
$$.type_index = -1;
$$.type_dimension = -1;
......@@ -5175,6 +5213,9 @@ ctype: CHAR
struct_member_list[struct_level] = this->struct_member_list;
}
sql_struct_or_union: SQL_STRUCT { $$ = make1_str("struct"); }
| UNION { $$ = make1_str("union"); }
opt_signed: SQL_SIGNED | /* empty */
sql_variable_declarations: /* empty */
......@@ -5735,6 +5776,7 @@ c_anything: IDENT { $$ = $1; }
| S_SIGNED { $$ = make1_str("signed"); }
| S_STATIC { $$ = make1_str("static"); }
| S_STRUCT { $$ = make1_str("struct"); }
| S_UNION { $$ = make1_str("union"); }
| S_UNSIGNED { $$ = make1_str("unsigned"); }
| S_VARCHAR { $$ = make1_str("varchar"); }
| S_ANYTHING { $$ = make_name(); }
......
......@@ -164,7 +164,8 @@ get_type(enum ECPGttype typ)
return ("ECPGt_char_variable");
break;
default:
abort();
sprintf(errortext, "illegal variable type %d\n", typ);
yyerror(errortext);
}
}
......@@ -357,7 +358,8 @@ ECPGfree_type(struct ECPGtype * typ)
if (IS_SIMPLE_TYPE(typ->u.element->typ))
free(typ->u.element);
else if (typ->u.element->typ == ECPGt_array)
abort(); /* Array of array, */
/* Array of array, */
yyerror("internal error, found multi-dimensional array\n");
else if (typ->u.element->typ == ECPGt_struct)
{
/* Array of structs. */
......@@ -365,7 +367,10 @@ ECPGfree_type(struct ECPGtype * typ)
free(typ->u.members);
}
else
abort();
{
sprintf(errortext, "illegal variable type %d\n", typ);
yyerror(errortext);
}
}
else if (typ->typ == ECPGt_struct)
{
......@@ -373,7 +378,10 @@ ECPGfree_type(struct ECPGtype * typ)
free(typ->u.members);
}
else
abort();
{
sprintf(errortext, "illegal variable type %d\n", typ);
yyerror(errortext);
}
}
free(typ);
}
......@@ -101,6 +101,7 @@ struct cursor
{
char *name;
char *command;
char *connection;
struct arguments *argsinsert;
struct arguments *argsresult;
struct cursor *next;
......
......@@ -15,4 +15,4 @@ perftest.c:perftest.pgc
/usr/local/pgsql/bin/ecpg $?
clean:
/bin/rm test1 test2 perftest *.c log
-/bin/rm test1 test2 perftest *.c log
......@@ -4,7 +4,7 @@ exec sql whenever sqlerror sqlprint;
exec sql include sqlca;
exec sql define AMOUNT 8;
exec sql define AMOUNT 4;
exec sql type intarray is int[AMOUNT];
exec sql type string is char(6);
......@@ -30,21 +30,31 @@ exec sql end declare section;
ECPGdebug(1, dbgs);
strcpy(msg, "connect");
exec sql connect to mm;
exec sql connect to mm as main;
strcpy(msg, "connect");
exec sql connect to pm;
strcpy(msg, "create");
exec sql at main create table test(name char(6), amount int, letter char(1));
exec sql create table test(name char(6), amount int, letter char(1));
strcpy(msg, "commit");
exec sql at main commit;
exec sql commit;
strcpy(msg, "set connection");
exec sql set connection main;
strcpy(msg, "execute insert 1");
sprintf(command, "insert into test(name, amount, letter) values ('foobar', 1, 'f')");
sprintf(command, "insert into test(name, amount, letter) values ('db: mm', 1, 'f')");
exec sql execute immediate :command;
sprintf(command, "insert into test(name, amount, letter) values ('db: mm', 2, 't')");
exec sql execute immediate :command;
strcpy(msg, "execute insert 2");
sprintf(command, "insert into test(name, amount, letter) select name, amount+1, letter from test");
exec sql execute immediate :command;
sprintf(command, "insert into test(name, amount, letter) values ('db: pm', 1, 'f')");
exec sql at pm execute immediate :command;
strcpy(msg, "execute insert 3");
sprintf(command, "insert into test(name, amount, letter) select name, amount+10, letter from test");
......@@ -55,27 +65,35 @@ exec sql end declare section;
strcpy(msg, "execute insert 4");
sprintf(command, "insert into test(name, amount, letter) select name, amount+;;, letter from test");
exec sql prepare I from :command;
exec sql execute I using :increment;
exec sql at pm execute I using :increment;
printf("Inserted %d tuples via prepared execute\n", sqlca.sqlerrd[2]);
strcpy(msg, "commit");
exec sql commit;
exec sql at pm commit;
strcpy(msg, "select");
exec sql select name, amount, letter into :name, :amount, :letter from test;
for (i=0, j=sqlca.sqlerrd[2]; i<j; i++)
printf("name[%d]=%6.6s\tamount[%d]=%d\tletter[%d]=%c\n", i, name[i], i, amount[i],i, letter[i][0]);
exec sql at pm select name, amount, letter into :name, :amount, :letter from test;
for (i=0, j=sqlca.sqlerrd[2]; i<j; i++)
printf("name[%d]=%6.6s\tamount[%d]=%d\tletter[%d]=%c\n", i, name[i], i, amount[i],i, letter[i][0]);
strcpy(msg, "drop");
exec sql drop table test;
exec sql at pm drop table test;
strcpy(msg, "commit");
exec sql commit;
exec sql at pm commit;
strcpy(msg, "disconnect");
exec sql disconnect;
exec sql disconnect all;
if (dbgs != NULL)
fclose(dbgs);
......
......@@ -5,6 +5,9 @@ exec sql include header_test;
exec sql type c is char reference;
typedef char* c;
exec sql type ind is union { int integer; short smallinteger; };
typedef union { int integer; short smallinteger; } ind;
int
main ()
{
......@@ -18,15 +21,17 @@ exec sql begin declare section;
birthinfo ind_birth;
} ind_personal;
int ind_married;
ind children;
ind ind_children;
char married[9];
c testname="Petra";
char *query="select name, born, age, married 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 var ind_married is long;
exec sql declare cur cursor for
select name, born, age, married from meskes;
select name, born, age, married, children from meskes;
char msg[128], command[128];
FILE *dbgs;
......@@ -38,11 +43,11 @@ exec sql end declare section;
exec sql connect to unix:postgresql://localhost:5432/mm;
strcpy(msg, "create");
exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
exec sql create table meskes(name char(8), born integer, age smallint, married char(8), children integer);
strcpy(msg, "insert");
exec sql insert into meskes(name, married) values ('Petra', '19900404');
exec sql insert into meskes(name, born, age, married) values ('Michael', 19660117, 33, '19900404');
exec sql insert into meskes(name, married, children) values ('Petra', '19900404', 3);
exec sql insert into meskes(name, born, age, married, children) values ('Michael', 19660117, 33, '19900404', 3);
exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 8);
exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 5);
exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 1);
......@@ -57,7 +62,7 @@ exec sql end declare section;
while (1) {
strcpy(msg, "fetch");
exec sql fetch in cur into :personal:ind_personal, :married:ind_married;
exec sql fetch in cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallinteger;
printf("%8.8s", personal.name.arr);
if (!ind_personal.ind_birth.born)
printf(", born %d", personal.birth.born);
......@@ -65,6 +70,8 @@ exec sql end declare section;
printf(", age = %d", personal.birth.age);
if (!ind_married)
printf(", married %s", married);
if (!ind_children.smallinteger)
printf(", children = %d", children.integer);
putchar('\n');
}
......@@ -82,7 +89,7 @@ exec sql end declare section;
while (1) {
strcpy(msg, "fetch");
exec sql fetch in prep into :personal:ind_personal, :married:ind_married;
exec sql fetch in prep into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallinteger;
printf("%8.8s", personal.name.arr);
if (!ind_personal.ind_birth.born)
printf(", born %d", personal.birth.born);
......@@ -90,6 +97,8 @@ exec sql end declare section;
printf(", age = %d", personal.birth.age);
if (!ind_married)
printf(", married %s", married);
if (!ind_children.smallinteger)
printf(", children = %d", children.integer);
putchar('\n');
}
......
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