Re-enabled variables in fetch/move command.
This commit is contained in:
parent
abab776b3c
commit
dbdc2e52a0
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,108 +1222,29 @@ 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;
|
||||
tobeinserted = NULL;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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)
|
||||
var = var->next;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,62 +2337,33 @@ 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);
|
||||
}
|
||||
| IntConst {
|
||||
if ($1[1] == '$')
|
||||
{
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "fetch/move count must not be a variablei, ignoring it.\n");
|
||||
$$ = EMPTY;
|
||||
}
|
||||
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"); }
|
||||
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);
|
||||
}
|
||||
else
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
from_in: IN_P { $$ = make_str("in"); }
|
||||
| FROM { $$ = make_str("from"); }
|
||||
;
|
||||
|
@ -32,7 +32,7 @@ int main(int argc, char* argv[]) {
|
||||
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),
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user