mirror of
https://github.com/postgres/postgres.git
synced 2025-11-07 19:06:32 +03:00
This one cleans the cursor problems ecpg had so far. It is now able
to understand cursors with variables. Michael
This commit is contained in:
@@ -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(""); }
|
||||
|
||||
Reference in New Issue
Block a user