Commit c6dd1e63 authored by Bruce Momjian's avatar Bruce Momjian

This one cleans the cursor problems ecpg had so far. It is now able

to understand cursors with variables.

Michael
parent 79c8d2e3
......@@ -270,3 +270,10 @@ Mon Aug 3 17:23:18 CEST 1998
- Fixed cursor handling
- Set version to 2.3.5
- Set library version to 2.4
Fri Aug 7 12:38:50 CEST 1998
- Fixed cursor handling once again
- Added support for variables in cursor
- Set version to 2.3.6
- Set library version to 2.5
What happens to a cursor declaration with variables?
The complete structure definition has to be listed inside the declare
section of the structure variable for ecpg to be able to understand it.
Variable type bool has to be checked. I never used it so far.
Variable type bool has to be tested. I never used it so far.
The error message for "no data" in an exec sql insert select from statement
has to be 100.
......
......@@ -13,9 +13,6 @@ bool ECPGdisconnect(int, const char *);
void ECPGlog(const char *format,...);
bool ECPGdeclare(int, const char *, char *);
bool ECPGopen(int, const char *);
#ifdef LIBPQ_FE_H
bool ECPGsetdb(PGconn *);
......
......@@ -4,7 +4,7 @@ include $(SRCDIR)/Makefile.global
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
SO_MAJOR_VERSION=2
SO_MINOR_VERSION=4
SO_MINOR_VERSION=5
PORTNAME=@PORTNAME@
......
This diff is collapsed.
......@@ -23,6 +23,7 @@ extern char *optarg;
struct _include_path *include_paths;
static int no_auto_trans = 0;
struct cursor *cur = NULL;
static void
usage(char *progname)
......@@ -138,6 +139,24 @@ main(int argc, char *const argv[])
{
struct cursor *ptr;
/* remove old cursor definitions if any are still there */
for (ptr = cur; ptr != NULL; ptr=ptr->next)
{
struct arguments *l1, *l2;
free(ptr->command);
free(ptr->name);
for (l1 = argsinsert; l1; l1 = l2)
{
l2 = l1->next;
free(l1);
}
for (l1 = argsresult; l1; l1 = l2)
{
l2 = l1->next;
free(l1);
}
}
/* initialize lex */
lex_init();
......
......@@ -16,6 +16,15 @@ struct _include_path { char * path;
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;
/* This is a linked list of the variable names and types. */
struct variable
{
......@@ -28,6 +37,15 @@ struct variable
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;
/* functions */
extern void lex_init(void);
......
......@@ -245,14 +245,9 @@ remove_variables(int brace_level)
* These are of two kinds: input and output.
* I will make two lists for them.
*/
struct arguments {
struct variable * variable;
struct variable * indicator;
struct arguments * next;
};
static struct arguments * argsinsert = NULL;
static struct arguments * argsresult = NULL;
struct arguments * argsinsert = NULL;
struct arguments * argsresult = NULL;
static void
reset_variables(void)
......@@ -279,7 +274,7 @@ add_variable(struct arguments ** list, struct variable * var, struct variable *
deletes the list as we go on.
*/
static void
dump_variables(struct arguments * list)
dump_variables(struct arguments * list, int mode)
{
if (list == NULL)
{
......@@ -290,7 +285,7 @@ dump_variables(struct arguments * list)
end of the list:
*/
dump_variables(list->next);
dump_variables(list->next, mode);
/* Then the current element and its indicator */
ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
......@@ -298,7 +293,8 @@ dump_variables(struct arguments * list)
(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);
/* Then release the list element. */
free(list);
if (mode != 0)
free(list);
}
static void
......@@ -494,9 +490,9 @@ output_statement(char * stmt, int mode)
fputs("\", ", yyout);
/* dump variables to C file*/
dump_variables(argsinsert);
dump_variables(argsinsert, 1);
fputs("ECPGt_EOIT, ", yyout);
dump_variables(argsresult);
dump_variables(argsresult, 1);
fputs("ECPGt_EORT);", yyout);
whenever_action(mode);
free(stmt);
......@@ -737,10 +733,9 @@ stmt: AddAttrStmt { output_statement($1, 0); }
| RenameStmt { output_statement($1, 0); }
| RevokeStmt { output_statement($1, 0); }
| OptimizableStmt {
if (strncmp($1, "ECPGdeclare" , sizeof("ECPGdeclare")-1) == 0)
if (strncmp($1, "/* " , sizeof("/* ")-1) == 0)
{
fputs($1, yyout);
whenever_action(0);
free($1);
}
else
......@@ -775,7 +770,27 @@ stmt: AddAttrStmt { output_statement($1, 0); }
whenever_action(0);
free($1);
}
| ECPGOpen { fprintf(yyout, "ECPGopen(__LINE__, %s);", $1);
| ECPGOpen {
struct cursor *ptr;
for (ptr = cur; ptr != NULL; ptr=ptr->next)
{
if (strcmp(ptr->name, $1) == 0)
break;
}
if (ptr == NULL)
{
sprintf(errortext, "trying to open undeclared cursor %s\n", $1);
yyerror(errortext);
}
fprintf(yyout, "ECPGdo(__LINE__, \"%s\",", ptr->command);
/* dump variables to C file*/
dump_variables(ptr->argsinsert, 0);
fputs("ECPGt_EOIT, ", yyout);
dump_variables(ptr->argsresult, 0);
fputs("ECPGt_EORT);", yyout);
whenever_action(0);
free($1);
}
......@@ -2359,7 +2374,31 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR
group_clause having_clause
union_clause sort_clause
{
$$ = make5_str(make1_str("ECPGdeclare(__LINE__, \""), $2, make1_str("\", \""), cat4_str(cat5_str(cat5_str(make1_str("declare"), strdup($2), $3, make1_str("cursor for select"), $7), $8, $9, $10, $11), $12, $13, $14), make1_str("\");"));
struct cursor *ptr, *this;
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
if (strcmp($2, ptr->name) == 0)
{
/* re-definition is a bug*/
sprintf(errortext, "cursor %s already defined", $2);
yyerror(errortext);
}
}
this = (struct cursor *) mm_alloc(sizeof(struct cursor));
/* initial definition */
this->next = cur;
this->name = $2;
this->command = cat4_str(cat5_str(cat5_str(make1_str("declare"), strdup($2), $3, make1_str("cursor for select"), $7), $8, $9, $10, $11), $12, $13, $14);
this->argsinsert = argsinsert;
this->argsresult = argsresult;
argsinsert = argsresult = NULL;
cur = this;
$$ = cat3_str(make1_str("/*"), strdup(this->command), make1_str("*/"));
}
;
......@@ -4221,7 +4260,7 @@ execstring: cvariable |
* open is an open cursor, at the moment this has to be removed
*/
ECPGOpen: SQL_OPEN name open_opts {
$$ = make3_str(make1_str("\""), $2, make1_str("\""));
$$ = $2;
};
open_opts: /* empty */ { $$ = make1_str(""); }
......
all: test1 test2 perftest
LDFLAGS=-g -I ../include -I ../../libpq -L../lib -lecpg -L../../libpq -lpq -lcrypt --static
LDFLAGS=-g -I ../include -I ../../libpq -L../lib -lecpg -L../../libpq -lpq -lcrypt
test1: test1.c
test1.c: test1.pgc
......
......@@ -19,6 +19,10 @@ exec sql begin declare section;
long ind_married;
char married[9];
exec sql end declare section;
exec sql declare cur cursor for
select name, born, age, married from meskes;
char msg[128], command[128];
FILE *dbgs;
......@@ -26,7 +30,7 @@ exec sql end declare section;
ECPGdebug(1, dbgs);
strcpy(msg, "connect");
exec sql connect to tcp:postgresql://localhost:5432/mm;
exec sql connect to tcp:postgresql://localhost:5432/mm;
strcpy(msg, "create");
exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
......@@ -41,10 +45,6 @@ exec sql end declare section;
strcpy(msg, "commit");
exec sql commit;
strcpy(msg, "declare");
exec sql declare cur cursor for
select name, born, age, married from meskes;
strcpy(msg, "open");
exec sql open cur;
......
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