mirror of
https://github.com/postgres/postgres.git
synced 2025-05-02 11:44:50 +03:00
From: Michael Meskes <Michael_Meskes@topmail.de>
See Changes file...
This commit is contained in:
parent
3eb22085b5
commit
bf6636baa6
@ -400,3 +400,60 @@ Tue Feb 2 07:40:52 CET 1999
|
|||||||
- Brought preproc.y in sync again with gram.y.
|
- Brought preproc.y in sync again with gram.y.
|
||||||
- Set ecpg version to 2.4.9
|
- 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
|
||||||
|
@ -11,10 +11,10 @@ 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
|
||||||
|
|
||||||
|
'at DB connection' is missing for several commands (is this standard?)
|
||||||
|
|
||||||
|
support for unions
|
||||||
|
|
||||||
Missing statements:
|
Missing statements:
|
||||||
- exec sql type
|
|
||||||
- exec sql prepare
|
|
||||||
- exec sql allocate
|
- exec sql allocate
|
||||||
- exqc sql free
|
|
||||||
- SQLSTATE
|
- SQLSTATE
|
||||||
- exec sql whenever sqlwarning
|
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
#define ECPG_NO_CONN -220
|
#define ECPG_NO_CONN -220
|
||||||
#define ECPG_NOT_CONN -221
|
#define ECPG_NOT_CONN -221
|
||||||
|
|
||||||
|
#define ECPG_INVALID_STMT -230
|
||||||
|
|
||||||
/* finally the backend error messages, they start at 400 */
|
/* finally the backend error messages, they start at 400 */
|
||||||
#define ECPG_PGSQL -400
|
#define ECPG_PGSQL -400
|
||||||
#define ECPG_TRANS -401
|
#define ECPG_TRANS -401
|
||||||
|
@ -11,6 +11,9 @@ extern "C"
|
|||||||
bool ECPGdo(int, char *,...);
|
bool ECPGdo(int, char *,...);
|
||||||
bool ECPGtrans(int, const char *);
|
bool ECPGtrans(int, const char *);
|
||||||
bool ECPGdisconnect(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,...);
|
void ECPGlog(const char *format,...);
|
||||||
|
|
||||||
|
@ -45,7 +45,8 @@ extern "C"
|
|||||||
ECPGt_struct,
|
ECPGt_struct,
|
||||||
ECPGt_EOIT, /* End of insert types. */
|
ECPGt_EOIT, /* End of insert types. */
|
||||||
ECPGt_EORT, /* End of result 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)
|
#define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_varchar2)
|
||||||
|
@ -6,13 +6,13 @@
|
|||||||
# Copyright (c) 1994, Regents of the University of California
|
# Copyright (c) 1994, Regents of the University of California
|
||||||
#
|
#
|
||||||
# IDENTIFICATION
|
# IDENTIFICATION
|
||||||
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.40 1999/01/21 20:01:32 scrappy Exp $
|
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.41 1999/02/20 07:00:53 scrappy Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
NAME= ecpg
|
NAME= ecpg
|
||||||
SO_MAJOR_VERSION= 2
|
SO_MAJOR_VERSION= 2
|
||||||
SO_MINOR_VERSION= 6.3
|
SO_MINOR_VERSION= 7.0
|
||||||
|
|
||||||
SRCDIR= @top_srcdir@
|
SRCDIR= @top_srcdir@
|
||||||
include $(SRCDIR)/Makefile.global
|
include $(SRCDIR)/Makefile.global
|
||||||
|
@ -81,6 +81,13 @@ struct statement
|
|||||||
struct variable *outlist;
|
struct variable *outlist;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct prepared_statement
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
struct statement *stmt;
|
||||||
|
struct prepared_statement *next;
|
||||||
|
} *prep_stmts = NULL;
|
||||||
|
|
||||||
static int simple_debug = 0;
|
static int simple_debug = 0;
|
||||||
static FILE *debugstream = NULL;
|
static FILE *debugstream = NULL;
|
||||||
static int committed = true;
|
static int committed = true;
|
||||||
@ -196,6 +203,41 @@ quote_postgres(char *arg, int lineno)
|
|||||||
return res;
|
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 */
|
/* create a list of variables */
|
||||||
static bool
|
static bool
|
||||||
create_statement(int lineno, struct statement ** stmt, char *query, va_list ap)
|
create_statement(int lineno, struct statement ** stmt, char *query, va_list ap)
|
||||||
@ -237,6 +279,14 @@ create_statement(int lineno, struct statement ** stmt, char *query, va_list ap)
|
|||||||
var->ind_offset = va_arg(ap, long);
|
var->ind_offset = va_arg(ap, long);
|
||||||
var->next = NULL;
|
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);
|
for (ptr = *list; ptr && ptr->next; ptr = ptr->next);
|
||||||
|
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
@ -251,6 +301,19 @@ create_statement(int lineno, struct statement ** stmt, char *query, va_list ap)
|
|||||||
return (true);
|
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
|
static bool
|
||||||
ECPGexecute(struct statement * stmt)
|
ECPGexecute(struct statement * stmt)
|
||||||
{
|
{
|
||||||
@ -379,7 +442,30 @@ ECPGexecute(struct statement * stmt)
|
|||||||
tobeinserted = mallocedval;
|
tobeinserted = mallocedval;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case ECPGt_varchar:
|
||||||
{
|
{
|
||||||
struct ECPGgeneric_varchar *variable =
|
struct ECPGgeneric_varchar *variable =
|
||||||
@ -428,7 +514,7 @@ ECPGexecute(struct statement * stmt)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
strcpy(newcopy, copiedquery);
|
strcpy(newcopy, copiedquery);
|
||||||
if ((p = strstr(newcopy, ";;")) == NULL)
|
if ((p = next_insert(newcopy)) == NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -449,7 +535,7 @@ ECPGexecute(struct statement * stmt)
|
|||||||
strcat(newcopy,
|
strcat(newcopy,
|
||||||
copiedquery
|
copiedquery
|
||||||
+ (p - newcopy)
|
+ (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. */
|
/* 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);
|
register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
|
||||||
return false;
|
return false;
|
||||||
@ -898,7 +984,21 @@ ECPGtrans(int lineno, const char *transaction)
|
|||||||
PQclear(res);
|
PQclear(res);
|
||||||
}
|
}
|
||||||
if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
|
if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
|
||||||
|
{
|
||||||
|
struct prepared_statement *this;
|
||||||
|
|
||||||
committed = 1;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1033,3 +1133,109 @@ sqlprint(void)
|
|||||||
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
|
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
|
||||||
printf("sql error %s\n", sqlca.sqlerrm.sqlerrmc);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ ECPGtype_name(enum ECPGttype typ)
|
|||||||
return "bool";
|
return "bool";
|
||||||
case ECPGt_varchar:
|
case ECPGt_varchar:
|
||||||
return "varchar";
|
return "varchar";
|
||||||
|
case ECPGt_char_variable:
|
||||||
|
return "char";
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -2,20 +2,25 @@ SRCDIR= ../../..
|
|||||||
include $(SRCDIR)/Makefile.global
|
include $(SRCDIR)/Makefile.global
|
||||||
|
|
||||||
MAJOR_VERSION=2
|
MAJOR_VERSION=2
|
||||||
MINOR_VERSION=4
|
MINOR_VERSION=5
|
||||||
PATCHLEVEL=9
|
PATCHLEVEL=0
|
||||||
|
|
||||||
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
|
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
|
||||||
-DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \
|
-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
|
keywords.o c_keywords.o ../lib/typename.o
|
||||||
|
|
||||||
all:: ecpg
|
all:: ecpg
|
||||||
|
|
||||||
|
preproc.c preproc.h: preproc.y
|
||||||
|
$(YACC) $(YFLAGS) $<
|
||||||
|
mv y.tab.c preproc.c
|
||||||
|
mv y.tab.h preproc.h
|
||||||
|
|
||||||
clean:
|
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: all
|
||||||
$(INSTALL) $(INSTL_EXE_OPTS) ecpg$(X) $(DESTDIR)$(BINDIR)
|
$(INSTALL) $(INSTL_EXE_OPTS) ecpg$(X) $(DESTDIR)$(BINDIR)
|
||||||
@ -31,13 +36,10 @@ pgc.c: pgc.l
|
|||||||
$(LEX) $<
|
$(LEX) $<
|
||||||
mv lex.yy.c pgc.c
|
mv lex.yy.c pgc.c
|
||||||
|
|
||||||
y.tab.h y.tab.c: preproc.y
|
preproc.o : preproc.h ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c
|
||||||
$(YACC) $(YFLAGS) $<
|
|
||||||
|
|
||||||
y.tab.o : y.tab.h ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c
|
|
||||||
type.o : ../include/ecpgtype.h
|
type.o : ../include/ecpgtype.h
|
||||||
pgc.o : ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c y.tab.h
|
pgc.o : ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c preproc.h
|
||||||
keywords.o: ../include/ecpgtype.h y.tab.h
|
keywords.o: ../include/ecpgtype.h preproc.h
|
||||||
c_keywords.o: ../include/ecpgtype.h y.tab.h
|
c_keywords.o: ../include/ecpgtype.h preproc.h
|
||||||
ecpg_keywords.o: ../include/ecpgtype.h y.tab.h
|
ecpg_keywords.o: ../include/ecpgtype.h preproc.h
|
||||||
|
|
||||||
|
@ -9,9 +9,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
#include "type.h"
|
|
||||||
#include "y.tab.h"
|
|
||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
|
#include "preproc.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of (keyword-name, keyword-token-value) pairs.
|
* List of (keyword-name, keyword-token-value) pairs.
|
||||||
|
@ -25,6 +25,7 @@ extern char *optarg;
|
|||||||
struct _include_path *include_paths;
|
struct _include_path *include_paths;
|
||||||
int no_auto_trans = 0;
|
int no_auto_trans = 0;
|
||||||
struct cursor *cur = NULL;
|
struct cursor *cur = NULL;
|
||||||
|
struct typedefs *types = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(char *progname)
|
usage(char *progname)
|
||||||
@ -155,22 +156,22 @@ main(int argc, char *const argv[])
|
|||||||
{
|
{
|
||||||
struct cursor *ptr;
|
struct cursor *ptr;
|
||||||
struct _defines *defptr;
|
struct _defines *defptr;
|
||||||
|
struct typedefs *typeptr;
|
||||||
|
|
||||||
/* remove old cursor definitions if any are still there */
|
/* remove old cursor definitions if any are still there */
|
||||||
for (ptr = cur; ptr != NULL;)
|
for (ptr = cur; ptr != NULL;)
|
||||||
{
|
{
|
||||||
struct cursor *this = ptr;
|
struct cursor *this = ptr;
|
||||||
struct arguments *l1,
|
struct arguments *l1, *l2;
|
||||||
*l2;
|
|
||||||
|
|
||||||
free(ptr->command);
|
free(ptr->command);
|
||||||
free(ptr->name);
|
free(ptr->name);
|
||||||
for (l1 = argsinsert; l1; l1 = l2)
|
for (l1 = ptr->argsinsert; l1; l1 = l2)
|
||||||
{
|
{
|
||||||
l2 = l1->next;
|
l2 = l1->next;
|
||||||
free(l1);
|
free(l1);
|
||||||
}
|
}
|
||||||
for (l1 = argsresult; l1; l1 = l2)
|
for (l1 = ptr->argsresult; l1; l1 = l2)
|
||||||
{
|
{
|
||||||
l2 = l1->next;
|
l2 = l1->next;
|
||||||
free(l1);
|
free(l1);
|
||||||
@ -190,6 +191,18 @@ main(int argc, char *const argv[])
|
|||||||
free(this);
|
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 */
|
/* initialize lex */
|
||||||
lex_init();
|
lex_init();
|
||||||
|
|
||||||
|
@ -9,9 +9,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
#include "type.h"
|
|
||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
#include "y.tab.h"
|
#include "preproc.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of (keyword-name, keyword-token-value) pairs.
|
* List of (keyword-name, keyword-token-value) pairs.
|
||||||
@ -21,25 +20,38 @@
|
|||||||
*/
|
*/
|
||||||
static ScanKeyword ScanKeywords[] = {
|
static ScanKeyword ScanKeywords[] = {
|
||||||
/* name value */
|
/* name value */
|
||||||
|
{"bool", SQL_BOOL},
|
||||||
{"break", SQL_BREAK},
|
{"break", SQL_BREAK},
|
||||||
{"call", SQL_CALL},
|
{"call", SQL_CALL},
|
||||||
{"connect", SQL_CONNECT},
|
{"connect", SQL_CONNECT},
|
||||||
{"connection", SQL_CONNECTION},
|
{"connection", SQL_CONNECTION},
|
||||||
{"continue", SQL_CONTINUE},
|
{"continue", SQL_CONTINUE},
|
||||||
|
{"deallocate", SQL_DEALLOCATE},
|
||||||
{"disconnect", SQL_DISCONNECT},
|
{"disconnect", SQL_DISCONNECT},
|
||||||
|
{"enum", SQL_ENUM},
|
||||||
{"found", SQL_FOUND},
|
{"found", SQL_FOUND},
|
||||||
|
{"free", SQL_FREE},
|
||||||
{"go", SQL_GO},
|
{"go", SQL_GO},
|
||||||
{"goto", SQL_GOTO},
|
{"goto", SQL_GOTO},
|
||||||
{"identified", SQL_IDENTIFIED},
|
{"identified", SQL_IDENTIFIED},
|
||||||
{"immediate", SQL_IMMEDIATE},
|
{"immediate", SQL_IMMEDIATE},
|
||||||
{"indicator", SQL_INDICATOR},
|
{"indicator", SQL_INDICATOR},
|
||||||
|
{"int", SQL_INT},
|
||||||
|
{"long", SQL_LONG},
|
||||||
{"open", SQL_OPEN},
|
{"open", SQL_OPEN},
|
||||||
|
{"prepare", SQL_PREPARE},
|
||||||
|
{"reference", SQL_REFERENCE},
|
||||||
{"release", SQL_RELEASE},
|
{"release", SQL_RELEASE},
|
||||||
{"section", SQL_SECTION},
|
{"section", SQL_SECTION},
|
||||||
|
{"short", SQL_SHORT},
|
||||||
|
{"signed", SQL_SIGNED},
|
||||||
{"sqlerror", SQL_SQLERROR},
|
{"sqlerror", SQL_SQLERROR},
|
||||||
{"sqlprint", SQL_SQLPRINT},
|
{"sqlprint", SQL_SQLPRINT},
|
||||||
{"sqlwarning", SQL_SQLWARNING},
|
{"sqlwarning", SQL_SQLWARNING},
|
||||||
{"stop", SQL_STOP},
|
{"stop", SQL_STOP},
|
||||||
|
{"struct", SQL_STRUCT},
|
||||||
|
{"unsigned", SQL_UNSIGNED},
|
||||||
|
{"var", SQL_VAR},
|
||||||
{"whenever", SQL_WHENEVER},
|
{"whenever", SQL_WHENEVER},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,63 +1,23 @@
|
|||||||
#include "parser/keywords.h"
|
#include "parser/keywords.h"
|
||||||
|
#include "type.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
/* variables */
|
/* variables */
|
||||||
|
|
||||||
extern int braces_open,
|
extern int braces_open,
|
||||||
no_auto_trans;
|
no_auto_trans, struct_level;
|
||||||
extern char *yytext;
|
extern char *yytext;
|
||||||
extern int yylineno,
|
extern int yylineno,
|
||||||
yyleng;
|
yyleng;
|
||||||
extern FILE *yyin,
|
extern FILE *yyin,
|
||||||
*yyout;
|
*yyout;
|
||||||
|
|
||||||
struct _include_path
|
|
||||||
{
|
|
||||||
char *path;
|
|
||||||
struct _include_path *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct _include_path *include_paths;
|
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;
|
extern struct cursor *cur;
|
||||||
|
extern struct typedefs *types;
|
||||||
struct _defines
|
|
||||||
{
|
|
||||||
char *old;
|
|
||||||
char *new;
|
|
||||||
struct _defines *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct _defines *defines;
|
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 ECPGtype ecpg_no_indicator;
|
||||||
extern struct variable 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 *argsinsert;
|
||||||
extern struct arguments *argsresult;
|
extern struct arguments *argsresult;
|
||||||
|
|
||||||
@ -77,6 +37,7 @@ extern void yyerror(char *);
|
|||||||
#define OK 0
|
#define OK 0
|
||||||
#define PARSE_ERROR -1
|
#define PARSE_ERROR -1
|
||||||
#define ILLEGAL_OPTION -2
|
#define ILLEGAL_OPTION -2
|
||||||
|
#define INDICATOR_NOT_ARRAY -3
|
||||||
|
|
||||||
#define NO_INCLUDE_FILE ENOENT
|
#define NO_INCLUDE_FILE ENOENT
|
||||||
#define OUT_OF_MEMORY ENOMEM
|
#define OUT_OF_MEMORY ENOMEM
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.10 1999/02/13 23:22:35 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.11 1999/02/20 07:01:00 scrappy Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -18,7 +18,7 @@
|
|||||||
#include "nodes/parsenodes.h"
|
#include "nodes/parsenodes.h"
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
#include "y.tab.h"
|
#include "preproc.h"
|
||||||
#include "parser/keywords.h"
|
#include "parser/keywords.h"
|
||||||
#include "utils/elog.h"
|
#include "utils/elog.h"
|
||||||
|
|
||||||
@ -69,9 +69,6 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"createdb", CREATEDB},
|
{"createdb", CREATEDB},
|
||||||
{"createuser", CREATEUSER},
|
{"createuser", CREATEUSER},
|
||||||
{"cross", CROSS},
|
{"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_date", CURRENT_DATE},
|
||||||
{"current_time", CURRENT_TIME},
|
{"current_time", CURRENT_TIME},
|
||||||
{"current_timestamp", CURRENT_TIMESTAMP},
|
{"current_timestamp", CURRENT_TIMESTAMP},
|
||||||
@ -96,6 +93,7 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"end", END_TRANS},
|
{"end", END_TRANS},
|
||||||
/***S*I***/
|
/***S*I***/
|
||||||
{"except", EXCEPT},
|
{"except", EXCEPT},
|
||||||
|
|
||||||
{"execute", EXECUTE},
|
{"execute", EXECUTE},
|
||||||
{"exists", EXISTS},
|
{"exists", EXISTS},
|
||||||
{"explain", EXPLAIN},
|
{"explain", EXPLAIN},
|
||||||
@ -125,6 +123,7 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"instead", INSTEAD},
|
{"instead", INSTEAD},
|
||||||
/***S*I***/
|
/***S*I***/
|
||||||
{"intersect", INTERSECT},
|
{"intersect", INTERSECT},
|
||||||
|
|
||||||
{"interval", INTERVAL},
|
{"interval", INTERVAL},
|
||||||
{"into", INTO},
|
{"into", INTO},
|
||||||
{"is", IS},
|
{"is", IS},
|
||||||
@ -138,6 +137,7 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"left", LEFT},
|
{"left", LEFT},
|
||||||
{"level", LEVEL},
|
{"level", LEVEL},
|
||||||
{"like", LIKE},
|
{"like", LIKE},
|
||||||
|
{"limit", LIMIT},
|
||||||
{"listen", LISTEN},
|
{"listen", LISTEN},
|
||||||
{"load", LOAD},
|
{"load", LOAD},
|
||||||
{"local", LOCAL},
|
{"local", LOCAL},
|
||||||
@ -167,6 +167,7 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"nullif", NULLIF},
|
{"nullif", NULLIF},
|
||||||
{"numeric", NUMERIC},
|
{"numeric", NUMERIC},
|
||||||
{"of", OF},
|
{"of", OF},
|
||||||
|
{"offset", OFFSET},
|
||||||
{"oids", OIDS},
|
{"oids", OIDS},
|
||||||
{"old", CURRENT},
|
{"old", CURRENT},
|
||||||
{"on", ON},
|
{"on", ON},
|
||||||
|
@ -24,9 +24,8 @@
|
|||||||
#include "nodes/parsenodes.h"
|
#include "nodes/parsenodes.h"
|
||||||
#include "parser/gramparse.h"
|
#include "parser/gramparse.h"
|
||||||
#include "parser/scansup.h"
|
#include "parser/scansup.h"
|
||||||
#include "type.h"
|
|
||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
#include "y.tab.h"
|
#include "preproc.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
|
||||||
/* some versions of lex define this as a macro */
|
/* some versions of lex define this as a macro */
|
||||||
@ -241,7 +240,7 @@ cppline {space}*#.*(\\{space}*\n)*\n*
|
|||||||
}
|
}
|
||||||
<xq>{xqstop} {
|
<xq>{xqstop} {
|
||||||
BEGIN(SQL);
|
BEGIN(SQL);
|
||||||
yylval.str = strdup(scanstr(literal));
|
yylval.str = mm_strdup(scanstr(literal));
|
||||||
return SCONST;
|
return SCONST;
|
||||||
}
|
}
|
||||||
<xq>{xqdouble} |
|
<xq>{xqdouble} |
|
||||||
@ -276,7 +275,7 @@ cppline {space}*#.*(\\{space}*\n)*\n*
|
|||||||
}
|
}
|
||||||
<xd>{xdstop} {
|
<xd>{xdstop} {
|
||||||
BEGIN(SQL);
|
BEGIN(SQL);
|
||||||
yylval.str = strdup(literal);
|
yylval.str = mm_strdup(literal);
|
||||||
return CSTRING;
|
return CSTRING;
|
||||||
}
|
}
|
||||||
<xd>{xdinside} {
|
<xd>{xdinside} {
|
||||||
@ -292,7 +291,7 @@ cppline {space}*#.*(\\{space}*\n)*\n*
|
|||||||
}
|
}
|
||||||
<xdc>{xdstop} {
|
<xdc>{xdstop} {
|
||||||
BEGIN(C);
|
BEGIN(C);
|
||||||
yylval.str = strdup(literal);
|
yylval.str = mm_strdup(literal);
|
||||||
return CSTRING;
|
return CSTRING;
|
||||||
}
|
}
|
||||||
<xdc>{xdinside} {
|
<xdc>{xdinside} {
|
||||||
@ -316,14 +315,14 @@ cppline {space}*#.*(\\{space}*\n)*\n*
|
|||||||
}
|
}
|
||||||
<SQL>{self} { return yytext[0]; }
|
<SQL>{self} { return yytext[0]; }
|
||||||
<SQL>{operator}/-[\.0-9] {
|
<SQL>{operator}/-[\.0-9] {
|
||||||
yylval.str = strdup((char*)yytext);
|
yylval.str = mm_strdup((char*)yytext);
|
||||||
return Op;
|
return Op;
|
||||||
}
|
}
|
||||||
<SQL>{operator} {
|
<SQL>{operator} {
|
||||||
if (strcmp((char*)yytext,"!=") == 0)
|
if (strcmp((char*)yytext,"!=") == 0)
|
||||||
yylval.str = strdup("<>"); /* compatability */
|
yylval.str = mm_strdup("<>"); /* compatability */
|
||||||
else
|
else
|
||||||
yylval.str = strdup((char*)yytext);
|
yylval.str = mm_strdup((char*)yytext);
|
||||||
return Op;
|
return Op;
|
||||||
}
|
}
|
||||||
<SQL>{param} {
|
<SQL>{param} {
|
||||||
@ -342,7 +341,6 @@ cppline {space}*#.*(\\{space}*\n)*\n*
|
|||||||
if (isascii((unsigned char)lower_text[i]) && isupper(lower_text[i]))
|
if (isascii((unsigned char)lower_text[i]) && isupper(lower_text[i]))
|
||||||
lower_text[i] = tolower(lower_text[i]);
|
lower_text[i] = tolower(lower_text[i]);
|
||||||
|
|
||||||
printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|
||||||
keyword = ScanKeywordLookup((char*)lower_text);
|
keyword = ScanKeywordLookup((char*)lower_text);
|
||||||
if (keyword != NULL) {
|
if (keyword != NULL) {
|
||||||
return keyword->value;
|
return keyword->value;
|
||||||
@ -367,7 +365,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
|
|
||||||
yb->buffer = YY_CURRENT_BUFFER;
|
yb->buffer = YY_CURRENT_BUFFER;
|
||||||
yb->lineno = yylineno;
|
yb->lineno = yylineno;
|
||||||
yb->filename = strdup(input_filename);
|
yb->filename = mm_strdup(input_filename);
|
||||||
yb->next = yy_buffer;
|
yb->next = yy_buffer;
|
||||||
|
|
||||||
yy_buffer = yb;
|
yy_buffer = yb;
|
||||||
@ -378,7 +376,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
}
|
}
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
yylval.str = strdup((char*)yytext);
|
yylval.str = mm_strdup((char*)yytext);
|
||||||
return IDENT;
|
return IDENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,7 +468,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
return ICONST;
|
return ICONST;
|
||||||
}
|
}
|
||||||
<SQL>:{identifier}(("->"|\.){identifier})* {
|
<SQL>:{identifier}(("->"|\.){identifier})* {
|
||||||
yylval.str = strdup((char*)yytext+1);
|
yylval.str = mm_strdup((char*)yytext+1);
|
||||||
return(CVARIABLE);
|
return(CVARIABLE);
|
||||||
}
|
}
|
||||||
<SQL>{identifier} {
|
<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]))
|
if (isascii((unsigned char)lower_text[i]) && isupper(lower_text[i]))
|
||||||
lower_text[i] = tolower(lower_text[i]);
|
lower_text[i] = tolower(lower_text[i]);
|
||||||
|
|
||||||
printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|
||||||
keyword = ScanKeywordLookup((char*)lower_text);
|
keyword = ScanKeywordLookup((char*)lower_text);
|
||||||
if (keyword != NULL) {
|
if (keyword != NULL) {
|
||||||
return keyword->value;
|
return keyword->value;
|
||||||
@ -509,7 +506,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
|
|
||||||
yb->buffer = YY_CURRENT_BUFFER;
|
yb->buffer = YY_CURRENT_BUFFER;
|
||||||
yb->lineno = yylineno;
|
yb->lineno = yylineno;
|
||||||
yb->filename = strdup(input_filename);
|
yb->filename = mm_strdup(input_filename);
|
||||||
yb->next = yy_buffer;
|
yb->next = yy_buffer;
|
||||||
|
|
||||||
yy_buffer = yb;
|
yy_buffer = yb;
|
||||||
@ -520,19 +517,26 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
}
|
}
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
yylval.str = strdup((char*)yytext);
|
yylval.str = mm_strdup((char*)yytext);
|
||||||
return IDENT;
|
return IDENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<SQL>{space} { /* ignore */ }
|
<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]; }
|
<SQL>{other} { return yytext[0]; }
|
||||||
<C>{exec}{space}{sql} { BEGIN SQL; return SQL_START; }
|
<C>{exec}{space}{sql} { BEGIN SQL; return SQL_START; }
|
||||||
<C>{ccomment} { /* ignore */ }
|
<C>{ccomment} { /* ignore */ }
|
||||||
<C>{cppline} {
|
<C>{cppline} {
|
||||||
yylval.str = strdup((char*)yytext);
|
yylval.str = mm_strdup((char*)yytext);
|
||||||
return(CPP_LINE);
|
return(CPP_LINE);
|
||||||
}
|
}
|
||||||
<C>{identifier} {
|
<C>{identifier} {
|
||||||
@ -556,7 +560,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
|
|
||||||
yb->buffer = YY_CURRENT_BUFFER;
|
yb->buffer = YY_CURRENT_BUFFER;
|
||||||
yb->lineno = yylineno;
|
yb->lineno = yylineno;
|
||||||
yb->filename = strdup(input_filename);
|
yb->filename = mm_strdup(input_filename);
|
||||||
yb->next = yy_buffer;
|
yb->next = yy_buffer;
|
||||||
|
|
||||||
yy_buffer = yb;
|
yy_buffer = yb;
|
||||||
@ -567,7 +571,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
}
|
}
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
yylval.str = strdup((char*)yytext);
|
yylval.str = mm_strdup((char*)yytext);
|
||||||
return IDENT;
|
return IDENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -585,7 +589,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
<C>{exec}{space}{sql}{space}{define} {BEGIN(def_ident);}
|
<C>{exec}{space}{sql}{space}{define} {BEGIN(def_ident);}
|
||||||
<def_ident>{space} {}
|
<def_ident>{space} {}
|
||||||
<def_ident>{identifier} {
|
<def_ident>{identifier} {
|
||||||
old = strdup(yytext);
|
old = mm_strdup(yytext);
|
||||||
BEGIN(def);
|
BEGIN(def);
|
||||||
llen = 0;
|
llen = 0;
|
||||||
*literal = '\0';
|
*literal = '\0';
|
||||||
@ -599,7 +603,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
if (strcmp(old, ptr->old) == 0)
|
if (strcmp(old, ptr->old) == 0)
|
||||||
{
|
{
|
||||||
free(ptr->new);
|
free(ptr->new);
|
||||||
ptr->new = strdup(scanstr(literal));
|
ptr->new = mm_strdup(scanstr(literal));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
@ -608,7 +612,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
|
|
||||||
/* initial definition */
|
/* initial definition */
|
||||||
this->old = old;
|
this->old = old;
|
||||||
this->new = strdup(scanstr(literal));
|
this->new = mm_strdup(scanstr(literal));
|
||||||
this->next = defines;
|
this->next = defines;
|
||||||
defines = this;
|
defines = this;
|
||||||
}
|
}
|
||||||
@ -666,7 +670,7 @@ printf("yyt= %s, lt = %s\n", yytext, lower_text);
|
|||||||
exit(NO_INCLUDE_FILE);
|
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 ));
|
yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE ));
|
||||||
yylineno = 0;
|
yylineno = 0;
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "type.h"
|
|
||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
|
|
||||||
/* malloc + error check */
|
/* malloc + error check */
|
||||||
@ -36,8 +35,8 @@ mm_strdup(const char *string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* duplicate memberlist */
|
/* duplicate memberlist */
|
||||||
static struct ECPGstruct_member *
|
struct ECPGstruct_member *
|
||||||
struct_member_dup(struct ECPGstruct_member * rm)
|
ECPGstruct_member_dup(struct ECPGstruct_member * rm)
|
||||||
{
|
{
|
||||||
struct ECPGstruct_member *new = NULL;
|
struct ECPGstruct_member *new = NULL;
|
||||||
|
|
||||||
@ -71,7 +70,8 @@ void
|
|||||||
ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start)
|
ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start)
|
||||||
{
|
{
|
||||||
struct ECPGstruct_member *ptr,
|
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->name = strdup(name);
|
||||||
ne->typ = type;
|
ne->typ = type;
|
||||||
@ -112,7 +112,7 @@ ECPGmake_struct_type(struct ECPGstruct_member * rm)
|
|||||||
{
|
{
|
||||||
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1);
|
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1);
|
||||||
|
|
||||||
ne->u.members = struct_member_dup(rm);
|
ne->u.members = ECPGstruct_member_dup(rm);
|
||||||
|
|
||||||
return ne;
|
return ne;
|
||||||
}
|
}
|
||||||
@ -160,6 +160,9 @@ get_type(enum ECPGttype typ)
|
|||||||
case ECPGt_NO_INDICATOR: /* no indicator */
|
case ECPGt_NO_INDICATOR: /* no indicator */
|
||||||
return ("ECPGt_NO_INDICATOR");
|
return ("ECPGt_NO_INDICATOR");
|
||||||
break;
|
break;
|
||||||
|
case ECPGt_char_variable: /* string that should not be quoted */
|
||||||
|
return ("ECPGt_char_variable");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
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,
|
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 == &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);
|
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");
|
||||||
|
exit(INDICATOR_NOT_ARRAY);
|
||||||
|
}
|
||||||
ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ,
|
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)
|
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)
|
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);
|
ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, NULL, prefix, ind_prefix);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
yyerror("Internal error: unknown datatype, pleqase inform pgsql-bugs@postgresql.org");
|
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);
|
||||||
@ -260,6 +270,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
|||||||
break;
|
break;
|
||||||
case ECPGt_char:
|
case ECPGt_char:
|
||||||
case ECPGt_unsigned_char:
|
case ECPGt_unsigned_char:
|
||||||
|
case ECPGt_char_variable:
|
||||||
sprintf(offset, "%ld*sizeof(char)", varcharsize);
|
sprintf(offset, "%ld*sizeof(char)", varcharsize);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -30,6 +30,7 @@ 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 *);
|
||||||
|
struct ECPGstruct_member * ECPGstruct_member_dup(struct ECPGstruct_member *);
|
||||||
|
|
||||||
/* Frees a type. */
|
/* Frees a type. */
|
||||||
void ECPGfree_struct_member(struct ECPGstruct_member *);
|
void ECPGfree_struct_member(struct ECPGstruct_member *);
|
||||||
@ -86,4 +87,52 @@ struct this_type
|
|||||||
{
|
{
|
||||||
enum ECPGttype type_enum;
|
enum ECPGttype type_enum;
|
||||||
char *type_str;
|
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;
|
||||||
};
|
};
|
||||||
|
@ -4,16 +4,25 @@ exec sql whenever sqlerror sqlprint;
|
|||||||
|
|
||||||
exec sql include sqlca;
|
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
|
int
|
||||||
main ()
|
main ()
|
||||||
{
|
{
|
||||||
exec sql begin declare section;
|
exec sql begin declare section;
|
||||||
int amount[AMOUNT];
|
intarray amount;
|
||||||
char name[AMOUNT][8];
|
int increment=100;
|
||||||
|
char name[AMOUNT][6];
|
||||||
|
char letter[AMOUNT][1];
|
||||||
|
char command[128];
|
||||||
exec sql end declare section;
|
exec sql end declare section;
|
||||||
char msg[128], command[128];
|
exec sql var name is string(AMOUNT);
|
||||||
|
char msg[128];
|
||||||
FILE *dbgs;
|
FILE *dbgs;
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
@ -24,30 +33,40 @@ exec sql end declare section;
|
|||||||
exec sql connect to mm;
|
exec sql connect to mm;
|
||||||
|
|
||||||
strcpy(msg, "create");
|
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");
|
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;
|
exec sql execute immediate :command;
|
||||||
|
|
||||||
strcpy(msg, "excute insert 2");
|
strcpy(msg, "execute insert 2");
|
||||||
sprintf(command, "insert into test(name, amount) select name, amount+1 from test");
|
sprintf(command, "insert into test(name, amount, letter) select name, amount+1, letter from test");
|
||||||
exec sql execute immediate :command;
|
exec sql execute immediate :command;
|
||||||
|
|
||||||
strcpy(msg, "excute insert 3");
|
strcpy(msg, "execute insert 3");
|
||||||
sprintf(command, "insert into test(name, amount) select name, amount+10 from test");
|
sprintf(command, "insert into test(name, amount, letter) select name, amount+10, letter from test");
|
||||||
exec sql execute immediate :command;
|
exec sql execute immediate :command;
|
||||||
|
|
||||||
printf("Inserted %d tuples via execute immediate\n", sqlca.sqlerrd[2]);
|
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");
|
strcpy(msg, "commit");
|
||||||
exec sql commit;
|
exec sql commit;
|
||||||
|
|
||||||
strcpy(msg, "select");
|
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++)
|
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");
|
strcpy(msg, "drop");
|
||||||
exec sql drop table test;
|
exec sql drop table test;
|
||||||
|
@ -2,25 +2,30 @@
|
|||||||
|
|
||||||
exec sql include header_test;
|
exec sql include header_test;
|
||||||
|
|
||||||
|
exec sql type c is char reference;
|
||||||
|
typedef char* c;
|
||||||
|
|
||||||
int
|
int
|
||||||
main ()
|
main ()
|
||||||
{
|
{
|
||||||
|
typedef struct { long born; short age; } birthinfo;
|
||||||
|
exec sql type birthinfo is struct { long born; short age; };
|
||||||
exec sql begin declare section;
|
exec sql begin declare section;
|
||||||
struct personal_struct { varchar name[8];
|
struct personal_struct { varchar name[8];
|
||||||
struct birth_struct { long born;
|
birthinfo birth;
|
||||||
short age;
|
|
||||||
} birth;
|
|
||||||
} personal;
|
} personal;
|
||||||
struct personal_indicator { short ind_name;
|
struct personal_indicator { int ind_name;
|
||||||
struct birth_indicator { short ind_born;
|
birthinfo ind_birth;
|
||||||
int ind_age;
|
|
||||||
} ind_birth;
|
|
||||||
} ind_personal;
|
} ind_personal;
|
||||||
long ind_married;
|
int ind_married;
|
||||||
char married[9];
|
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 end declare section;
|
||||||
|
|
||||||
exec sql declare cur cursor for
|
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 from meskes;
|
||||||
|
|
||||||
char msg[128], command[128];
|
char msg[128], command[128];
|
||||||
@ -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));
|
exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
|
||||||
|
|
||||||
strcpy(msg, "insert");
|
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, 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 ('Carsten', 19910103, 8);
|
||||||
exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 4);
|
exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 5);
|
||||||
exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 0);
|
exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 1);
|
||||||
|
|
||||||
strcpy(msg, "commit");
|
strcpy(msg, "commit");
|
||||||
exec sql commit;
|
exec sql commit;
|
||||||
@ -53,12 +58,44 @@ exec sql declare cur cursor for
|
|||||||
while (1) {
|
while (1) {
|
||||||
strcpy(msg, "fetch");
|
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;
|
||||||
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");
|
strcpy(msg, "close");
|
||||||
exec sql close cur;
|
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");
|
strcpy(msg, "drop");
|
||||||
exec sql drop table meskes;
|
exec sql drop table meskes;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user