Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
bf6636ba
Commit
bf6636ba
authored
Feb 20, 1999
by
Marc G. Fournier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
From: Michael Meskes <Michael_Meskes@topmail.de> See Changes file...
parent
3eb22085
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1514 additions
and
457 deletions
+1514
-457
src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/ChangeLog
+57
-0
src/interfaces/ecpg/TODO
src/interfaces/ecpg/TODO
+4
-4
src/interfaces/ecpg/include/ecpgerrno.h
src/interfaces/ecpg/include/ecpgerrno.h
+2
-0
src/interfaces/ecpg/include/ecpglib.h
src/interfaces/ecpg/include/ecpglib.h
+4
-1
src/interfaces/ecpg/include/ecpgtype.h
src/interfaces/ecpg/include/ecpgtype.h
+2
-1
src/interfaces/ecpg/lib/Makefile.in
src/interfaces/ecpg/lib/Makefile.in
+2
-2
src/interfaces/ecpg/lib/ecpglib.c
src/interfaces/ecpg/lib/ecpglib.c
+210
-4
src/interfaces/ecpg/lib/typename.c
src/interfaces/ecpg/lib/typename.c
+3
-1
src/interfaces/ecpg/preproc/Makefile
src/interfaces/ecpg/preproc/Makefile
+15
-13
src/interfaces/ecpg/preproc/c_keywords.c
src/interfaces/ecpg/preproc/c_keywords.c
+1
-2
src/interfaces/ecpg/preproc/ecpg.c
src/interfaces/ecpg/preproc/ecpg.c
+18
-5
src/interfaces/ecpg/preproc/ecpg_keywords.c
src/interfaces/ecpg/preproc/ecpg_keywords.c
+14
-2
src/interfaces/ecpg/preproc/extern.h
src/interfaces/ecpg/preproc/extern.h
+7
-46
src/interfaces/ecpg/preproc/keywords.c
src/interfaces/ecpg/preproc/keywords.c
+6
-5
src/interfaces/ecpg/preproc/pgc.l
src/interfaces/ecpg/preproc/pgc.l
+27
-23
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/preproc/preproc.y
+988
-310
src/interfaces/ecpg/preproc/type.c
src/interfaces/ecpg/preproc/type.c
+20
-9
src/interfaces/ecpg/preproc/type.h
src/interfaces/ecpg/preproc/type.h
+51
-2
src/interfaces/ecpg/test/test1.pgc
src/interfaces/ecpg/test/test1.pgc
+31
-12
src/interfaces/ecpg/test/test2.pgc
src/interfaces/ecpg/test/test2.pgc
+52
-15
No files found.
src/interfaces/ecpg/ChangeLog
View file @
bf6636ba
...
...
@@ -400,3 +400,60 @@ Tue Feb 2 07:40:52 CET 1999
- Brought preproc.y in sync again with gram.y.
- Set ecpg version to 2.4.9
Wed Feb 3 18:28:46 CET 1999
- Started working on PREPARE statement.
- Fixed typo in preproc that cause CREATE statement to not work
anymore.
Thu Feb 4 19:43:39 CET 1999
- Some parts of the PREPARE statement work now.
- Added EXECUTE command
- Added DEALLOCATE PREPARE command
Fri Feb 5 18:25:07 CET 1999
- PREPARE seems to be working okay now.
- Fixed some minor bugs.
- Renamed y.tab.* to preproc.*
Mon Feb 8 07:57:29 CET 1999
- Synced preproc.y with gram.y again.
- Allow ':<name>' as positional variable in prepare statement also.
You can still specify ';;' instead of course.
- Added TYPE statement.
- Set library version to 2.7.0
Tue Feb 9 07:07:11 CET 1999
- Synced preproc.y with gram.y.
Tue Feb 9 20:21:44 CET 1999
- Added FREE statement.
Wed Feb 10 07:51:09 CET 1999
- Synced keyword.c.
Sat Feb 13 10:44:43 CET 1999
- Added DECLARE STATEMENT for compatibility with Oracle. De facto
this statement does nothing.
- Added VAR statement.
Son Feb 14 11:36:04 CET 1999
- Added type 'enum' to TYPE and VAR statement.
- Allow ecpg keywords as datatypes.
Thu Feb 18 08:35:35 CET 1999
- Make sure indicator for array is array too.
Fri Feb 19 18:38:45 CET 1999
- Finished type aliasing for structures.
- Set ecpg version to 2.5.0
src/interfaces/ecpg/TODO
View file @
bf6636ba
...
...
@@ -11,10 +11,10 @@ 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 unions
Missing statements:
- exec sql type
- exec sql prepare
- exec sql allocate
- exqc sql free
- SQLSTATE
- exec sql whenever sqlwarning
src/interfaces/ecpg/include/ecpgerrno.h
View file @
bf6636ba
...
...
@@ -28,6 +28,8 @@
#define ECPG_NO_CONN -220
#define ECPG_NOT_CONN -221
#define ECPG_INVALID_STMT -230
/* finally the backend error messages, they start at 400 */
#define ECPG_PGSQL -400
#define ECPG_TRANS -401
...
...
src/interfaces/ecpg/include/ecpglib.h
View file @
bf6636ba
...
...
@@ -11,7 +11,10 @@ extern "C"
bool
ECPGdo
(
int
,
char
*
,...);
bool
ECPGtrans
(
int
,
const
char
*
);
bool
ECPGdisconnect
(
int
,
const
char
*
);
bool
ECPGprepare
(
int
,
char
*
,
char
*
);
bool
ECPGdeallocate
(
int
,
char
*
);
char
*
ECPGprepared_statement
(
char
*
);
void
ECPGlog
(
const
char
*
format
,...);
#ifdef LIBPQ_FE_H
...
...
src/interfaces/ecpg/include/ecpgtype.h
View file @
bf6636ba
...
...
@@ -45,7 +45,8 @@ extern "C"
ECPGt_struct
,
ECPGt_EOIT
,
/* End of insert types. */
ECPGt_EORT
,
/* End of result types. */
ECPGt_NO_INDICATOR
/* no indicator */
ECPGt_NO_INDICATOR
,
/* no indicator */
ECPGt_char_variable
};
#define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_varchar2)
...
...
src/interfaces/ecpg/lib/Makefile.in
View file @
bf6636ba
...
...
@@ -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.4
0 1999/01/21 20:01:32
scrappy Exp $
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.4
1 1999/02/20 07:00:53
scrappy Exp $
#
#-------------------------------------------------------------------------
NAME
=
ecpg
SO_MAJOR_VERSION
=
2
SO_MINOR_VERSION
=
6.3
SO_MINOR_VERSION
=
7.0
SRCDIR
=
@top_srcdir@
include
$(SRCDIR)/Makefile.global
...
...
src/interfaces/ecpg/lib/ecpglib.c
View file @
bf6636ba
...
...
@@ -75,12 +75,19 @@ struct variable
struct
statement
{
int
lineno
;
int
lineno
;
char
*
command
;
struct
variable
*
inlist
;
struct
variable
*
outlist
;
};
struct
prepared_statement
{
char
*
name
;
struct
statement
*
stmt
;
struct
prepared_statement
*
next
;
}
*
prep_stmts
=
NULL
;
static
int
simple_debug
=
0
;
static
FILE
*
debugstream
=
NULL
;
static
int
committed
=
true
;
...
...
@@ -196,6 +203,41 @@ quote_postgres(char *arg, int lineno)
return
res
;
}
/* This function returns a newly malloced string that has the \
in the strings inside the argument quoted with another \.
*/
static
char
*
quote_strings
(
char
*
arg
,
int
lineno
)
{
char
*
res
=
(
char
*
)
ecpg_alloc
(
2
*
strlen
(
arg
)
+
1
,
lineno
);
int
i
,
ri
;
bool
string
=
false
;
if
(
!
res
)
return
(
res
);
for
(
i
=
0
,
ri
=
0
;
arg
[
i
];
i
++
,
ri
++
)
{
switch
(
arg
[
i
])
{
case
'\''
:
string
=
string
?
false
:
true
;
break
;
case
'\\'
:
res
[
ri
++
]
=
'\\'
;
default:
;
}
res
[
ri
]
=
arg
[
i
];
}
res
[
ri
]
=
'\0'
;
return
res
;
}
/* create a list of variables */
static
bool
create_statement
(
int
lineno
,
struct
statement
**
stmt
,
char
*
query
,
va_list
ap
)
...
...
@@ -236,6 +278,14 @@ create_statement(int lineno, struct statement ** stmt, char *query, va_list ap)
var
->
ind_arrsize
=
va_arg
(
ap
,
long
);
var
->
ind_offset
=
va_arg
(
ap
,
long
);
var
->
next
=
NULL
;
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
);
...
...
@@ -251,6 +301,19 @@ create_statement(int lineno, struct statement ** stmt, char *query, va_list ap)
return
(
true
);
}
static
char
*
next_insert
(
char
*
text
)
{
char
*
ptr
=
text
;
bool
string
=
false
;
for
(;
ptr
[
1
]
!=
'\0'
&&
(
ptr
[
0
]
!=
';'
||
ptr
[
1
]
!=
';'
||
string
);
ptr
++
)
if
(
ptr
[
0
]
==
'\''
)
string
=
string
?
false
:
true
;
return
(
ptr
[
1
]
==
'\0'
)
?
NULL
:
ptr
;
}
static
bool
ECPGexecute
(
struct
statement
*
stmt
)
{
...
...
@@ -379,7 +442,30 @@ ECPGexecute(struct statement * stmt)
tobeinserted
=
mallocedval
;
}
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
;
char
*
tmp
;
if
(
!
(
newcopy
=
ecpg_alloc
(
slen
+
1
,
stmt
->
lineno
)))
return
false
;
strncpy
(
newcopy
,
(
char
*
)
var
->
value
,
slen
);
newcopy
[
slen
]
=
'\0'
;
if
(
!
(
mallocedval
=
(
char
*
)
ecpg_alloc
(
2
*
strlen
(
newcopy
)
+
1
,
stmt
->
lineno
)))
return
false
;
tmp
=
quote_strings
(
newcopy
,
stmt
->
lineno
);
if
(
!
tmp
)
return
false
;
strcat
(
mallocedval
,
tmp
);
free
(
newcopy
);
tobeinserted
=
mallocedval
;
}
break
;
case
ECPGt_varchar
:
{
struct
ECPGgeneric_varchar
*
variable
=
...
...
@@ -428,7 +514,7 @@ ECPGexecute(struct statement * stmt)
return
false
;
strcpy
(
newcopy
,
copiedquery
);
if
((
p
=
strstr
(
newcopy
,
";;"
))
==
NULL
)
if
((
p
=
next_insert
(
newcopy
))
==
NULL
)
{
/*
...
...
@@ -449,7 +535,7 @@ ECPGexecute(struct statement * stmt)
strcat
(
newcopy
,
copiedquery
+
(
p
-
newcopy
)
+
2
/* Length of ;; */
);
+
sizeof
(
";;"
)
-
1
/* don't count the '\0' */
);
}
/*
...
...
@@ -470,7 +556,7 @@ ECPGexecute(struct statement * stmt)
}
/* Check if there are unmatched things left. */
if
(
strstr
(
copiedquery
,
";;"
)
!=
NULL
)
if
(
next_insert
(
copiedquery
)
!=
NULL
)
{
register_error
(
ECPG_TOO_FEW_ARGUMENTS
,
"Too few arguments line %d."
,
stmt
->
lineno
);
return
false
;
...
...
@@ -898,7 +984,21 @@ ECPGtrans(int lineno, const char *transaction)
PQclear
(
res
);
}
if
(
strcmp
(
transaction
,
"commit"
)
==
0
||
strcmp
(
transaction
,
"rollback"
)
==
0
)
{
struct
prepared_statement
*
this
;
committed
=
1
;
/* deallocate all prepared statements */
for
(
this
=
prep_stmts
;
this
!=
NULL
;
this
=
this
->
next
)
{
bool
b
=
ECPGdeallocate
(
lineno
,
this
->
name
);
if
(
!
b
)
return
false
;
}
}
return
TRUE
;
}
...
...
@@ -1033,3 +1133,109 @@ sqlprint(void)
sqlca
.
sqlerrm
.
sqlerrmc
[
sqlca
.
sqlerrm
.
sqlerrml
]
=
'\0'
;
printf
(
"sql error %s
\n
"
,
sqlca
.
sqlerrm
.
sqlerrmc
);
}
static
void
replace_variables
(
char
*
text
)
{
char
*
ptr
=
text
;
bool
string
=
false
;
for
(;
*
ptr
!=
'\0'
;
ptr
++
)
{
if
(
*
ptr
==
'\''
)
string
=
string
?
false
:
true
;
if
(
!
string
&&
*
ptr
==
':'
)
{
ptr
[
0
]
=
ptr
[
1
]
=
';'
;
for
(
ptr
+=
2
;
*
ptr
&&
*
ptr
!=
' '
;
ptr
++
)
*
ptr
=
' '
;
}
}
}
/* handle the EXEC SQL PREPARE statement */
bool
ECPGprepare
(
int
lineno
,
char
*
name
,
char
*
variable
)
{
struct
statement
*
stmt
;
struct
prepared_statement
*
this
;
/* check if we already have prepared this statement */
for
(
this
=
prep_stmts
;
this
!=
NULL
&&
strcmp
(
this
->
name
,
name
)
!=
0
;
this
=
this
->
next
);
if
(
this
)
{
bool
b
=
ECPGdeallocate
(
lineno
,
name
);
if
(
!
b
)
return
false
;
}
this
=
(
struct
prepared_statement
*
)
ecpg_alloc
(
sizeof
(
struct
prepared_statement
),
lineno
);
if
(
!
this
)
return
false
;
stmt
=
(
struct
statement
*
)
ecpg_alloc
(
sizeof
(
struct
statement
),
lineno
);
if
(
!
stmt
)
{
free
(
this
);
return
false
;
}
/* create statement */
stmt
->
lineno
=
lineno
;
stmt
->
command
=
ecpg_strdup
(
variable
,
lineno
);
stmt
->
inlist
=
stmt
->
outlist
=
NULL
;
/* if we have C variables in our statment replace them with ';;' */
replace_variables
(
stmt
->
command
);
/* add prepared statement to our list */
this
->
name
=
ecpg_strdup
(
name
,
lineno
);
this
->
stmt
=
stmt
;
if
(
prep_stmts
==
NULL
)
this
->
next
=
NULL
;
else
this
->
next
=
prep_stmts
;
prep_stmts
=
this
;
return
true
;
}
/* handle the EXEC SQL DEALLOCATE PREPARE statement */
bool
ECPGdeallocate
(
int
lineno
,
char
*
name
)
{
struct
prepared_statement
*
this
,
*
prev
;
/* check if we really have prepared this statement */
for
(
this
=
prep_stmts
,
prev
=
NULL
;
this
!=
NULL
&&
strcmp
(
this
->
name
,
name
)
!=
0
;
prev
=
this
,
this
=
this
->
next
);
if
(
this
)
{
/* okay, free all the resources */
free
(
this
->
name
);
free
(
this
->
stmt
->
command
);
free
(
this
->
stmt
);
if
(
prev
!=
NULL
)
prev
->
next
=
this
->
next
;
else
prep_stmts
=
this
->
next
;
return
true
;
}
ECPGlog
(
"deallocate_prepare: invalid statement name %s
\n
"
,
name
);
register_error
(
ECPG_INVALID_STMT
,
"Invalid statement name %s in line %d"
,
name
,
lineno
);
return
false
;
}
/* return the prepared statement */
char
*
ECPGprepared_statement
(
char
*
name
)
{
struct
prepared_statement
*
this
;
for
(
this
=
prep_stmts
;
this
!=
NULL
&&
strcmp
(
this
->
name
,
name
)
!=
0
;
this
=
this
->
next
);
return
(
this
)
?
this
->
stmt
->
command
:
NULL
;
}
src/interfaces/ecpg/lib/typename.c
View file @
bf6636ba
...
...
@@ -8,7 +8,7 @@ ECPGtype_name(enum ECPGttype typ)
{
switch
(
typ
)
{
case
ECPGt_char
:
case
ECPGt_char
:
return
"char"
;
case
ECPGt_unsigned_char
:
return
"unsigned char"
;
...
...
@@ -32,6 +32,8 @@ ECPGtype_name(enum ECPGttype typ)
return
"bool"
;
case
ECPGt_varchar
:
return
"varchar"
;
case
ECPGt_char_variable
:
return
"char"
;
default:
abort
();
}
...
...
src/interfaces/ecpg/preproc/Makefile
View file @
bf6636ba
...
...
@@ -2,20 +2,25 @@ SRCDIR= ../../..
include
$(SRCDIR)/Makefile.global
MAJOR_VERSION
=
2
MINOR_VERSION
=
4
PATCHLEVEL
=
9
MINOR_VERSION
=
5
PATCHLEVEL
=
0
CFLAGS
+=
-I
../include
-DMAJOR_VERSION
=
$(MAJOR_VERSION)
\
-DMINOR_VERSION
=
$(MINOR_VERSION)
-DPATCHLEVEL
=
$(PATCHLEVEL)
\
-DINCLUDE_PATH
=
\"
$(DESTDIR)$(HEADERDIR)
\"
-DINCLUDE_PATH
=
\"
$(DESTDIR)$(HEADERDIR)
\"
OBJ
=
y.tab
.o pgc.o type.o ecpg.o ecpg_keywords.o ../../../backend/parser/scansup.o
\
OBJ
=
preproc
.o pgc.o type.o ecpg.o ecpg_keywords.o ../../../backend/parser/scansup.o
\
keywords.o c_keywords.o ../lib/typename.o
all
::
ecpg
preproc.c preproc.h
:
preproc.y
$(YACC)
$(YFLAGS)
$<
mv
y.tab.c preproc.c
mv
y.tab.h preproc.h
clean
:
rm
-f
*
.o core a.out ecpg
$(X)
y.tab.h y.tab.c pgc.c
*
~
rm
-f
*
.o core a.out ecpg
$(X)
*
~
install
:
all
$(INSTALL)
$(INSTL_EXE_OPTS)
ecpg
$(X)
$(DESTDIR)$(BINDIR)
...
...
@@ -31,13 +36,10 @@ pgc.c: pgc.l
$(LEX)
$<
mv
lex.yy.c pgc.c
y.tab.h y.tab.c
:
preproc.y
$(YACC)
$(YFLAGS)
$<
y.tab.o
:
y.tab.h ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c
preproc.o
:
preproc.h ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c
type.o
:
../include/ecpgtype.h
pgc.o
:
../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c
y.tab
.h
keywords.o
:
../include/ecpgtype.h
y.tab
.h
c_keywords.o
:
../include/ecpgtype.h
y.tab.h
ecpg_keywords.o
:
../include/ecpgtype.h
y.tab.h
pgc.o
:
../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c
preproc
.h
keywords.o
:
../include/ecpgtype.h
preproc
.h
c_keywords.o
:
../include/ecpgtype.h
preproc.h
ecpg_keywords.o
:
../include/ecpgtype.h
preproc.h
src/interfaces/ecpg/preproc/c_keywords.c
View file @
bf6636ba
...
...
@@ -9,9 +9,8 @@
#include <string.h>
#include "postgres.h"
#include "type.h"
#include "y.tab.h"
#include "extern.h"
#include "preproc.h"
/*
* List of (keyword-name, keyword-token-value) pairs.
...
...
src/interfaces/ecpg/preproc/ecpg.c
View file @
bf6636ba
...
...
@@ -25,6 +25,7 @@ extern char *optarg;
struct
_include_path
*
include_paths
;
int
no_auto_trans
=
0
;
struct
cursor
*
cur
=
NULL
;
struct
typedefs
*
types
=
NULL
;
static
void
usage
(
char
*
progname
)
...
...
@@ -155,22 +156,22 @@ main(int argc, char *const argv[])
{
struct
cursor
*
ptr
;
struct
_defines
*
defptr
;
struct
typedefs
*
typeptr
;
/* remove old cursor definitions if any are still there */
for
(
ptr
=
cur
;
ptr
!=
NULL
;)
{
struct
cursor
*
this
=
ptr
;
struct
arguments
*
l1
,
*
l2
;
struct
arguments
*
l1
,
*
l2
;
free
(
ptr
->
command
);
free
(
ptr
->
name
);
for
(
l1
=
argsinsert
;
l1
;
l1
=
l2
)
for
(
l1
=
ptr
->
argsinsert
;
l1
;
l1
=
l2
)
{
l2
=
l1
->
next
;
free
(
l1
);
}
for
(
l1
=
argsresult
;
l1
;
l1
=
l2
)
for
(
l1
=
ptr
->
argsresult
;
l1
;
l1
=
l2
)
{
l2
=
l1
->
next
;
free
(
l1
);
...
...
@@ -189,7 +190,19 @@ main(int argc, char *const argv[])
defptr
=
defptr
->
next
;
free
(
this
);
}
/* and old typedefs */
for
(
typeptr
=
types
;
typeptr
!=
NULL
;)
{
struct
typedefs
*
this
=
typeptr
;
free
(
typeptr
->
name
);
free
(
typeptr
->
type
);
ECPGfree_struct_member
(
typeptr
->
struct_member_list
);
typeptr
=
typeptr
->
next
;
free
(
this
);
}
/* initialize lex */
lex_init
();
...
...
src/interfaces/ecpg/preproc/ecpg_keywords.c
View file @
bf6636ba
...
...
@@ -9,9 +9,8 @@
#include <string.h>
#include "postgres.h"
#include "type.h"
#include "extern.h"
#include "
y.tab
.h"
#include "
preproc
.h"
/*
* List of (keyword-name, keyword-token-value) pairs.
...
...
@@ -21,25 +20,38 @@
*/
static
ScanKeyword
ScanKeywords
[]
=
{
/* name value */
{
"bool"
,
SQL_BOOL
},
{
"break"
,
SQL_BREAK
},
{
"call"
,
SQL_CALL
},
{
"connect"
,
SQL_CONNECT
},
{
"connection"
,
SQL_CONNECTION
},
{
"continue"
,
SQL_CONTINUE
},
{
"deallocate"
,
SQL_DEALLOCATE
},
{
"disconnect"
,
SQL_DISCONNECT
},
{
"enum"
,
SQL_ENUM
},
{
"found"
,
SQL_FOUND
},
{
"free"
,
SQL_FREE
},
{
"go"
,
SQL_GO
},
{
"goto"
,
SQL_GOTO
},
{
"identified"
,
SQL_IDENTIFIED
},
{
"immediate"
,
SQL_IMMEDIATE
},
{
"indicator"
,
SQL_INDICATOR
},
{
"int"
,
SQL_INT
},
{
"long"
,
SQL_LONG
},
{
"open"
,
SQL_OPEN
},
{
"prepare"
,
SQL_PREPARE
},
{
"reference"
,
SQL_REFERENCE
},
{
"release"
,
SQL_RELEASE
},
{
"section"
,
SQL_SECTION
},
{
"short"
,
SQL_SHORT
},
{
"signed"
,
SQL_SIGNED
},
{
"sqlerror"
,
SQL_SQLERROR
},
{
"sqlprint"
,
SQL_SQLPRINT
},
{
"sqlwarning"
,
SQL_SQLWARNING
},
{
"stop"
,
SQL_STOP
},
{
"struct"
,
SQL_STRUCT
},
{
"unsigned"
,
SQL_UNSIGNED
},
{
"var"
,
SQL_VAR
},
{
"whenever"
,
SQL_WHENEVER
},
};
...
...
src/interfaces/ecpg/preproc/extern.h
View file @
bf6636ba
#include "parser/keywords.h"
#include "type.h"
#include <errno.h>
/* variables */
extern
int
braces_open
,
no_auto_trans
;
no_auto_trans
,
struct_level
;
extern
char
*
yytext
;
extern
int
yylineno
,
yyleng
;
extern
FILE
*
yyin
,
*
yyout
;
struct
_include_path
{
char
*
path
;
struct
_include_path
*
next
;
};
extern
struct
_include_path
*
include_paths
;
struct
cursor
{
char
*
name
;
char
*
command
;
struct
arguments
*
argsinsert
;
struct
arguments
*
argsresult
;
struct
cursor
*
next
;
};
extern
struct
cursor
*
cur
;
struct
_defines
{
char
*
old
;
char
*
new
;
struct
_defines
*
next
;
};
extern
struct
typedefs
*
types
;
extern
struct
_defines
*
defines
;
/* This is a linked list of the variable names and types. */
struct
variable
{
char
*
name
;
struct
ECPGtype
*
type
;
int
brace_level
;
struct
variable
*
next
;
};
extern
struct
ECPGtype
ecpg_no_indicator
;
extern
struct
variable
no_indicator
;
struct
arguments
{
struct
variable
*
variable
;
struct
variable
*
indicator
;
struct
arguments
*
next
;
};
extern
struct
arguments
*
argsinsert
;
extern
struct
arguments
*
argsresult
;
...
...
@@ -74,9 +34,10 @@ extern void yyerror(char *);
/* return codes */
#define OK 0
#define PARSE_ERROR -1
#define ILLEGAL_OPTION -2
#define OK 0
#define PARSE_ERROR -1
#define ILLEGAL_OPTION -2
#define INDICATOR_NOT_ARRAY -3
#define NO_INCLUDE_FILE ENOENT
#define OUT_OF_MEMORY ENOMEM
src/interfaces/ecpg/preproc/keywords.c
View file @
bf6636ba
...
...
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.1
0 1999/02/13 23:22:35 momjian
Exp $
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.1
1 1999/02/20 07:01:00 scrappy
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -18,7 +18,7 @@
#include "nodes/parsenodes.h"
#include "nodes/pg_list.h"
#include "type.h"
#include "
y.tab
.h"
#include "
preproc
.h"
#include "parser/keywords.h"
#include "utils/elog.h"
...
...
@@ -69,9 +69,6 @@ static ScanKeyword ScanKeywords[] = {
{
"createdb"
,
CREATEDB
},
{
"createuser"
,
CREATEUSER
},
{
"cross"
,
CROSS
},
{
"current"
,
CURRENT
},
/* 6.4 to 6.5 is migration time! CURRENT
* will be removed in 6.5! Use OLD keyword
* in rules. Jan */
{
"current_date"
,
CURRENT_DATE
},
{
"current_time"
,
CURRENT_TIME
},
{
"current_timestamp"
,
CURRENT_TIMESTAMP
},
...
...
@@ -96,6 +93,7 @@ static ScanKeyword ScanKeywords[] = {
{
"end"
,
END_TRANS
},
/***S*I***/
{
"except"
,
EXCEPT
},
{
"execute"
,
EXECUTE
},
{
"exists"
,
EXISTS
},
{
"explain"
,
EXPLAIN
},
...
...
@@ -125,6 +123,7 @@ static ScanKeyword ScanKeywords[] = {
{
"instead"
,
INSTEAD
},
/***S*I***/
{
"intersect"
,
INTERSECT
},
{
"interval"
,
INTERVAL
},
{
"into"
,
INTO
},
{
"is"
,
IS
},
...
...
@@ -138,6 +137,7 @@ static ScanKeyword ScanKeywords[] = {
{
"left"
,
LEFT
},
{
"level"
,
LEVEL
},
{
"like"
,
LIKE
},
{
"limit"
,
LIMIT
},
{
"listen"
,
LISTEN
},
{
"load"
,
LOAD
},
{
"local"
,
LOCAL
},
...
...
@@ -167,6 +167,7 @@ static ScanKeyword ScanKeywords[] = {
{
"nullif"
,
NULLIF
},
{
"numeric"
,
NUMERIC
},
{
"of"
,
OF
},
{
"offset"
,
OFFSET
},
{
"oids"
,
OIDS
},
{
"old"
,
CURRENT
},
{
"on"
,
ON
},
...
...
src/interfaces/ecpg/preproc/pgc.l
View file @
bf6636ba
...
...
@@ -24,9 +24,8 @@
#include "nodes/parsenodes.h"
#include "parser/gramparse.h"
#include "parser/scansup.h"
#include "type.h"
#include "extern.h"
#include "
y.tab
.h"
#include "
preproc
.h"
#include "utils/builtins.h"
/* some versions of lex define this as a macro */
...
...
@@ -241,7 +240,7 @@ cppline {space}*#.*(\\{space}*\n)*\n*
}
<xq>{xqstop} {
BEGIN(SQL);
yylval.str = strdup(scanstr(literal));
yylval.str =
mm_
strdup(scanstr(literal));
return SCONST;
}
<xq>{xqdouble} |
...
...
@@ -276,7 +275,7 @@ cppline {space}*#.*(\\{space}*\n)*\n*
}
<xd>{xdstop} {
BEGIN(SQL);
yylval.str = strdup(literal);
yylval.str =
mm_
strdup(literal);
return CSTRING;
}
<xd>{xdinside} {
...
...
@@ -292,7 +291,7 @@ cppline {space}*#.*(\\{space}*\n)*\n*
}
<xdc>{xdstop} {
BEGIN(C);
yylval.str = strdup(literal);
yylval.str =
mm_
strdup(literal);
return CSTRING;
}
<xdc>{xdinside} {
...
...
@@ -316,14 +315,14 @@ cppline {space}*#.*(\\{space}*\n)*\n*
}
<SQL>{self} { return yytext[0]; }
<SQL>{operator}/-[\.0-9] {
yylval.str = strdup((char*)yytext);
yylval.str =
mm_
strdup((char*)yytext);
return Op;
}
<SQL>{operator} {
if (strcmp((char*)yytext,"!=") == 0)
yylval.str = strdup("<>"); /* compatability */
yylval.str =
mm_
strdup("<>"); /* compatability */
else
yylval.str = strdup((char*)yytext);
yylval.str =
mm_
strdup((char*)yytext);
return Op;
}
<SQL>{param} {
...
...
@@ -342,7 +341,6 @@ cppline {space}*#.*(\\{space}*\n)*\n*
if (isascii((unsigned char)lower_text[i]) && isupper(lower_text[i]))
lower_text[i] = tolower(lower_text[i]);
printf("yyt= %s, lt = %s\n", yytext, lower_text);
keyword = ScanKeywordLookup((char*)lower_text);
if (keyword != NULL) {
return keyword->value;
...
...
@@ -367,7 +365,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
yb->buffer = YY_CURRENT_BUFFER;
yb->lineno = yylineno;
yb->filename = strdup(input_filename);
yb->filename =
mm_
strdup(input_filename);
yb->next = yy_buffer;
yy_buffer = yb;
...
...
@@ -378,7 +376,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
}
if (ptr == NULL)
{
yylval.str = strdup((char*)yytext);
yylval.str =
mm_
strdup((char*)yytext);
return IDENT;
}
}
...
...
@@ -470,7 +468,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
return ICONST;
}
<SQL>:{identifier}(("->"|\.){identifier})* {
yylval.str = strdup((char*)yytext+1);
yylval.str =
mm_
strdup((char*)yytext+1);
return(CVARIABLE);
}
<SQL>{identifier} {
...
...
@@ -484,7 +482,6 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
if (isascii((unsigned char)lower_text[i]) && isupper(lower_text[i]))
lower_text[i] = tolower(lower_text[i]);
printf("yyt= %s, lt = %s\n", yytext, lower_text);
keyword = ScanKeywordLookup((char*)lower_text);
if (keyword != NULL) {
return keyword->value;
...
...
@@ -509,7 +506,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
yb->buffer = YY_CURRENT_BUFFER;
yb->lineno = yylineno;
yb->filename = strdup(input_filename);
yb->filename =
mm_
strdup(input_filename);
yb->next = yy_buffer;
yy_buffer = yb;
...
...
@@ -520,19 +517,26 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
}
if (ptr == NULL)
{
yylval.str = strdup((char*)yytext);
yylval.str =
mm_
strdup((char*)yytext);
return IDENT;
}
}
}
}
<SQL>{space} { /* ignore */ }
<SQL>";" { BEGIN C; return SQL_SEMI; }
<SQL>";" { /*
* We may find a ';' inside a structure
* definition in a TYPE or VAR statement.
* This is not a EOL marker.
*/
if (struct_level == 0)
BEGIN C;
return SQL_SEMI; }
<SQL>{other} { return yytext[0]; }
<C>{exec}{space}{sql} { BEGIN SQL; return SQL_START; }
<C>{ccomment} { /* ignore */ }
<C>{cppline} {
yylval.str = strdup((char*)yytext);
yylval.str =
mm_
strdup((char*)yytext);
return(CPP_LINE);
}
<C>{identifier} {
...
...
@@ -556,7 +560,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
yb->buffer = YY_CURRENT_BUFFER;
yb->lineno = yylineno;
yb->filename = strdup(input_filename);
yb->filename =
mm_
strdup(input_filename);
yb->next = yy_buffer;
yy_buffer = yb;
...
...
@@ -567,7 +571,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
}
if (ptr == NULL)
{
yylval.str = strdup((char*)yytext);
yylval.str =
mm_
strdup((char*)yytext);
return IDENT;
}
}
...
...
@@ -585,7 +589,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
<C>{exec}{space}{sql}{space}{define} {BEGIN(def_ident);}
<def_ident>{space} {}
<def_ident>{identifier} {
old = strdup(yytext);
old =
mm_
strdup(yytext);
BEGIN(def);
llen = 0;
*literal = '\0';
...
...
@@ -599,7 +603,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
if (strcmp(old, ptr->old) == 0)
{
free(ptr->new);
ptr->new = strdup(scanstr(literal));
ptr->new =
mm_
strdup(scanstr(literal));
}
}
if (ptr == NULL)
...
...
@@ -608,7 +612,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
/* initial definition */
this->old = old;
this->new = strdup(scanstr(literal));
this->new =
mm_
strdup(scanstr(literal));
this->next = defines;
defines = this;
}
...
...
@@ -666,7 +670,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
exit(NO_INCLUDE_FILE);
}
input_filename = strdup(inc_file);
input_filename =
mm_
strdup(inc_file);
yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE ));
yylineno = 0;
...
...
src/interfaces/ecpg/preproc/preproc.y
View file @
bf6636ba
This diff is collapsed.
Click to expand it.
src/interfaces/ecpg/preproc/type.c
View file @
bf6636ba
...
...
@@ -2,7 +2,6 @@
#include <string.h>
#include <stdlib.h>
#include "type.h"
#include "extern.h"
/* malloc + error check */
...
...
@@ -36,8 +35,8 @@ mm_strdup(const char *string)
}
/* duplicate memberlist */
st
atic
st
ruct
ECPGstruct_member
*
struct_member_dup
(
struct
ECPGstruct_member
*
rm
)
struct
ECPGstruct_member
*
ECPG
struct_member_dup
(
struct
ECPGstruct_member
*
rm
)
{
struct
ECPGstruct_member
*
new
=
NULL
;
...
...
@@ -71,7 +70,8 @@ void
ECPGmake_struct_member
(
char
*
name
,
struct
ECPGtype
*
type
,
struct
ECPGstruct_member
**
start
)
{
struct
ECPGstruct_member
*
ptr
,
*
ne
=
(
struct
ECPGstruct_member
*
)
mm_alloc
(
sizeof
(
struct
ECPGstruct_member
));
*
ne
=
(
struct
ECPGstruct_member
*
)
mm_alloc
(
sizeof
(
struct
ECPGstruct_member
));
ne
->
name
=
strdup
(
name
);
ne
->
typ
=
type
;
...
...
@@ -112,7 +112,7 @@ ECPGmake_struct_type(struct ECPGstruct_member * rm)
{
struct
ECPGtype
*
ne
=
ECPGmake_simple_type
(
ECPGt_struct
,
1
);
ne
->
u
.
members
=
struct_member_dup
(
rm
);
ne
->
u
.
members
=
ECPG
struct_member_dup
(
rm
);
return
ne
;
}
...
...
@@ -160,6 +160,9 @@ get_type(enum ECPGttype typ)
case
ECPGt_NO_INDICATOR
:
/* no indicator */
return
(
"ECPGt_NO_INDICATOR"
);
break
;
case
ECPGt_char_variable
:
/* string that should not be quoted */
return
(
"ECPGt_char_variable"
);
break
;
default:
abort
();
}
...
...
@@ -202,23 +205,30 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
{
ECPGdump_a_simple
(
o
,
name
,
typ
->
u
.
element
->
typ
,
typ
->
u
.
element
->
size
,
typ
->
size
,
NULL
,
prefix
);
if
(
ind_typ
==
&
ecpg_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
);
else
{
if
(
ind_typ
->
typ
!=
ECPGt_array
)
{
fprintf
(
stderr
,
"Indicator for an array has to be array too.
\n
"
);
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
);
}
}
else
if
(
typ
->
u
.
element
->
typ
==
ECPGt_array
)
{
yyerror
(
"No nested arrays allowed (except strings)"
);
/*
Array of array,
*/
yyerror
(
"No nested arrays allowed (except strings)"
);
/*
array of array
*/
}
else
if
(
typ
->
u
.
element
->
typ
==
ECPGt_struct
)
{
/* Array of structs
.
*/
/* 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, ple
q
ase inform pgsql-bugs@postgresql.org"
);
yyerror
(
"Internal error: unknown datatype, please inform pgsql-bugs@postgresql.org"
);
break
;
case
ECPGt_struct
:
ECPGdump_a_struct
(
o
,
name
,
ind_name
,
1
,
typ
,
ind_typ
,
NULL
,
prefix
,
ind_prefix
);
...
...
@@ -260,6 +270,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
break
;
case
ECPGt_char
:
case
ECPGt_unsigned_char
:
case
ECPGt_char_variable
:
sprintf
(
offset
,
"%ld*sizeof(char)"
,
varcharsize
);
break
;
default:
...
...
src/interfaces/ecpg/preproc/type.h
View file @
bf6636ba
...
...
@@ -30,6 +30,7 @@ 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
*
);
struct
ECPGstruct_member
*
ECPGstruct_member_dup
(
struct
ECPGstruct_member
*
);
/* Frees a type. */
void
ECPGfree_struct_member
(
struct
ECPGstruct_member
*
);
...
...
@@ -84,6 +85,54 @@ struct index
struct
this_type
{
enum
ECPGttype
type_enum
;
char
*
type_str
;
enum
ECPGttype
type_enum
;
char
*
type_str
;
int
type_dimension
;
int
type_index
;
};
struct
_include_path
{
char
*
path
;
struct
_include_path
*
next
;
};
struct
cursor
{
char
*
name
;
char
*
command
;
struct
arguments
*
argsinsert
;
struct
arguments
*
argsresult
;
struct
cursor
*
next
;
};
struct
typedefs
{
char
*
name
;
struct
this_type
*
type
;
struct
ECPGstruct_member
*
struct_member_list
;
struct
typedefs
*
next
;
};
struct
_defines
{
char
*
old
;
char
*
new
;
struct
_defines
*
next
;
};
/* This is a linked list of the variable names and types. */
struct
variable
{
char
*
name
;
struct
ECPGtype
*
type
;
int
brace_level
;
struct
variable
*
next
;
};
struct
arguments
{
struct
variable
*
variable
;
struct
variable
*
indicator
;
struct
arguments
*
next
;
};
src/interfaces/ecpg/test/test1.pgc
View file @
bf6636ba
...
...
@@ -4,16 +4,25 @@ exec sql whenever sqlerror sqlprint;
exec sql include sqlca;
exec sql define AMOUNT 5;
exec sql define AMOUNT 8;
exec sql type intarray is int[AMOUNT];
exec sql type string is char(6);
typedef int intarray[AMOUNT];
int
main ()
{
exec sql begin declare section;
int amount[AMOUNT];
char name[AMOUNT][8];
intarray amount;
int increment=100;
char name[AMOUNT][6];
char letter[AMOUNT][1];
char command[128];
exec sql end declare section;
char msg[128], command[128];
exec sql var name is string(AMOUNT);
char msg[128];
FILE *dbgs;
int i,j;
...
...
@@ -24,30 +33,40 @@ exec sql end declare section;
exec sql connect to mm;
strcpy(msg, "create");
exec sql create table test(name char(8), amount int);
exec sql create table test(name char(6), amount int, letter char(1));
strcpy(msg, "commit");
exec sql commit;
strcpy(msg, "execute insert 1");
sprintf(command, "insert into test(name, amount
) values ('foobar', 1
)");
sprintf(command, "insert into test(name, amount
, letter) values ('foobar', 1, 'f'
)");
exec sql execute immediate :command;
strcpy(msg, "excute insert 2");
sprintf(command, "insert into test(name, amount
) select name, amount+1
from test");
strcpy(msg, "ex
e
cute insert 2");
sprintf(command, "insert into test(name, amount
, letter) select name, amount+1, letter
from test");
exec sql execute immediate :command;
strcpy(msg, "excute insert 3");
sprintf(command, "insert into test(name, amount
) select name, amount+10
from test");
strcpy(msg, "ex
e
cute insert 3");
sprintf(command, "insert into test(name, amount
, letter) select name, amount+10, letter
from test");
exec sql execute immediate :command;
printf("Inserted %d tuples via execute immediate\n", sqlca.sqlerrd[2]);
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;
printf("Inserted %d tuples via prepared execute\n", sqlca.sqlerrd[2]);
strcpy(msg, "commit");
exec sql commit;
strcpy(msg, "select");
exec sql select name, amount
into :name, :amount
from test;
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]=%
8.8s, amount[%d]=%d\n", i, name[i], i, amount[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;
...
...
src/interfaces/ecpg/test/test2.pgc
View file @
bf6636ba
...
...
@@ -2,26 +2,31 @@
exec sql include header_test;
exec sql type c is char reference;
typedef char* c;
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 birth_struct { long born;
short age;
} birth;
birthinfo birth;
} personal;
struct personal_indicator { short ind_name;
struct birth_indicator { short ind_born;
int ind_age;
} ind_birth;
struct personal_indicator { int ind_name;
birthinfo ind_birth;
} ind_personal;
long
ind_married;
int
ind_married;
char married[9];
c testname="Petra";
char *query="select name, born, age, married from meskes where name = :var1";
exec sql end declare section;
exec sql declare cur cursor for
select name, born, age, married from meskes;
exec sql var ind_married is long;
exec sql declare cur cursor for
select name, born, age, married from meskes;
char msg[128], command[128];
FILE *dbgs;
...
...
@@ -36,11 +41,11 @@ exec sql declare cur cursor for
exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
strcpy(msg, "insert");
exec sql insert into meskes(name,
born, age, married) values ('Petra', 19661202, 32
, '19900404');
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, born, age) values ('Carsten', 19910103,
7
);
exec sql insert into meskes(name, born, age) values ('Marc', 19930907,
4
);
exec sql insert into meskes(name, born, age) values ('Chris', 19970923,
0
);
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
);
strcpy(msg, "commit");
exec sql commit;
...
...
@@ -53,12 +58,44 @@ exec sql declare cur cursor for
while (1) {
strcpy(msg, "fetch");
exec sql fetch in cur into :personal:ind_personal, :married:ind_married;
printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married);
printf("%8.8s", personal.name.arr);
if (!ind_personal.ind_birth.born)
printf(", born %d", personal.birth.born);
if (!ind_personal.ind_birth.age)
printf(", age = %d", personal.birth.age);
if (!ind_married)
printf(", married %s", married);
putchar('\n');
}
strcpy(msg, "close");
exec sql close cur;
/* and now the same query with prepare */
exec sql prepare MM from :query;
exec sql declare prep cursor for MM;
strcpy(msg, "open");
exec sql open prep using :testname;
exec sql whenever not found do break;
while (1) {
strcpy(msg, "fetch");
exec sql fetch in prep into :personal:ind_personal, :married:ind_married;
printf("%8.8s", personal.name.arr);
if (!ind_personal.ind_birth.born)
printf(", born %d", personal.birth.born);
if (!ind_personal.ind_birth.age)
printf(", age = %d", personal.birth.age);
if (!ind_married)
printf(", married %s", married);
putchar('\n');
}
strcpy(msg, "close");
exec sql close prep;
strcpy(msg, "drop");
exec sql drop table meskes;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment