Commit a160c421 authored by Michael Meskes's avatar Michael Meskes

Added dynamic cursor names to ecpg. Almost the whole patch was done by

Boszormenyi Zoltan, with only a minor tweak or two from me.
parent da29cc80
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.8 2009/11/11 20:31:26 alvherre Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.9 2009/11/26 15:06:47 meskes Exp $ */
ECPG: stmtClosePortalStmt block ECPG: stmtClosePortalStmt block
{ {
if (INFORMIX_MODE) if (INFORMIX_MODE)
...@@ -213,18 +212,36 @@ ECPG: var_valueNumericOnly addon ...@@ -213,18 +212,36 @@ ECPG: var_valueNumericOnly addon
} }
ECPG: fetch_argscursor_name addon ECPG: fetch_argscursor_name addon
add_additional_variables($1, false); add_additional_variables($1, false);
if ($1[0] == ':')
{
free($1);
$1 = make_str("$0");
}
ECPG: fetch_argsfrom_incursor_name addon ECPG: fetch_argsfrom_incursor_name addon
add_additional_variables($2, false); add_additional_variables($2, false);
if ($2[0] == ':')
{
free($2);
$2 = make_str("$0");
}
ECPG: fetch_argsNEXTopt_from_incursor_name addon ECPG: fetch_argsNEXTopt_from_incursor_name addon
ECPG: fetch_argsPRIORopt_from_incursor_name addon ECPG: fetch_argsPRIORopt_from_incursor_name addon
ECPG: fetch_argsFIRST_Popt_from_incursor_name addon ECPG: fetch_argsFIRST_Popt_from_incursor_name addon
ECPG: fetch_argsLAST_Popt_from_incursor_name addon ECPG: fetch_argsLAST_Popt_from_incursor_name addon
ECPG: fetch_argsALLopt_from_incursor_name addon ECPG: fetch_argsALLopt_from_incursor_name addon
ECPG: fetch_argsFORWARDopt_from_incursor_name addon
ECPG: fetch_argsBACKWARDopt_from_incursor_name addon
add_additional_variables($3, false); add_additional_variables($3, false);
if ($3[0] == ':')
{
free($3);
$3 = make_str("$0");
}
ECPG: fetch_argsSignedIconstopt_from_incursor_name addon ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
add_additional_variables($3, false); add_additional_variables($3, false);
if ($3[0] == ':')
{
free($3);
$3 = make_str("$0");
}
if ($1[0] == '$') if ($1[0] == '$')
{ {
free($1); free($1);
...@@ -233,16 +250,35 @@ ECPG: fetch_argsSignedIconstopt_from_incursor_name addon ...@@ -233,16 +250,35 @@ ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsFORWARDALLopt_from_incursor_name addon ECPG: fetch_argsFORWARDALLopt_from_incursor_name addon
ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon
add_additional_variables($4, false); add_additional_variables($4, false);
if ($4[0] == ':')
{
free($4);
$4 = make_str("$0");
}
ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon
add_additional_variables($4, false); add_additional_variables($4, false);
if ($4[0] == ':')
{
free($4);
$4 = make_str("$0");
}
if ($2[0] == '$') if ($2[0] == '$')
{ {
free($2); free($2);
$2 = make_str("$0"); $2 = make_str("$0");
} }
ECPG: cursor_namename rule
| char_civar
{
char *curname = mm_alloc(strlen($1) + 2);
sprintf(curname, ":%s", $1);
free($1);
$1 = curname;
$$ = $1;
}
ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
{ {
$$.name = $2; $$.name = $2;
...@@ -260,6 +296,7 @@ ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block ...@@ -260,6 +296,7 @@ ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block
{ {
struct cursor *ptr, *this; struct cursor *ptr, *this;
char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
char *comment; char *comment;
for (ptr = cur; ptr != NULL; ptr = ptr->next) for (ptr = cur; ptr != NULL; ptr = ptr->next)
...@@ -274,7 +311,7 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt ...@@ -274,7 +311,7 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
this->name = $2; this->name = $2;
this->connection = connection; this->connection = connection;
this->opened = false; this->opened = false;
this->command = cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"), $7); this->command = cat_str(7, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for"), $7);
this->argsinsert = argsinsert; this->argsinsert = argsinsert;
this->argsresult = argsresult; this->argsresult = argsresult;
argsinsert = argsresult = NULL; argsinsert = argsresult = NULL;
...@@ -294,6 +331,11 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt ...@@ -294,6 +331,11 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
else else
$$ = comment; $$ = comment;
} }
ECPG: ClosePortalStmtCLOSEcursor_name block
{
char *cursor_marker = $2[0] == ':' ? make_str("$0") : $2;
$$ = cat2_str(make_str("close"), cursor_marker);
}
ECPG: opt_hold block ECPG: opt_hold block
{ {
if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true) if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true)
...@@ -363,6 +405,54 @@ ECPG: FetchStmtMOVEfetch_args rule ...@@ -363,6 +405,54 @@ ECPG: FetchStmtMOVEfetch_args rule
{ {
$$ = cat2_str(make_str("fetch"), $2); $$ = cat2_str(make_str("fetch"), $2);
} }
| FETCH FORWARD cursor_name opt_ecpg_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat_str(2, make_str("fetch forward"), cursor_marker);
}
| FETCH FORWARD from_in cursor_name opt_ecpg_into
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(2, make_str("fetch forward from"), cursor_marker);
}
| FETCH BACKWARD cursor_name opt_ecpg_into
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat_str(2, make_str("fetch backward"), cursor_marker);
}
| FETCH BACKWARD from_in cursor_name opt_ecpg_into
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(2, make_str("fetch backward from"), cursor_marker);
}
| MOVE FORWARD cursor_name
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat_str(2, make_str("move forward"), cursor_marker);
}
| MOVE FORWARD from_in cursor_name
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(2, make_str("move forward from"), cursor_marker);
}
| MOVE BACKWARD cursor_name
{
char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
add_additional_variables($3, false);
$$ = cat_str(2, make_str("move backward"), cursor_marker);
}
| MOVE BACKWARD from_in cursor_name
{
char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
add_additional_variables($4, false);
$$ = cat_str(2, make_str("move backward from"), cursor_marker);
}
ECPG: select_limitLIMITselect_limit_value','select_offset_value block ECPG: select_limitLIMITselect_limit_value','select_offset_value block
{ {
mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server"); mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server");
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.15 2009/11/21 05:44:05 tgl Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.16 2009/11/26 15:06:47 meskes Exp $ */
statements: /*EMPTY*/ statements: /*EMPTY*/
| statements statement | statements statement
...@@ -278,6 +278,7 @@ prepared_name: name { ...@@ -278,6 +278,7 @@ prepared_name: name {
ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name
{ {
struct cursor *ptr, *this; struct cursor *ptr, *this;
char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable)); struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
const char *con = connection ? connection : "NULL"; const char *con = connection ? connection : "NULL";
...@@ -294,7 +295,7 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared ...@@ -294,7 +295,7 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared
this->next = cur; this->next = cur;
this->name = $2; this->name = $2;
this->connection = connection; this->connection = connection;
this->command = cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for $1")); this->command = cat_str(6, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for $1"));
this->argsresult = NULL; this->argsresult = NULL;
thisquery->type = &ecpg_query; thisquery->type = &ecpg_query;
...@@ -304,6 +305,12 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared ...@@ -304,6 +305,12 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared
sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7); sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);
this->argsinsert = NULL; this->argsinsert = NULL;
if ($2[0] == ':')
{
struct variable *var = find_variable($2 + 1);
remove_variable_from_list(&argsinsert, var);
add_variable_to_head(&(this->argsinsert), var, &no_indicator);
}
add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator); add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
cur = this; cur = this;
...@@ -947,7 +954,13 @@ ECPGFree: SQL_FREE name { $$ = $2; } ...@@ -947,7 +954,13 @@ ECPGFree: SQL_FREE name { $$ = $2; }
/* /*
* open is an open cursor, at the moment this has to be removed * open is an open cursor, at the moment this has to be removed
*/ */
ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using { $$ = $2; }; ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using
{
if ($2[0] == ':')
remove_variable_from_list(&argsinsert, find_variable($2 + 1));
$$ = $2;
}
;
opt_ecpg_using: /*EMPTY*/ { $$ = EMPTY; } opt_ecpg_using: /*EMPTY*/ { $$ = EMPTY; }
| ecpg_using { $$ = $1; } | ecpg_using { $$ = $1; }
...@@ -1567,6 +1580,17 @@ civarind: cvariable indicator ...@@ -1567,6 +1580,17 @@ civarind: cvariable indicator
} }
; ;
char_civar: char_variable
{
char *ptr = strstr($1, ".arr");
if (ptr) /* varchar, we need the struct name here, not the struct element */
*ptr = '\0';
add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
$$ = $1;
}
;
civar: cvariable civar: cvariable
{ {
add_variable_to_head(&argsinsert, find_variable($1), &no_indicator); add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
...@@ -1782,6 +1806,10 @@ ecpg_into: INTO into_list { $$ = EMPTY; } ...@@ -1782,6 +1806,10 @@ ecpg_into: INTO into_list { $$ = EMPTY; }
| into_descriptor { $$ = $1; } | into_descriptor { $$ = $1; }
; ;
opt_ecpg_into: /* EMPTY */ { $$ = EMPTY; }
| ecpg_into { $$ = $1; }
;
%% %%
void base_yyerror(const char *error) void base_yyerror(const char *error)
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.3 2009/11/21 05:44:05 tgl Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.4 2009/11/26 15:06:47 meskes Exp $ */
%type <str> ECPGAllocateDescr %type <str> ECPGAllocateDescr
%type <str> ECPGCKeywords %type <str> ECPGCKeywords
%type <str> ECPGColId %type <str> ECPGColId
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
%type <str> c_term %type <str> c_term
%type <str> c_thing %type <str> c_thing
%type <str> char_variable %type <str> char_variable
%type <str> char_civar
%type <str> civar %type <str> civar
%type <str> civarind %type <str> civarind
%type <str> ColId %type <str> ColId
...@@ -75,6 +76,7 @@ ...@@ -75,6 +76,7 @@
%type <str> opt_bit_field %type <str> opt_bit_field
%type <str> opt_connection_name %type <str> opt_connection_name
%type <str> opt_database_name %type <str> opt_database_name
%type <str> opt_ecpg_into
%type <str> opt_ecpg_using %type <str> opt_ecpg_using
%type <str> opt_initializer %type <str> opt_initializer
%type <str> opt_options %type <str> opt_options
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.75 2009/09/08 04:25:00 tgl Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.76 2009/11/26 15:06:47 meskes Exp $ */
#ifndef _ECPG_PREPROC_EXTERN_H #ifndef _ECPG_PREPROC_EXTERN_H
#define _ECPG_PREPROC_EXTERN_H #define _ECPG_PREPROC_EXTERN_H
...@@ -90,6 +90,7 @@ extern struct descriptor *lookup_descriptor(char *, char *); ...@@ -90,6 +90,7 @@ extern struct descriptor *lookup_descriptor(char *, char *);
extern struct variable *descriptor_variable(const char *name, int input); extern struct variable *descriptor_variable(const char *name, int input);
extern void add_variable_to_head(struct arguments **, struct variable *, struct variable *); extern void add_variable_to_head(struct arguments **, struct variable *, struct variable *);
extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *); extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
extern void dump_variables(struct arguments *, int); extern void dump_variables(struct arguments *, int);
extern struct typedefs *get_typedef(char *); extern struct typedefs *get_typedef(char *);
extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool); extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool);
......
#!/usr/bin/perl #!/usr/bin/perl
# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/parse.pl,v 1.5 2009/11/21 05:44:05 tgl Exp $ # $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/parse.pl,v 1.6 2009/11/26 15:06:47 meskes Exp $
# parser generater for ecpg # parser generater for ecpg
# call with backend parser as stdin # call with backend parser as stdin
# #
...@@ -74,7 +74,8 @@ $replace_line{'reserved_keywordTO'} = 'ignore'; ...@@ -74,7 +74,8 @@ $replace_line{'reserved_keywordTO'} = 'ignore';
$replace_line{'reserved_keywordUNION'} = 'ignore'; $replace_line{'reserved_keywordUNION'} = 'ignore';
# some other production rules have to be ignored or replaced # some other production rules have to be ignored or replaced
$replace_line{'fetch_direction'} = 'ignore'; $replace_line{'fetch_argsFORWARDopt_from_incursor_name'} = 'ignore';
$replace_line{'fetch_argsBACKWARDopt_from_incursor_name'} = 'ignore';
$replace_line{"opt_array_boundsopt_array_bounds'['Iconst']'"} = 'ignore'; $replace_line{"opt_array_boundsopt_array_bounds'['Iconst']'"} = 'ignore';
$replace_line{'VariableShowStmtSHOWvar_name'} = 'SHOW var_name ecpg_into'; $replace_line{'VariableShowStmtSHOWvar_name'} = 'SHOW var_name ecpg_into';
$replace_line{'VariableShowStmtSHOWTIMEZONE'} = 'SHOW TIME ZONE ecpg_into'; $replace_line{'VariableShowStmtSHOWTIMEZONE'} = 'SHOW TIME ZONE ecpg_into';
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/variable.c,v 1.50 2009/08/07 10:51:20 meskes Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/variable.c,v 1.51 2009/11/26 15:06:47 meskes Exp $ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -401,6 +401,30 @@ add_variable_to_tail(struct arguments ** list, struct variable * var, struct var ...@@ -401,6 +401,30 @@ add_variable_to_tail(struct arguments ** list, struct variable * var, struct var
*list = new; *list = new;
} }
void
remove_variable_from_list(struct arguments ** list, struct variable * var)
{
struct arguments *p, *prev = NULL;
bool found = false;
for (p = *list; p; p = p->next)
{
if (p->variable == var)
{
found = true;
break;
}
prev = p;
}
if (found)
{
if (prev)
prev->next = p->next;
else
*list = p->next;
}
}
/* Dump out a list of all the variable on this list. /* Dump out a list of all the variable on this list.
This is a recursive function that works from the end of the list and This is a recursive function that works from the end of the list and
deletes the list as we go on. deletes the list as we go on.
......
...@@ -16,6 +16,7 @@ test: pgtypeslib/num_test2 ...@@ -16,6 +16,7 @@ test: pgtypeslib/num_test2
test: preproc/array_of_struct test: preproc/array_of_struct
test: preproc/autoprep test: preproc/autoprep
test: preproc/comment test: preproc/comment
test: preproc/cursor
test: preproc/define test: preproc/define
test: preproc/init test: preproc/init
test: preproc/strings test: preproc/strings
......
...@@ -16,6 +16,7 @@ test: pgtypeslib/num_test2 ...@@ -16,6 +16,7 @@ test: pgtypeslib/num_test2
test: preproc/array_of_struct test: preproc/array_of_struct
test: preproc/autoprep test: preproc/autoprep
test: preproc/comment test: preproc/comment
test: preproc/cursor
test: preproc/define test: preproc/define
test: preproc/init test: preproc/init
test: preproc/strings test: preproc/strings
......
...@@ -7,6 +7,7 @@ include $(top_srcdir)/$(subdir)/../Makefile.regress ...@@ -7,6 +7,7 @@ include $(top_srcdir)/$(subdir)/../Makefile.regress
TESTS = array_of_struct array_of_struct.c \ TESTS = array_of_struct array_of_struct.c \
autoprep autoprep.c \ autoprep autoprep.c \
comment comment.c \ comment comment.c \
cursor cursor.c \
define define.c \ define define.c \
init init.c \ init init.c \
strings strings.c \ strings strings.c \
......
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