aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/ecpg/ChangeLog4
-rw-r--r--src/interfaces/ecpg/ecpglib/descriptor.c4
-rw-r--r--src/interfaces/ecpg/ecpglib/execute.c174
-rw-r--r--src/interfaces/ecpg/ecpglib/extern.h4
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l3
-rw-r--r--src/interfaces/ecpg/preproc/preproc.y81
-rw-r--r--src/interfaces/ecpg/test/expected/sql-fetch.c8
-rw-r--r--src/interfaces/ecpg/test/sql/fetch.pgc4
8 files changed, 126 insertions, 156 deletions
diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index 59e22774d75..871630923c1 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -2293,6 +2293,10 @@ Mon, 14 Jan 2008 10:42:23 +0100
- Set valid return values even in case of an error to prevent
segfaults.
+
+Tue, 15 Jan 2008 11:26:14 +0100
+
+ - Re-enabled variables in fetch/move command.
- Set pgtypes library version to 3.0.
- Set compat library version to 3.0.
- Set ecpg library version to 6.0.
diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c
index 0e76e244b16..df9ea295344 100644
--- a/src/interfaces/ecpg/ecpglib/descriptor.c
+++ b/src/interfaces/ecpg/ecpglib/descriptor.c
@@ -1,6 +1,6 @@
/* dynamic SQL support routines
*
- * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.28 2007/11/15 21:14:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.29 2008/01/15 10:31:47 meskes Exp $
*/
#define POSTGRES_ECPG_INTERNAL
@@ -529,7 +529,7 @@ ECPGset_desc(int lineno, const char *desc_name, int index,...)
for (;;)
{
enum ECPGdtype itemtype;
- const char *tobeinserted = NULL;
+ char *tobeinserted = NULL;
itemtype = va_arg(args, enum ECPGdtype);
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 1b1f47217b2..2ccdcbb68fb 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.74 2008/01/13 11:53:16 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.75 2008/01/15 10:31:47 meskes Exp $ */
/*
* The aim is to get a simpler inteface to the database routines.
@@ -128,8 +128,8 @@ next_insert(char *text, int pos, bool questionmarks)
int i;
for (i = p + 1; isdigit(text[i]); i++);
- if (!isalpha(text[i]) &&isascii(text[i]) &&text[i] != '_')
- /* not dollar delimeted quote */
+ if (!isalpha(text[i]) && isascii(text[i]) && text[i] != '_')
+ /* not dollar delimited quote */
return p;
}
else if (questionmarks && text[p] == '?')
@@ -451,7 +451,7 @@ ecpg_store_result(const PGresult *results, int act_field,
bool
ecpg_store_input(const int lineno, const bool force_indicator, const struct variable * var,
- const char **tobeinserted_p, bool quote)
+ char **tobeinserted_p, bool quote)
{
char *mallocedval = NULL;
char *newcopy = NULL;
@@ -1046,6 +1046,39 @@ free_params(const char **paramValues, int nParams, bool print, int lineno)
ecpg_free(paramValues);
}
+
+static bool
+insert_tobeinserted(int position, int ph_len, struct statement * stmt, char *tobeinserted)
+{
+ char *newcopy;
+
+ if (!(newcopy = (char *) ecpg_alloc(strlen(stmt->command)
+ + strlen(tobeinserted)
+ + 1, stmt->lineno)))
+ {
+ ecpg_free(tobeinserted);
+ return false;
+ }
+
+ strcpy(newcopy, stmt->command);
+ strcpy(newcopy + position - 1, tobeinserted);
+
+ /*
+ * The strange thing in the second argument is the rest of the
+ * string from the old string
+ */
+ strcat(newcopy,
+ stmt->command
+ + position
+ + ph_len - 1);
+
+ ecpg_free(stmt->command);
+ stmt->command = newcopy;
+
+ ecpg_free((char *) tobeinserted);
+ return true;
+}
+
static bool
ecpg_execute(struct statement * stmt)
{
@@ -1069,7 +1102,7 @@ ecpg_execute(struct statement * stmt)
var = stmt->inlist;
while (var)
{
- const char *tobeinserted;
+ char *tobeinserted;
int counter = 1;
tobeinserted = NULL;
@@ -1134,11 +1167,51 @@ ecpg_execute(struct statement * stmt)
/*
* now tobeinserted points to an area that contains the next parameter
+ * now find the positin in the string where it belongs
+ */
+ if ((position = next_insert(stmt->command, position, stmt->questionmarks) + 1) == 0)
+ {
+ /*
+ * We have an argument but we dont have the matched up
+ * placeholder in the string
+ */
+ ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
+ ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
+ NULL);
+ free_params(paramValues, nParams, false, stmt->lineno);
+ return false;
+ }
+
+ /*
* if var->type=ECPGt_char_variable we have a dynamic cursor we have
* to simulate a dynamic cursor because there is no backend
* functionality for it
*/
- if (var->type != ECPGt_char_variable)
+ if (var->type == ECPGt_char_variable)
+ {
+ int ph_len = (stmt->command[position] == '?') ? strlen("?") : strlen("$1");
+
+ if (!insert_tobeinserted(position, ph_len, stmt, tobeinserted))
+ {
+ free_params(paramValues, nParams, false, stmt->lineno);
+ return false;
+ }
+ tobeinserted = NULL;
+ }
+ /*
+ * if the placeholder is '$0' we have to replace it on the client side
+ * this is for places we want to support variables at that are not supported in the backend
+ */
+ else if (stmt->command[position] == '0' )
+ {
+ if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
+ {
+ free_params(paramValues, nParams, false, stmt->lineno);
+ return false;
+ }
+ tobeinserted = NULL;
+ }
+ else
{
nParams++;
if (!(paramValues = (const char **) ecpg_realloc(paramValues, sizeof(const char *) * nParams, stmt->lineno)))
@@ -1149,107 +1222,28 @@ ecpg_execute(struct statement * stmt)
paramValues[nParams - 1] = tobeinserted;
- if ((position = next_insert(stmt->command, position, stmt->questionmarks) + 1) == 0)
- {
- /*
- * We have an argument but we dont have the matched up
- * placeholder in the string
- */
- ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
- ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
- NULL);
- free_params(paramValues, nParams, false, stmt->lineno);
- return false;
- }
-
/* let's see if this was an old style placeholder */
- if (stmt->command[position - 1] == '?')
+ if (stmt->command[position] == '?')
{
/* yes, replace with new style */
int buffersize = sizeof(int) * CHAR_BIT * 10 / 3; /* a rough guess of the
* size we need */
- char *buffer,
- *newcopy;
- if (!(buffer = (char *) ecpg_alloc(buffersize, stmt->lineno)))
+ if (!(tobeinserted = (char *) ecpg_alloc(buffersize, stmt->lineno)))
{
free_params(paramValues, nParams, false, stmt->lineno);
return false;
}
- snprintf(buffer, buffersize, "$%d", counter++);
+ snprintf(tobeinserted, buffersize, "$%d", counter++);
- if (!(newcopy = (char *) ecpg_alloc(strlen(stmt->command) + strlen(buffer) + 1, stmt->lineno)))
+ if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
{
free_params(paramValues, nParams, false, stmt->lineno);
- ecpg_free(buffer);
return false;
}
-
- strcpy(newcopy, stmt->command);
-
- /* set positional parameter */
- strcpy(newcopy + position - 1, buffer);
-
- /*
- * The strange thing in the second argument is the rest of the
- * string from the old string
- */
- strcat(newcopy,
- stmt->command
- + position + 1);
- ecpg_free(buffer);
- ecpg_free(stmt->command);
- stmt->command = newcopy;
- }
- }
- else
- {
- char *newcopy;
-
- if (!(newcopy = (char *) ecpg_alloc(strlen(stmt->command)
- + strlen(tobeinserted)
- + 1, stmt->lineno)))
- {
- free_params(paramValues, nParams, false, stmt->lineno);
- return false;
- }
-
- strcpy(newcopy, stmt->command);
- if ((position = next_insert(stmt->command, position, stmt->questionmarks) + 1) == 0)
- {
- /*
- * We have an argument but we dont have the matched up string
- * in the string
- */
- ecpg_raise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
- ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
- NULL);
- free_params(paramValues, nParams, false, stmt->lineno);
- ecpg_free(newcopy);
- return false;
+ tobeinserted = NULL;
}
- else
- {
- int ph_len = (stmt->command[position] == '?') ? strlen("?") : strlen("$1");
-
- strcpy(newcopy + position - 1, tobeinserted);
-
- /*
- * The strange thing in the second argument is the rest of the
- * string from the old string
- */
- strcat(newcopy,
- stmt->command
- + position
- + ph_len - 1);
- }
-
- ecpg_free(stmt->command);
- stmt->command = newcopy;
-
- ecpg_free((char *) tobeinserted);
- tobeinserted = NULL;
}
if (desc_counter == 0)
diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h
index e366c9ce448..975904eb774 100644
--- a/src/interfaces/ecpg/ecpglib/extern.h
+++ b/src/interfaces/ecpg/ecpglib/extern.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.32 2007/11/15 21:14:45 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.33 2008/01/15 10:31:47 meskes Exp $ */
#ifndef _ECPG_LIB_EXTERN_H
#define _ECPG_LIB_EXTERN_H
@@ -138,7 +138,7 @@ struct descriptor *ecpg_find_desc(int line, const char *name);
bool ecpg_store_result(const PGresult *results, int act_field,
const struct statement * stmt, struct variable * var);
-bool ecpg_store_input(const int, const bool, const struct variable *, const char **, bool);
+bool ecpg_store_input(const int, const bool, const struct variable *, char **, bool);
bool ecpg_check_PQresult(PGresult *, int, PGconn *, enum COMPAT_MODE);
void ecpg_raise(int line, int code, const char *sqlstate, const char *str);
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 1bdfc7e0fa9..e5bd28be920 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.158 2008/01/11 15:19:16 meskes Exp $
+ * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.159 2008/01/15 10:31:47 meskes Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,7 +28,6 @@ extern YYSTYPE yylval;
static int xcdepth = 0; /* depth of nesting in slash-star comments */
static char *dolqstart; /* current $foo$ quote start string */
-static bool escape_string_warning;
static YY_BUFFER_STATE scanbufhandle;
static char *scanbuf;
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index 563a891bc66..9bcf9944803 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.358 2008/01/14 09:43:42 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.359 2008/01/15 10:31:47 meskes Exp $ */
/* Copyright comment */
%{
@@ -566,7 +566,7 @@ add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enu
%type <str> join_outer where_clause relation_expr sub_type arg_class
%type <str> opt_column_list insert_rest InsertStmt param_name
%type <str> columnList DeleteStmt UpdateStmt DeclareCursorStmt
-%type <str> NotifyStmt columnElem UnlistenStmt TableElement
+%type <str> NotifyStmt columnElem UnlistenStmt TableElement fetch_count
%type <str> copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
%type <str> FetchStmt from_in CreateOpClassStmt returning_clause
%type <str> ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose
@@ -2337,61 +2337,32 @@ FetchStmt: FETCH fetch_direction from_in name ecpg_into
{ $$ = cat2_str(make_str("move"), $2); }
;
-fetch_direction: NEXT { $$ = make_str("next"); }
- | PRIOR { $$ = make_str("prior"); }
- | FIRST_P { $$ = make_str("first"); }
- | LAST_P { $$ = make_str("last"); }
- | ABSOLUTE_P IntConst {
- if ($2[1] == '$')
- {
- mmerror(PARSE_ERROR, ET_ERROR, "fetch/move count must not be a variable, ignoring it.\n");
- $$ = make_str("absolute");
- }
- else
- $$ = cat2_str(make_str("absolute"), $2);
- }
- | RELATIVE_P IntConst {
- if ($2[1] == '$')
- {
- mmerror(PARSE_ERROR, ET_ERROR, "fetch/move count must not be a variable, ignoring it.\n");
- $$ = make_str("relative");
- }
- else
- $$ = cat2_str(make_str("relative"), $2);
+fetch_direction: NEXT { $$ = make_str("next"); }
+ | PRIOR { $$ = make_str("prior"); }
+ | FIRST_P { $$ = make_str("first"); }
+ | LAST_P { $$ = make_str("last"); }
+ | ABSOLUTE_P fetch_count { $$ = cat2_str(make_str("absolute"), $2); }
+ | RELATIVE_P fetch_count { $$ = cat2_str(make_str("relative"), $2); }
+ | fetch_count { $$ = $1; }
+ | ALL { $$ = make_str("all"); }
+ | FORWARD { $$ = make_str("forward"); }
+ | FORWARD fetch_count { $$ = cat2_str(make_str("forward"), $2); }
+ | FORWARD ALL { $$ = make_str("forward all"); }
+ | BACKWARD { $$ = make_str("backward"); }
+ | BACKWARD fetch_count { $$ = cat2_str(make_str("backward"), $2); }
+ | BACKWARD ALL { $$ = make_str("backward all"); }
+ ;
+
+fetch_count: IntConst {
+ if ($1[1] == '$')
+ {
+ /* a variable here has to be replaced on the client side, thus we have to use '?' here */
+ $$ = make_str("$0");
+ free($1);
}
- | IntConst {
- if ($1[1] == '$')
- {
- mmerror(PARSE_ERROR, ET_ERROR, "fetch/move count must not be a variablei, ignoring it.\n");
- $$ = EMPTY;
- }
- else
+ else
$$ = $1;
- }
- | ALL { $$ = make_str("all"); }
- | FORWARD { $$ = make_str("forward"); }
- | FORWARD IntConst {
- if ($2[1] == '$')
- {
- mmerror(PARSE_ERROR, ET_ERROR, "fetch/move count must not be a variable, ignoring it.\n");
- $$ = make_str("forward");
- }
- else
- $$ = cat2_str(make_str("forward"), $2);
- }
- | FORWARD ALL { $$ = make_str("forward all"); }
- | BACKWARD { $$ = make_str("backward"); }
- | BACKWARD IntConst {
- if ($2[1] == '$')
- {
- mmerror(PARSE_ERROR, ET_ERROR, "fetch/move count must not be a variable, ignoring it.\n");
- $$ = make_str("backward");
- }
- else
- $$ = cat2_str(make_str("backward"), $2);
- }
- | BACKWARD ALL { $$ = make_str("backward all"); }
- ;
+ }
from_in: IN_P { $$ = make_str("in"); }
| FROM { $$ = make_str("from"); }
diff --git a/src/interfaces/ecpg/test/expected/sql-fetch.c b/src/interfaces/ecpg/test/expected/sql-fetch.c
index dd04d6f14fa..54d69e47abc 100644
--- a/src/interfaces/ecpg/test/expected/sql-fetch.c
+++ b/src/interfaces/ecpg/test/expected/sql-fetch.c
@@ -26,13 +26,13 @@
int main(int argc, char* argv[]) {
/* exec sql begin declare section */
-
+
#line 9 "fetch.pgc"
char str [ 25 ] ;
#line 10 "fetch.pgc"
- int i ;
+ int i , count = 1 ;
/* exec sql end declare section */
#line 11 "fetch.pgc"
@@ -146,7 +146,9 @@ if (sqlca.sqlcode < 0) sqlprint();}
#line 37 "fetch.pgc"
- { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 in C", ECPGt_EOIT,
+ { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 in C",
+ ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+ ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(i),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(str),(long)25,(long)1,(25)*sizeof(char),
diff --git a/src/interfaces/ecpg/test/sql/fetch.pgc b/src/interfaces/ecpg/test/sql/fetch.pgc
index a65d393748e..340b888048e 100644
--- a/src/interfaces/ecpg/test/sql/fetch.pgc
+++ b/src/interfaces/ecpg/test/sql/fetch.pgc
@@ -7,7 +7,7 @@ EXEC SQL INCLUDE ../regression;
int main(int argc, char* argv[]) {
EXEC SQL BEGIN DECLARE SECTION;
char str[25];
- int i;
+ int i, count=1;
EXEC SQL END DECLARE SECTION;
ECPGdebug(1, stderr);
@@ -36,7 +36,7 @@ int main(int argc, char* argv[]) {
EXEC SQL WHENEVER NOT FOUND CONTINUE;
EXEC SQL MOVE BACKWARD 2 IN C;
- EXEC SQL FETCH 1 IN C INTO :i, :str;
+ EXEC SQL FETCH :count IN C INTO :i, :str;
printf("%d: %s\n", i, str);
EXEC SQL CLOSE C;