mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-31 20:20:44 +08:00
Added files containing changes between gram.y and preproc.y.
This commit is contained in:
parent
4607c5ca56
commit
e339ed5f50
382
src/interfaces/ecpg/preproc/ecpg.addons
Normal file
382
src/interfaces/ecpg/preproc/ecpg.addons
Normal file
@ -0,0 +1,382 @@
|
||||
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
|
||||
|
||||
ECPG: stmtClosePortalStmt block
|
||||
{
|
||||
if (INFORMIX_MODE)
|
||||
{
|
||||
if (pg_strcasecmp($1+strlen("close "), "database") == 0)
|
||||
{
|
||||
if (connection)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no at option for close database statement\n");
|
||||
|
||||
fprintf(yyout, "{ ECPGdisconnect(__LINE__, \"CURRENT\");");
|
||||
whenever_action(2);
|
||||
free($1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
output_statement($1, 0, ECPGst_normal);
|
||||
}
|
||||
ECPG: stmtDeallocateStmt block
|
||||
{
|
||||
if (connection)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement\n");
|
||||
|
||||
output_deallocate_prepare_statement($1);
|
||||
}
|
||||
ECPG: stmtDeclareCursorStmt block
|
||||
{ output_simple_statement($1); }
|
||||
ECPG: stmtDeleteStmt block
|
||||
ECPG: stmtDiscardStmt block
|
||||
ECPG: stmtFetchStmt block
|
||||
ECPG: stmtInsertStmt block
|
||||
ECPG: stmtSelectStmt block
|
||||
ECPG: stmtUpdateStmt block
|
||||
{ output_statement($1, 1, ECPGst_normal); }
|
||||
ECPG: stmtExecuteStmt block
|
||||
{ output_statement($1, 1, ECPGst_execute); }
|
||||
ECPG: stmtPrepareStmt block
|
||||
{
|
||||
if ($1.type == NULL || strlen($1.type) == 0)
|
||||
output_prepare_statement($1.name, $1.stmt);
|
||||
else
|
||||
output_statement(cat_str(5, make_str("prepare"), $1.name, $1.type, make_str("as"), $1.stmt), 0, ECPGst_normal);
|
||||
}
|
||||
ECPG: stmtTransactionStmt block
|
||||
{
|
||||
fprintf(yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
|
||||
whenever_action(2);
|
||||
free($1);
|
||||
}
|
||||
ECPG: stmtViewStmt rule
|
||||
| ECPGAllocateDescr
|
||||
{
|
||||
fprintf(yyout,"ECPGallocate_desc(__LINE__, %s);",$1);
|
||||
whenever_action(0);
|
||||
free($1);
|
||||
}
|
||||
| ECPGConnect
|
||||
{
|
||||
if (connection)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement\n");
|
||||
|
||||
fprintf(yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit);
|
||||
reset_variables();
|
||||
whenever_action(2);
|
||||
free($1);
|
||||
}
|
||||
| ECPGCursorStmt
|
||||
{
|
||||
output_simple_statement($1);
|
||||
}
|
||||
| ECPGDeallocateDescr
|
||||
{
|
||||
if (connection)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement\n");
|
||||
fprintf(yyout,"ECPGdeallocate_desc(__LINE__, %s);",$1);
|
||||
whenever_action(0);
|
||||
free($1);
|
||||
}
|
||||
| ECPGDeclare
|
||||
{
|
||||
output_simple_statement($1);
|
||||
}
|
||||
| ECPGDescribe
|
||||
{
|
||||
fprintf(yyout, "{ ECPGdescribe(__LINE__, %s,", $1);
|
||||
dump_variables(argsresult, 1);
|
||||
fputs("ECPGt_EORT);", yyout);
|
||||
fprintf(yyout, "}");
|
||||
output_line_number();
|
||||
|
||||
free($1);
|
||||
}
|
||||
| ECPGDisconnect
|
||||
{
|
||||
if (connection)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no at option for disconnect statement\n");
|
||||
|
||||
fprintf(yyout, "{ ECPGdisconnect(__LINE__, %s);",
|
||||
$1 ? $1 : "\"CURRENT\"");
|
||||
whenever_action(2);
|
||||
free($1);
|
||||
}
|
||||
| ECPGExecuteImmediateStmt { output_statement($1, 0, ECPGst_exec_immediate); }
|
||||
| ECPGFree
|
||||
{
|
||||
const char *con = connection ? connection : "NULL";
|
||||
if (strcmp($1, "all"))
|
||||
fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, %s, \"%s\");", compat, con, $1);
|
||||
else
|
||||
fprintf(yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con);
|
||||
|
||||
whenever_action(2);
|
||||
free($1);
|
||||
}
|
||||
| ECPGGetDescriptor
|
||||
{
|
||||
lookup_descriptor($1.name, connection);
|
||||
output_get_descr($1.name, $1.str);
|
||||
free($1.name);
|
||||
free($1.str);
|
||||
}
|
||||
| ECPGGetDescriptorHeader
|
||||
{
|
||||
lookup_descriptor($1, connection);
|
||||
output_get_descr_header($1);
|
||||
free($1);
|
||||
}
|
||||
| ECPGOpen
|
||||
{
|
||||
struct cursor *ptr;
|
||||
|
||||
if ((ptr = add_additional_variables($1, true)) != NULL)
|
||||
{
|
||||
connection = ptr->connection ? mm_strdup(ptr->connection) : NULL;
|
||||
output_statement(mm_strdup(ptr->command), 0, 0);
|
||||
ptr->opened = true;
|
||||
}
|
||||
}
|
||||
| ECPGSetAutocommit
|
||||
{
|
||||
fprintf(yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL");
|
||||
whenever_action(2);
|
||||
free($1);
|
||||
}
|
||||
| ECPGSetConnection
|
||||
{
|
||||
if (connection)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement\n");
|
||||
|
||||
fprintf(yyout, "{ ECPGsetconn(__LINE__, %s);", $1);
|
||||
whenever_action(2);
|
||||
free($1);
|
||||
}
|
||||
| ECPGSetDescriptor
|
||||
{
|
||||
lookup_descriptor($1.name, connection);
|
||||
output_set_descr($1.name, $1.str);
|
||||
free($1.name);
|
||||
free($1.str);
|
||||
}
|
||||
| ECPGSetDescriptorHeader
|
||||
{
|
||||
lookup_descriptor($1, connection);
|
||||
output_set_descr_header($1);
|
||||
free($1);
|
||||
}
|
||||
| ECPGTypedef
|
||||
{
|
||||
if (connection)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no at option for typedef statement\n");
|
||||
|
||||
fprintf(yyout, "%s", $1);
|
||||
free($1);
|
||||
output_line_number();
|
||||
}
|
||||
| ECPGVar
|
||||
{
|
||||
if (connection)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no at option for var statement\n");
|
||||
|
||||
output_simple_statement($1);
|
||||
}
|
||||
| ECPGWhenever
|
||||
{
|
||||
if (connection)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no at option for whenever statement\n");
|
||||
|
||||
output_simple_statement($1);
|
||||
}
|
||||
ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listopt_oidscopy_fromcopy_file_namecopy_delimiteropt_withcopy_opt_list addon
|
||||
if (strcmp($6, "to") == 0 && strcmp($7, "stdin") == 0)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "copy to stdin not possible\n");
|
||||
else if (strcmp($6, "from") == 0 && strcmp($7, "stdout") == 0)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "copy from stdout not possible\n");
|
||||
else if (strcmp($6, "from") == 0 && strcmp($7, "stdin") == 0)
|
||||
mmerror(PARSE_ERROR, ET_WARNING, "copy from stdin not implemented\n");
|
||||
ECPG: CopyStmtCOPYselect_with_parensTOcopy_file_nameopt_withcopy_opt_list addon
|
||||
if (strcmp($4, "stdin") == 0)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "copy to stdin not possible\n");
|
||||
ECPG: ConstraintAttributeSpecConstraintDeferrabilitySpecConstraintTimeSpec addon
|
||||
if (strcmp($1, "deferrable") != 0 && strcmp($2, "initially deferrable") == 0 )
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE\n");
|
||||
ECPG: ConstraintAttributeSpecConstraintTimeSpecConstraintDeferrabilitySpec addon
|
||||
if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE\n");
|
||||
ECPG: var_valueNumericOnly addon
|
||||
ECPG: fetch_directionSignedIconst addon
|
||||
if ($1[1] == '$')
|
||||
{
|
||||
free($1);
|
||||
$1 = make_str("$0");
|
||||
}
|
||||
ECPG: fetch_directionABSOLUTE_PSignedIconst addon
|
||||
ECPG: fetch_directionRELATIVE_PSignedIconst addon
|
||||
ECPG: fetch_directionFORWARDSignedIconst addon
|
||||
ECPG: fetch_directionBACKWARDSignedIconst addon
|
||||
if ($2[1] == '$')
|
||||
{
|
||||
free($2);
|
||||
$2 = make_str("$0");
|
||||
}
|
||||
ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
|
||||
{
|
||||
$$.name = $2;
|
||||
$$.type = $3;
|
||||
$$.stmt = cat_str(3, make_str("\""), $5, make_str("\""));
|
||||
}
|
||||
| PREPARE prepared_name FROM execstring
|
||||
{
|
||||
$$.name = $2;
|
||||
$$.type = NULL;
|
||||
$$.stmt = $4;
|
||||
}
|
||||
ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
|
||||
{ $$ = $2; }
|
||||
ECPG: DeclareCursorStmtDECLAREnamecursor_optionsCURSORopt_holdFORSelectStmt block
|
||||
{
|
||||
struct cursor *ptr, *this;
|
||||
|
||||
for (ptr = cur; ptr != NULL; ptr = ptr->next)
|
||||
{
|
||||
if (strcmp($2, ptr->name) == 0)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" already defined\n", $2);
|
||||
}
|
||||
|
||||
this = (struct cursor *) mm_alloc(sizeof(struct cursor));
|
||||
|
||||
this->next = cur;
|
||||
this->name = $2;
|
||||
this->connection = connection;
|
||||
this->opened = false;
|
||||
this->command = cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"), $7);
|
||||
this->argsinsert = argsinsert;
|
||||
this->argsresult = argsresult;
|
||||
argsinsert = argsresult = NULL;
|
||||
cur = this;
|
||||
|
||||
if (INFORMIX_MODE)
|
||||
$$ = cat_str(5, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), make_str("/*"), mm_strdup(this->command), make_str("*/"));
|
||||
else
|
||||
$$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
|
||||
}
|
||||
ECPG: opt_hold block
|
||||
{
|
||||
if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true)
|
||||
$$ = make_str("with hold");
|
||||
else
|
||||
$$ = EMPTY;
|
||||
}
|
||||
ECPG: into_clauseINTOOptTempTableName block
|
||||
{
|
||||
FoundInto = 1;
|
||||
$$= cat2_str(make_str("into"), $2);
|
||||
}
|
||||
| ecpg_into { $$ = EMPTY; }
|
||||
ECPG: table_refselect_with_parens addon
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "sub-SELECT in FROM must have an alias\n");
|
||||
ECPG: TypenameSimpleTypenameopt_array_bounds block
|
||||
{ $$ = cat2_str($1, $2.str); }
|
||||
ECPG: TypenameSETOFSimpleTypenameopt_array_bounds block
|
||||
{ $$ = $$ = cat_str(3, make_str("setof"), $2, $3.str); }
|
||||
ECPG: opt_array_boundsopt_array_bounds'['']' block
|
||||
{
|
||||
$$.index1 = $1.index1;
|
||||
$$.index2 = $1.index2;
|
||||
if (strcmp($$.index1, "-1") == 0)
|
||||
$$.index1 = make_str("0");
|
||||
else if (strcmp($1.index2, "-1") == 0)
|
||||
$$.index2 = make_str("0");
|
||||
$$.str = cat_str(2, $1.str, make_str("[]"));
|
||||
}
|
||||
| opt_array_bounds '[' Iresult ']'
|
||||
{
|
||||
$$.index1 = $1.index1;
|
||||
$$.index2 = $1.index2;
|
||||
if (strcmp($1.index1, "-1") == 0)
|
||||
$$.index1 = strdup($3);
|
||||
else if (strcmp($1.index2, "-1") == 0)
|
||||
$$.index2 = strdup($3);
|
||||
$$.str = cat_str(4, $1.str, make_str("["), $3, make_str("]"));
|
||||
}
|
||||
ECPG: opt_array_bounds
|
||||
{
|
||||
$$.index1 = make_str("-1");
|
||||
$$.index2 = make_str("-1");
|
||||
$$.str= EMPTY;
|
||||
}
|
||||
ECPG: IconstICONST block
|
||||
{ $$ = make_name(); }
|
||||
ECPG: AexprConstNULL_P rule
|
||||
| civar { $$ = $1; }
|
||||
| civarind { $$ = $1; }
|
||||
ECPG: ColIdcol_name_keyword rule
|
||||
| ECPGKeywords { $$ = $1; }
|
||||
| ECPGCKeywords { $$ = $1; }
|
||||
| CHAR_P { $$ = make_str("char"); }
|
||||
| VALUES { $$ = make_str("values"); }
|
||||
ECPG: type_function_nametype_func_name_keyword rule
|
||||
| ECPGKeywords { $$ = $1; }
|
||||
| ECPGTypeName { $$ = $1; }
|
||||
| ECPGCKeywords { $$ = $1; }
|
||||
ECPG: VariableShowStmtSHOWALL block
|
||||
{
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL not implemented\n");
|
||||
$$ = EMPTY;
|
||||
}
|
||||
ECPG: FetchStmtFETCHfetch_directionfrom_inname block
|
||||
{
|
||||
add_additional_variables($4, false);
|
||||
$$ = cat_str(4, make_str("fetch"), $2, $3, $4);
|
||||
}
|
||||
ECPG: FetchStmtFETCHname block
|
||||
{
|
||||
add_additional_variables($2, false);
|
||||
$$ = cat_str(2, make_str("fetch"), $2);
|
||||
}
|
||||
ECPG: FetchStmtMOVEname rule
|
||||
| FETCH fetch_direction from_in name ecpg_into
|
||||
{
|
||||
add_additional_variables($4, false);
|
||||
$$ = cat_str(4, make_str("fetch"), $2, $3, $4);
|
||||
}
|
||||
| FETCH fetch_direction name ecpg_into
|
||||
{
|
||||
add_additional_variables($3, false);
|
||||
$$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
|
||||
}
|
||||
| FETCH from_in name ecpg_into
|
||||
{
|
||||
add_additional_variables($3, false);
|
||||
$$ = cat_str(3, make_str("fetch"), $2, $3);
|
||||
}
|
||||
| FETCH name ecpg_into
|
||||
{
|
||||
add_additional_variables($2, false);
|
||||
$$ = cat2_str(make_str("fetch"), $2);
|
||||
}
|
||||
| FETCH fetch_direction name
|
||||
{
|
||||
add_additional_variables($3, false);
|
||||
$$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
|
||||
}
|
||||
| FETCH from_in name
|
||||
{
|
||||
add_additional_variables($3, false);
|
||||
$$ = cat_str(3, make_str("fetch"), $2, $3);
|
||||
}
|
||||
ECPG: SpecialRuleRelationOLD addon
|
||||
if (!QueryIsRule)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "OLD used in non-rule query\n");
|
||||
ECPG: SpecialRuleRelationNEW addon
|
||||
if (!QueryIsRule)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "NEW used in non-rule query\n");
|
||||
ECPG: select_limitLIMITselect_limit_value','select_offset_value block
|
||||
{
|
||||
mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to backend");
|
||||
$$ = cat_str(4, make_str("limit"), $2, make_str(","), $4);
|
||||
}
|
||||
ECPG: SignedIconstIconst rule
|
||||
| civar { $$ = $1; }
|
390
src/interfaces/ecpg/preproc/ecpg.header
Normal file
390
src/interfaces/ecpg/preproc/ecpg.header
Normal file
@ -0,0 +1,390 @@
|
||||
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.header,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
|
||||
|
||||
/* Copyright comment */
|
||||
%{
|
||||
#include "postgres_fe.h"
|
||||
|
||||
#include "extern.h"
|
||||
#include <unistd.h>
|
||||
|
||||
/* Location tracking support --- simpler than bison's default */
|
||||
#define YYLLOC_DEFAULT(Current, Rhs, N) \
|
||||
do { \
|
||||
if (N) \
|
||||
(Current) = (Rhs)[1]; \
|
||||
else \
|
||||
(Current) = (Rhs)[0]; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* The %name-prefix option below will make bison call base_yylex, but we
|
||||
* really want it to call filtered_base_yylex (see parser.c).
|
||||
*/
|
||||
#define base_yylex filtered_base_yylex
|
||||
|
||||
/*
|
||||
* Variables containing simple states.
|
||||
*/
|
||||
int struct_level = 0;
|
||||
int braces_open; /* brace level counter */
|
||||
int ecpg_informix_var = 0;
|
||||
char *connection = NULL;
|
||||
char *input_filename = NULL;
|
||||
|
||||
static int QueryIsRule = 0, FoundInto = 0;
|
||||
static int initializer = 0;
|
||||
static int pacounter = 1;
|
||||
static char pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess at the size we need */
|
||||
static struct this_type actual_type[STRUCT_DEPTH];
|
||||
static char *actual_startline[STRUCT_DEPTH];
|
||||
|
||||
/* temporarily store struct members while creating the data structure */
|
||||
struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
|
||||
|
||||
/* also store struct type so we can do a sizeof() later */
|
||||
static char *ECPGstruct_sizeof = NULL;
|
||||
|
||||
/* for forward declarations we have to store some data as well */
|
||||
static char *forward_name = NULL;
|
||||
|
||||
struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, NULL, NULL, {NULL}, 0};
|
||||
struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
|
||||
|
||||
struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, {NULL}, 0};
|
||||
|
||||
/*
|
||||
* Handle parsing errors and warnings
|
||||
*/
|
||||
void
|
||||
mmerror(int error_code, enum errortype type, char * error, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
/* internationalize the error message string */
|
||||
error = _(error);
|
||||
|
||||
fprintf(stderr, "%s:%d: ", input_filename, yylineno);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ET_WARNING:
|
||||
fprintf(stderr, _("WARNING: "));
|
||||
break;
|
||||
case ET_ERROR:
|
||||
case ET_FATAL:
|
||||
fprintf(stderr, _("ERROR: "));
|
||||
break;
|
||||
}
|
||||
|
||||
va_start(ap, error);
|
||||
vfprintf(stderr, error, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ET_WARNING:
|
||||
break;
|
||||
case ET_ERROR:
|
||||
ret_value = error_code;
|
||||
break;
|
||||
case ET_FATAL:
|
||||
if (yyin)
|
||||
fclose(yyin);
|
||||
if (yyout)
|
||||
fclose(yyout);
|
||||
if (unlink(output_filename) != 0 && *output_filename != '-')
|
||||
fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
|
||||
exit(error_code);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* string concatenation
|
||||
*/
|
||||
|
||||
static char *
|
||||
cat2_str(char *str1, char *str2)
|
||||
{
|
||||
char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2);
|
||||
|
||||
strcpy(res_str, str1);
|
||||
strcat(res_str, " ");
|
||||
strcat(res_str, str2);
|
||||
free(str1);
|
||||
free(str2);
|
||||
return(res_str);
|
||||
}
|
||||
|
||||
static char *
|
||||
cat_str(int count, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
char *res_str;
|
||||
|
||||
va_start(args, count);
|
||||
|
||||
res_str = va_arg(args, char *);
|
||||
|
||||
/* now add all other strings */
|
||||
for (i = 1; i < count; i++)
|
||||
res_str = cat2_str(res_str, va_arg(args, char *));
|
||||
|
||||
va_end(args);
|
||||
|
||||
return(res_str);
|
||||
}
|
||||
|
||||
char *
|
||||
make_str(const char *str)
|
||||
{
|
||||
char * res_str = (char *)mm_alloc(strlen(str) + 1);
|
||||
|
||||
strcpy(res_str, str);
|
||||
return res_str;
|
||||
}
|
||||
|
||||
static char *
|
||||
make2_str(char *str1, char *str2)
|
||||
{
|
||||
char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
|
||||
|
||||
strcpy(res_str, str1);
|
||||
strcat(res_str, str2);
|
||||
free(str1);
|
||||
free(str2);
|
||||
return(res_str);
|
||||
}
|
||||
|
||||
static char *
|
||||
make3_str(char *str1, char *str2, char *str3)
|
||||
{
|
||||
char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1);
|
||||
|
||||
strcpy(res_str, str1);
|
||||
strcat(res_str, str2);
|
||||
strcat(res_str, str3);
|
||||
free(str1);
|
||||
free(str2);
|
||||
free(str3);
|
||||
return(res_str);
|
||||
}
|
||||
|
||||
/* and the rest */
|
||||
static char *
|
||||
make_name(void)
|
||||
{
|
||||
char * name = (char *)mm_alloc(yyleng + 1);
|
||||
|
||||
strncpy(name, yytext, yyleng);
|
||||
name[yyleng] = '\0';
|
||||
return(name);
|
||||
}
|
||||
|
||||
static char *
|
||||
create_questionmarks(char *name, bool array)
|
||||
{
|
||||
struct variable *p = find_variable(name);
|
||||
int count;
|
||||
char *result = EMPTY;
|
||||
|
||||
/* In case we have a struct, we have to print as many "?" as there are attributes in the struct
|
||||
* An array is only allowed together with an element argument
|
||||
* This is essantially only used for inserts, but using a struct as input parameter is an error anywhere else
|
||||
* so we don't have to worry here. */
|
||||
|
||||
if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct))
|
||||
{
|
||||
struct ECPGstruct_member *m;
|
||||
|
||||
if (p->type->type == ECPGt_struct)
|
||||
m = p->type->u.members;
|
||||
else
|
||||
m = p->type->u.element->u.members;
|
||||
|
||||
for (count = 0; m != NULL; m=m->next, count++);
|
||||
}
|
||||
else
|
||||
count = 1;
|
||||
|
||||
for (; count > 0; count --)
|
||||
{
|
||||
sprintf(pacounter_buffer, "$%d", pacounter++);
|
||||
result = cat_str(3, result, strdup(pacounter_buffer), make_str(" , "));
|
||||
}
|
||||
|
||||
/* removed the trailing " ," */
|
||||
|
||||
result[strlen(result)-3] = '\0';
|
||||
return(result);
|
||||
}
|
||||
|
||||
static char *
|
||||
adjust_informix(struct arguments *list)
|
||||
{
|
||||
/* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
|
||||
* for instance you can declare variables in a function, and then subsequently use them
|
||||
* {
|
||||
* declare_vars();
|
||||
* exec sql ... which uses vars declared in the above function
|
||||
*
|
||||
* This breaks standard and leads to some very dangerous programming.
|
||||
* Since they do, we have to work around and accept their syntax as well.
|
||||
* But we will do so ONLY in Informix mode.
|
||||
* We have to change the variables to our own struct and just store the pointer instead of the variable
|
||||
*/
|
||||
|
||||
struct arguments *ptr;
|
||||
char *result = make_str("");
|
||||
|
||||
for (ptr = list; ptr != NULL; ptr = ptr->next)
|
||||
{
|
||||
char temp[20]; /* this should be sufficient unless you have 8 byte integers */
|
||||
char *original_var;
|
||||
|
||||
/* change variable name to "ECPG_informix_get_var(<counter>)" */
|
||||
original_var = ptr->variable->name;
|
||||
sprintf(temp, "%d))", ecpg_informix_var);
|
||||
|
||||
if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
|
||||
{
|
||||
ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"), ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
|
||||
sprintf(temp, "%d, (", ecpg_informix_var++);
|
||||
}
|
||||
else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
|
||||
{
|
||||
ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
|
||||
sprintf(temp, "%d, (", ecpg_informix_var++);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr->variable = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
|
||||
sprintf(temp, "%d, &(", ecpg_informix_var++);
|
||||
}
|
||||
|
||||
/* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
|
||||
result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
|
||||
|
||||
/* now the indicator if there is one */
|
||||
if (ptr->indicator->type->type != ECPGt_NO_INDICATOR)
|
||||
{
|
||||
/* change variable name to "ECPG_informix_get_var(<counter>)" */
|
||||
original_var = ptr->indicator->name;
|
||||
sprintf(temp, "%d))", ecpg_informix_var);
|
||||
|
||||
/* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
|
||||
if (atoi(ptr->indicator->type->size) > 1)
|
||||
{
|
||||
ptr->indicator = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
|
||||
sprintf(temp, "%d, (", ecpg_informix_var++);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr->indicator = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
|
||||
sprintf(temp, "%d, &(", ecpg_informix_var++);
|
||||
}
|
||||
result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct cursor *
|
||||
add_additional_variables(char *name, bool insert)
|
||||
{
|
||||
struct cursor *ptr;
|
||||
struct arguments *p;
|
||||
|
||||
for (ptr = cur; ptr != NULL; ptr=ptr->next)
|
||||
{
|
||||
if (strcmp(ptr->name, name) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ptr == NULL)
|
||||
{
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "trying to access an undeclared cursor \"%s\"\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (insert)
|
||||
{
|
||||
/* add all those input variables that were given earlier
|
||||
* note that we have to append here but have to keep the existing order */
|
||||
for (p = ptr->argsinsert; p; p = p->next)
|
||||
add_variable_to_tail(&argsinsert, p->variable, p->indicator);
|
||||
}
|
||||
|
||||
/* add all those output variables that were given earlier */
|
||||
for (p = ptr->argsresult; p; p = p->next)
|
||||
add_variable_to_tail(&argsresult, p->variable, p->indicator);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void
|
||||
add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enum, char *type_dimension, char *type_index, int initializer, int array)
|
||||
{
|
||||
/* add entry to list */
|
||||
struct typedefs *ptr, *this;
|
||||
|
||||
if ((type_enum == ECPGt_struct ||
|
||||
type_enum == ECPGt_union) &&
|
||||
initializer == 1)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in typedef command");
|
||||
else
|
||||
{
|
||||
for (ptr = types; ptr != NULL; ptr = ptr->next)
|
||||
{
|
||||
if (strcmp(name, ptr->name) == 0)
|
||||
/* re-definition is a bug */
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "type %s already defined", name);
|
||||
}
|
||||
adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true);
|
||||
|
||||
this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
|
||||
|
||||
/* initial definition */
|
||||
this->next = types;
|
||||
this->name = name;
|
||||
this->brace_level = braces_open;
|
||||
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
|
||||
this->type->type_enum = type_enum;
|
||||
this->type->type_str = mm_strdup(name);
|
||||
this->type->type_dimension = dimension; /* dimension of array */
|
||||
this->type->type_index = length; /* length of string */
|
||||
this->type->type_sizeof = ECPGstruct_sizeof;
|
||||
this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
|
||||
ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
|
||||
|
||||
if (type_enum != ECPGt_varchar &&
|
||||
type_enum != ECPGt_char &&
|
||||
type_enum != ECPGt_unsigned_char &&
|
||||
atoi(this->type->type_index) >= 0)
|
||||
mmerror(PARSE_ERROR, ET_ERROR, "no multidimensional array support for simple data types");
|
||||
|
||||
types = this;
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
%name-prefix="base_yy"
|
||||
%locations
|
||||
|
||||
%union {
|
||||
double dval;
|
||||
char *str;
|
||||
int ival;
|
||||
struct when action;
|
||||
struct index index;
|
||||
int tagname;
|
||||
struct this_type type;
|
||||
enum ECPGttype type_enum;
|
||||
enum ECPGdtype dtype_enum;
|
||||
struct fetch_desc descriptor;
|
||||
struct su_symbol struct_union;
|
||||
struct prep prep;
|
||||
}
|
28
src/interfaces/ecpg/preproc/ecpg.tokens
Normal file
28
src/interfaces/ecpg/preproc/ecpg.tokens
Normal file
@ -0,0 +1,28 @@
|
||||
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.tokens,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
|
||||
/* special embedded SQL token */
|
||||
%token SQL_ALLOCATE SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK
|
||||
SQL_CALL SQL_CARDINALITY SQL_CONNECT
|
||||
SQL_COUNT
|
||||
SQL_DATETIME_INTERVAL_CODE
|
||||
SQL_DATETIME_INTERVAL_PRECISION SQL_DESCRIBE
|
||||
SQL_DESCRIPTOR SQL_DISCONNECT SQL_FOUND
|
||||
SQL_FREE SQL_GET SQL_GO SQL_GOTO SQL_IDENTIFIED
|
||||
SQL_INDICATOR SQL_KEY_MEMBER SQL_LENGTH
|
||||
SQL_LONG SQL_NULLABLE SQL_OCTET_LENGTH
|
||||
SQL_OPEN SQL_OUTPUT SQL_REFERENCE
|
||||
SQL_RETURNED_LENGTH SQL_RETURNED_OCTET_LENGTH SQL_SCALE
|
||||
SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL SQL_SQLERROR
|
||||
SQL_SQLPRINT SQL_SQLWARNING SQL_START SQL_STOP
|
||||
SQL_STRUCT SQL_UNSIGNED SQL_VAR SQL_WHENEVER
|
||||
|
||||
/* C token */
|
||||
%token S_ADD S_AND S_ANYTHING S_AUTO S_CONST S_DEC S_DIV
|
||||
S_DOTPOINT S_EQUAL S_EXTERN S_INC S_LSHIFT S_MEMPOINT
|
||||
S_MEMBER S_MOD S_MUL S_NEQUAL S_OR S_REGISTER S_RSHIFT
|
||||
S_STATIC S_SUB S_VOLATILE
|
||||
S_TYPEDEF
|
||||
|
||||
%token TYPECAST
|
||||
%token CSTRING CVARIABLE CPP_LINE IP
|
||||
%token DOLCONST ECONST NCONST UCONST UIDENT
|
||||
|
2003
src/interfaces/ecpg/preproc/ecpg.trailer
Normal file
2003
src/interfaces/ecpg/preproc/ecpg.trailer
Normal file
File diff suppressed because it is too large
Load Diff
143
src/interfaces/ecpg/preproc/ecpg.type
Normal file
143
src/interfaces/ecpg/preproc/ecpg.type
Normal file
@ -0,0 +1,143 @@
|
||||
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
|
||||
%type <str> ECPGAllocateDescr
|
||||
%type <str> ECPGCKeywords
|
||||
%type <str> ECPGColId
|
||||
%type <str> ECPGColLabel
|
||||
%type <str> ECPGColLabelCommon
|
||||
%type <str> ECPGConnect
|
||||
%type <str> ECPGCursorStmt
|
||||
%type <str> ECPGDeallocateDescr
|
||||
%type <str> ECPGDeclaration
|
||||
%type <str> ECPGDeclare
|
||||
%type <str> ECPGDescribe
|
||||
%type <str> ECPGDisconnect
|
||||
%type <str> ECPGExecuteImmediateStmt
|
||||
%type <str> ECPGFree
|
||||
%type <str> ECPGGetDescHeaderItem
|
||||
%type <str> ECPGGetDescItem
|
||||
%type <str> ECPGGetDescriptorHeader
|
||||
%type <str> ECPGKeywords
|
||||
%type <str> ECPGKeywords_rest
|
||||
%type <str> ECPGKeywords_vanames
|
||||
%type <str> ECPGOpen
|
||||
%type <str> ECPGSetAutocommit
|
||||
%type <str> ECPGSetConnection
|
||||
%type <str> ECPGSetDescHeaderItem
|
||||
%type <str> ECPGSetDescItem
|
||||
%type <str> ECPGSetDescriptorHeader
|
||||
%type <str> ECPGTypeName
|
||||
%type <str> ECPGTypedef
|
||||
%type <str> ECPGVar
|
||||
%type <str> ECPGVarDeclaration
|
||||
%type <str> ECPGWhenever
|
||||
%type <str> ECPGunreserved
|
||||
%type <str> ECPGunreserved_con
|
||||
%type <str> ECPGunreserved_interval
|
||||
%type <str> UsingConst
|
||||
%type <str> UsingValue
|
||||
%type <str> c_anything
|
||||
%type <str> c_args
|
||||
%type <str> c_list
|
||||
%type <str> c_stuff
|
||||
%type <str> c_stuff_item
|
||||
%type <str> c_term
|
||||
%type <str> c_thing
|
||||
%type <str> char_variable
|
||||
%type <str> civar
|
||||
%type <str> civarind
|
||||
%type <str> ColLabel
|
||||
%type <str> connect_options
|
||||
%type <str> connection_object
|
||||
%type <str> connection_target
|
||||
%type <str> coutputvariable
|
||||
%type <str> cvariable
|
||||
%type <str> db_prefix
|
||||
%type <str> CreateAsStmt
|
||||
%type <str> DeallocateStmt
|
||||
%type <str> dis_name
|
||||
%type <str> ecpg_bconst
|
||||
%type <str> ecpg_fconst
|
||||
%type <str> ecpg_ident
|
||||
%type <str> ecpg_interval
|
||||
%type <str> ecpg_into
|
||||
%type <str> ecpg_param
|
||||
%type <str> ecpg_sconst
|
||||
%type <str> ecpg_using
|
||||
%type <str> ecpg_xconst
|
||||
%type <str> enum_definition
|
||||
%type <str> enum_type
|
||||
%type <str> execstring
|
||||
%type <str> execute_rest
|
||||
%type <str> indicator
|
||||
%type <str> into_descriptor
|
||||
%type <str> Iresult
|
||||
%type <str> on_off
|
||||
%type <str> opt_bit_field
|
||||
%type <str> opt_connection_name
|
||||
%type <str> opt_database_name
|
||||
%type <str> opt_ecpg_using
|
||||
%type <str> opt_initializer
|
||||
%type <str> opt_options
|
||||
%type <str> opt_output
|
||||
%type <str> opt_pointer
|
||||
%type <str> opt_port
|
||||
%type <str> opt_reference
|
||||
%type <str> opt_scale
|
||||
%type <str> opt_server
|
||||
%type <str> opt_user
|
||||
%type <str> opt_opt_value
|
||||
%type <str> ora_user
|
||||
%type <str> precision
|
||||
%type <str> prepared_name
|
||||
%type <str> quoted_ident_stringvar
|
||||
%type <str> RuleStmt
|
||||
%type <str> s_struct_union
|
||||
%type <str> server
|
||||
%type <str> server_name
|
||||
%type <str> single_vt_declaration
|
||||
%type <str> storage_clause
|
||||
%type <str> storage_declaration
|
||||
%type <str> storage_modifier
|
||||
%type <str> struct_union_type
|
||||
%type <str> struct_union_type_with_symbol
|
||||
%type <str> symbol
|
||||
%type <str> type_declaration
|
||||
%type <str> unreserved_keyword
|
||||
%type <str> user_name
|
||||
%type <str> using_descriptor
|
||||
%type <str> var_declaration
|
||||
%type <str> var_type_declarations
|
||||
%type <str> variable
|
||||
%type <str> variable_declarations
|
||||
%type <str> variable_list
|
||||
%type <str> vt_declarations
|
||||
|
||||
%type <str> Op
|
||||
%type <str> IntConstVar
|
||||
%type <str> AllConstVar
|
||||
%type <str> CSTRING
|
||||
%type <str> CPP_LINE
|
||||
%type <str> CVARIABLE
|
||||
%type <str> DOLCONST
|
||||
%type <str> ECONST
|
||||
%type <str> NCONST
|
||||
%type <str> SCONST
|
||||
%type <str> UCONST
|
||||
%type <str> UIDENT
|
||||
|
||||
%type <struct_union> s_struct_union_symbol
|
||||
|
||||
%type <descriptor> ECPGGetDescriptor
|
||||
%type <descriptor> ECPGSetDescriptor
|
||||
|
||||
%type <type_enum> simple_type
|
||||
%type <type_enum> signed_type
|
||||
%type <type_enum> unsigned_type
|
||||
|
||||
%type <dtype_enum> descriptor_item
|
||||
%type <dtype_enum> desc_header_item
|
||||
|
||||
%type <type> var_type
|
||||
|
||||
%type <action> action
|
||||
|
Loading…
x
Reference in New Issue
Block a user