Commit e339ed5f authored by Michael Meskes's avatar Michael Meskes

Added files containing changes between gram.y and preproc.y.

parent 4607c5ca
/* $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; }
/* $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;
}
/* $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
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
statements: /*EMPTY*/
| statements statement
;
statement: ecpgstart at stmt ';' { connection = NULL; }
| ecpgstart stmt ';'
| ecpgstart ECPGVarDeclaration
{
fprintf(yyout, "%s", $2);
free($2);
output_line_number();
}
| ECPGDeclaration
| c_thing { fprintf(yyout, "%s", $1); free($1); }
| CPP_LINE { fprintf(yyout, "%s", $1); free($1); }
| '{' { braces_open++; fputs("{", yyout); }
| '}' { remove_typedefs(braces_open); remove_variables(braces_open--); fputs("}", yyout); }
;
CreateAsStmt: CREATE OptTemp TABLE create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data
{
if (FoundInto == 1)
mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT cannot specify INTO\n");
$$ = cat_str(6, make_str("create"), $2, make_str("table"), $4, make_str("as"), $7);
}
;
RuleStmt: CREATE opt_or_replace RULE name AS
{QueryIsRule = 1;}
ON event TO qualified_name where_clause
DO opt_instead RuleActionList
{
QueryIsRule=0;
$$ = cat_str(12, make_str("create"), $2, make_str("rule"), $4, make_str("as on"), $8, make_str("to"), $10, $11, make_str("do"), $13, $14);
}
;
at: AT connection_object
{
connection = $2;
/*
* Do we have a variable as connection target?
* Remove the variable from the variable
* list or else it will be used twice
*/
if (argsinsert != NULL)
argsinsert = NULL;
}
;
/*
* the exec sql connect statement: connect to the given database
*/
ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
{ $$ = cat_str(5, $3, make_str(","), $5, make_str(","), $4); }
| SQL_CONNECT TO DEFAULT
{ $$ = make_str("NULL, NULL, NULL, \"DEFAULT\""); }
/* also allow ORACLE syntax */
| SQL_CONNECT ora_user
{ $$ = cat_str(3, make_str("NULL,"), $2, make_str(", NULL")); }
| DATABASE connection_target
{ $$ = cat2_str($2, make_str(", NULL, NULL, NULL")); }
;
connection_target: opt_database_name opt_server opt_port
{
/* old style: dbname[@server][:port] */
if (strlen($2) > 0 && *($2) != '@')
mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", $2);
/* C strings need to be handled differently */
if ($1[0] == '\"')
$$ = $1;
else
$$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
}
| db_prefix ':' server opt_port '/' opt_database_name opt_options
{
/* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported");
if (strncmp($3, "//", strlen("//")) != 0)
mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", $3);
if (strncmp($1, "unix", strlen("unix")) == 0 &&
strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
mmerror(PARSE_ERROR, ET_ERROR, "unix domain sockets only work on \"localhost\" but not on \"%s\"", $3 + strlen("//"));
$$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6), $7, make_str("\"")));
}
| char_variable
{
$$ = $1;
}
| ecpg_sconst
{
/* We can only process double quoted strings not single quotes ones,
* so we change the quotes.
* Note, that the rule for ecpg_sconst adds these single quotes. */
$1[0] = '\"';
$1[strlen($1)-1] = '\"';
$$ = $1;
}
;
opt_database_name: database_name { $$ = $1; }
| /*EMPTY*/ { $$ = EMPTY; }
;
db_prefix: ecpg_ident cvariable
{
if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", $2);
if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
mmerror(PARSE_ERROR, ET_ERROR, "illegal connection type %s", $1);
$$ = make3_str($1, make_str(":"), $2);
}
;
server: Op server_name
{
if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0)
mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", $1);
$$ = make2_str($1, $2);
}
;
opt_server: server { $$ = $1; }
| /*EMPTY*/ { $$ = EMPTY; }
;
server_name: ColId { $$ = $1; }
| ColId '.' server_name { $$ = make3_str($1, make_str("."), $3); }
| IP { $$ = make_name(); }
;
opt_port: ':' Iconst { $$ = make2_str(make_str(":"), $2); }
| /*EMPTY*/ { $$ = EMPTY; }
;
opt_connection_name: AS connection_object { $$ = $2; }
| /*EMPTY*/ { $$ = make_str("NULL"); }
;
opt_user: USER ora_user { $$ = $2; }
| /*EMPTY*/ { $$ = make_str("NULL, NULL"); }
;
ora_user: user_name
{ $$ = cat2_str($1, make_str(", NULL")); }
| user_name '/' user_name
{ $$ = cat_str(3, $1, make_str(","), $3); }
| user_name SQL_IDENTIFIED BY user_name
{ $$ = cat_str(3, $1, make_str(","), $4); }
| user_name USING user_name
{ $$ = cat_str(3, $1, make_str(","), $3); }
;
user_name: RoleId
{
if ($1[0] == '\"')
$$ = $1;
else
$$ = make3_str(make_str("\""), $1, make_str("\""));
}
| ecpg_sconst
{
if ($1[0] == '\"')
$$ = $1;
else
$$ = make3_str(make_str("\""), $1, make_str("\""));
}
| civar
{
enum ECPGttype type = argsinsert->variable->type->type;
/* if array see what's inside */
if (type == ECPGt_array)
type = argsinsert->variable->type->u.element->type;
/* handle varchars */
if (type == ECPGt_varchar)
$$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr"));
else
$$ = mm_strdup(argsinsert->variable->name);
}
;
char_variable: cvariable
{
/* check if we have a string variable */
struct variable *p = find_variable($1);
enum ECPGttype type = p->type->type;
/* If we have just one character this is not a string */
if (atol(p->type->size) == 1)
mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
else
{
/* if array see what's inside */
if (type == ECPGt_array)
type = p->type->u.element->type;
switch (type)
{
case ECPGt_char:
case ECPGt_unsigned_char:
$$ = $1;
break;
case ECPGt_varchar:
$$ = make2_str($1, make_str(".arr"));
break;
default:
mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
$$ = $1;
break;
}
}
}
;
opt_options: Op connect_options
{
if (strlen($1) == 0)
mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
if (strcmp($1, "?") != 0)
mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $1);
$$ = make2_str(make_str("?"), $2);
}
| /*EMPTY*/ { $$ = EMPTY; }
;
connect_options: ColId opt_opt_value
{ $$ = make2_str($1, $2); }
| ColId opt_opt_value Op connect_options
{
if (strlen($3) == 0)
mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
if (strcmp($3, "&") != 0)
mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $3);
$$ = cat_str(3, make2_str($1, $2), $3, $4);
}
;
opt_opt_value: /*EMPTY*/
{ $$ = EMPTY; }
| '=' Iconst
{ $$ = make2_str(make_str("="), $2); }
| '=' ecpg_ident
{ $$ = make2_str(make_str("="), $2); }
| '=' civar
{ $$ = make2_str(make_str("="), $2); }
;
prepared_name: name {
if ($1[0] == '\"' && $1[strlen($1)-1] == '\"') /* already quoted? */
$$ = $1;
else /* not quoted => convert to lowercase */
{
int i;
for (i = 0; i< strlen($1); i++)
$1[i] = tolower((unsigned char) $1[i]);
$$ = make3_str(make_str("\""), $1, make_str("\""));
}
}
| char_variable { $$ = $1; }
;
/*
* Declare a prepared cursor. The syntax is different from the standard
* declare statement, so we create a new rule.
*/
ECPGCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR prepared_name
{
struct cursor *ptr, *this;
struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
const char *con = connection ? connection : "NULL";
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
if (strcmp($2, ptr->name) == 0)
/* re-definition is a bug */
mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" already defined", $2);
}
this = (struct cursor *) mm_alloc(sizeof(struct cursor));
/* initial definition */
this->next = cur;
this->name = $2;
this->connection = connection;
this->command = cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for $1"));
this->argsresult = NULL;
thisquery->type = &ecpg_query;
thisquery->brace_level = 0;
thisquery->next = NULL;
thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen($7));
sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);
this->argsinsert = NULL;
add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
cur = this;
$$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
}
;
ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring
{
/* execute immediate means prepare the statement and
* immediately execute it */
$$ = $3;
};
/*
* variable decalartion outside exec sql declare block
*/
ECPGVarDeclaration: single_vt_declaration;
single_vt_declaration: type_declaration { $$ = $1; }
| var_declaration { $$ = $1; }
;
precision: NumericOnly { $$ = $1; };
opt_scale: ',' NumericOnly { $$ = $2; }
| /* EMPTY */ { $$ = EMPTY; }
;
ecpg_interval: opt_interval { $$ = $1; }
| YEAR_P TO MINUTE_P { $$ = make_str("year to minute"); }
| YEAR_P TO SECOND_P { $$ = make_str("year to second"); }
| DAY_P TO DAY_P { $$ = make_str("day to day"); }
| MONTH_P TO MONTH_P { $$ = make_str("month to month"); }
;
/*
* variable declaration inside exec sql declare block
*/
ECPGDeclaration: sql_startdeclare
{ fputs("/* exec sql begin declare section */", yyout); }
var_type_declarations sql_enddeclare
{
fprintf(yyout, "%s/* exec sql end declare section */", $3);
free($3);
output_line_number();
}
;
sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {};
sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {};
var_type_declarations: /*EMPTY*/ { $$ = EMPTY; }
| vt_declarations { $$ = $1; }
| CPP_LINE { $$ = $1; }
;
vt_declarations: var_declaration { $$ = $1; }
| type_declaration { $$ = $1; }
| vt_declarations var_declaration { $$ = cat2_str($1, $2); }
| vt_declarations type_declaration { $$ = cat2_str($1, $2); }
| vt_declarations CPP_LINE { $$ = cat2_str($1, $2); }
;
variable_declarations: var_declaration { $$ = $1; }
| variable_declarations var_declaration { $$ = cat2_str($1, $2); }
;
type_declaration: S_TYPEDEF
{
/* reset this variable so we see if there was */
/* an initializer specified */
initializer = 0;
}
var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';'
{
add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0);
fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str);
output_line_number();
$$ = make_str("");
};
var_declaration: storage_declaration
var_type
{
actual_type[struct_level].type_enum = $2.type_enum;
actual_type[struct_level].type_dimension = $2.type_dimension;
actual_type[struct_level].type_index = $2.type_index;
actual_type[struct_level].type_sizeof = $2.type_sizeof;
actual_startline[struct_level] = hashline_number();
}
variable_list ';'
{
$$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n"));
}
| var_type
{
actual_type[struct_level].type_enum = $1.type_enum;
actual_type[struct_level].type_dimension = $1.type_dimension;
actual_type[struct_level].type_index = $1.type_index;
actual_type[struct_level].type_sizeof = $1.type_sizeof;
actual_startline[struct_level] = hashline_number();
}
variable_list ';'
{
$$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n"));
}
| struct_union_type_with_symbol ';'
{
$$ = cat2_str($1, make_str(";"));
}
;
opt_bit_field: ':' Iconst { $$ =cat2_str(make_str(":"), $2); }
| /* EMPTY */ { $$ = EMPTY; }
;
storage_declaration: storage_clause storage_modifier
{$$ = cat2_str ($1, $2); }
| storage_clause {$$ = $1; }
| storage_modifier {$$ = $1; }
;
storage_clause : S_EXTERN { $$ = make_str("extern"); }
| S_STATIC { $$ = make_str("static"); }
| S_REGISTER { $$ = make_str("register"); }
| S_AUTO { $$ = make_str("auto"); }
;
storage_modifier : S_CONST { $$ = make_str("const"); }
| S_VOLATILE { $$ = make_str("volatile"); }
;
var_type: simple_type
{
$$.type_enum = $1;
$$.type_str = mm_strdup(ecpg_type_name($1));
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
| struct_union_type
{
$$.type_str = $1;
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
if (strncmp($1, "struct", sizeof("struct")-1) == 0)
{
$$.type_enum = ECPGt_struct;
$$.type_sizeof = ECPGstruct_sizeof;
}
else
{
$$.type_enum = ECPGt_union;
$$.type_sizeof = NULL;
}
}
| enum_type
{
$$.type_str = $1;
$$.type_enum = ECPGt_int;
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
| ECPGColLabelCommon '(' precision opt_scale ')'
{
if (strcmp($1, "numeric") == 0)
{
$$.type_enum = ECPGt_numeric;
$$.type_str = make_str("numeric");
}
else if (strcmp($1, "decimal") == 0)
{
$$.type_enum = ECPGt_decimal;
$$.type_str = make_str("decimal");
}
else
{
mmerror(PARSE_ERROR, ET_ERROR, "only numeric/decimal have precision/scale argument");
$$.type_enum = ECPGt_numeric;
$$.type_str = make_str("numeric");
}
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
| ECPGColLabelCommon ecpg_interval
{
if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here");
/*
* Check for type names that the SQL grammar treats as
* unreserved keywords
*/
if (strcmp($1, "varchar") == 0)
{
$$.type_enum = ECPGt_varchar;
$$.type_str = EMPTY; /*make_str("varchar");*/
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
else if (strcmp($1, "float") == 0)
{
$$.type_enum = ECPGt_float;
$$.type_str = make_str("float");
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
else if (strcmp($1, "double") == 0)
{
$$.type_enum = ECPGt_double;
$$.type_str = make_str("double");
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
else if (strcmp($1, "numeric") == 0)
{
$$.type_enum = ECPGt_numeric;
$$.type_str = make_str("numeric");
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
else if (strcmp($1, "decimal") == 0)
{
$$.type_enum = ECPGt_decimal;
$$.type_str = make_str("decimal");
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
else if (strcmp($1, "date") == 0)
{
$$.type_enum = ECPGt_date;
$$.type_str = make_str("date");
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
else if (strcmp($1, "timestamp") == 0)
{
$$.type_enum = ECPGt_timestamp;
$$.type_str = make_str("timestamp");
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
else if (strcmp($1, "interval") == 0)
{
$$.type_enum = ECPGt_interval;
$$.type_str = make_str("interval");
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
else if (strcmp($1, "datetime") == 0)
{
$$.type_enum = ECPGt_timestamp;
$$.type_str = make_str("timestamp");
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = NULL;
}
else
{
/* this is for typedef'ed types */
struct typedefs *this = get_typedef($1);
$$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
$$.type_enum = this->type->type_enum;
$$.type_dimension = this->type->type_dimension;
$$.type_index = this->type->type_index;
if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
$$.type_sizeof = this->type->type_sizeof;
else
$$.type_sizeof = cat_str(3, make_str("sizeof("), mm_strdup(this->name), make_str(")"));
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
}
}
| s_struct_union_symbol
{
/* this is for named structs/unions */
char *name;
struct typedefs *this;
bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
name = cat2_str($1.su, $1.symbol);
/* Do we have a forward definition? */
if (!forward)
{
/* No */
this = get_typedef(name);
$$.type_str = mm_strdup(this->name);
$$.type_enum = this->type->type_enum;
$$.type_dimension = this->type->type_dimension;
$$.type_index = this->type->type_index;
$$.type_sizeof = this->type->type_sizeof;
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
free(name);
}
else
{
$$.type_str = name;
$$.type_enum = ECPGt_long;
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = make_str("");
struct_member_list[struct_level] = NULL;
}
}
;
enum_type: ENUM_P symbol enum_definition
{ $$ = cat_str(3, make_str("enum"), $2, $3); }
| ENUM_P enum_definition
{ $$ = cat2_str(make_str("enum"), $2); }
| ENUM_P symbol
{ $$ = cat2_str(make_str("enum"), $2); }
;
enum_definition: '{' c_list '}'
{ $$ = cat_str(3, make_str("{"), $2, make_str("}")); };
struct_union_type_with_symbol: s_struct_union_symbol
{
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
forward_name = mm_strdup($1.symbol);
}
'{' variable_declarations '}'
{
struct typedefs *ptr, *this;
struct this_type su_type;
ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = NULL;
struct_level--;
if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
su_type.type_enum = ECPGt_struct;
else
su_type.type_enum = ECPGt_union;
su_type.type_str = cat2_str($1.su, $1.symbol);
free(forward_name);
forward_name = NULL;
/* This is essantially a typedef but needs the keyword struct/union as well.
* So we create the typedef for each struct definition with symbol */
for (ptr = types; ptr != NULL; ptr = ptr->next)
{
if (strcmp(su_type.type_str, ptr->name) == 0)
/* re-definition is a bug */
mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" already defined", su_type.type_str);
}
this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
/* initial definition */
this->next = types;
this->name = mm_strdup(su_type.type_str);
this->brace_level = braces_open;
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
this->type->type_enum = su_type.type_enum;
this->type->type_str = mm_strdup(su_type.type_str);
this->type->type_dimension = make_str("-1"); /* dimension of array */
this->type->type_index = make_str("-1"); /* length of string */
this->type->type_sizeof = ECPGstruct_sizeof;
this->struct_member_list = struct_member_list[struct_level];
types = this;
$$ = cat_str(4, su_type.type_str, make_str("{"), $4, make_str("}"));
}
;
struct_union_type: struct_union_type_with_symbol { $$ = $1; }
| s_struct_union
{
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
}
'{' variable_declarations '}'
{
ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = NULL;
struct_level--;
$$ = cat_str(4, $1, make_str("{"), $4, make_str("}"));
}
;
s_struct_union_symbol: SQL_STRUCT symbol
{
$$.su = make_str("struct");
$$.symbol = $2;
ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")"));
}
| UNION symbol
{
$$.su = make_str("union");
$$.symbol = $2;
}
;
s_struct_union: SQL_STRUCT
{
ECPGstruct_sizeof = make_str(""); /* This must not be NULL to distinguish from simple types. */
$$ = make_str("struct");
}
| UNION { $$ = make_str("union"); }
;
simple_type: unsigned_type { $$=$1; }
| opt_signed signed_type { $$=$2; }
;
unsigned_type: SQL_UNSIGNED SQL_SHORT { $$ = ECPGt_unsigned_short; }
| SQL_UNSIGNED SQL_SHORT INT_P { $$ = ECPGt_unsigned_short; }
| SQL_UNSIGNED { $$ = ECPGt_unsigned_int; }
| SQL_UNSIGNED INT_P { $$ = ECPGt_unsigned_int; }
| SQL_UNSIGNED SQL_LONG { $$ = ECPGt_unsigned_long; }
| SQL_UNSIGNED SQL_LONG INT_P { $$ = ECPGt_unsigned_long; }
| SQL_UNSIGNED SQL_LONG SQL_LONG
{
#ifdef HAVE_LONG_LONG_INT_64
$$ = ECPGt_unsigned_long_long;
#else
$$ = ECPGt_unsigned_long;
#endif
}
| SQL_UNSIGNED SQL_LONG SQL_LONG INT_P
{
#ifdef HAVE_LONG_LONG_INT_64
$$ = ECPGt_unsigned_long_long;
#else
$$ = ECPGt_unsigned_long;
#endif
}
| SQL_UNSIGNED CHAR_P { $$ = ECPGt_unsigned_char; }
;
signed_type: SQL_SHORT { $$ = ECPGt_short; }
| SQL_SHORT INT_P { $$ = ECPGt_short; }
| INT_P { $$ = ECPGt_int; }
| SQL_LONG { $$ = ECPGt_long; }
| SQL_LONG INT_P { $$ = ECPGt_long; }
| SQL_LONG SQL_LONG
{
#ifdef HAVE_LONG_LONG_INT_64
$$ = ECPGt_long_long;
#else
$$ = ECPGt_long;
#endif
}
| SQL_LONG SQL_LONG INT_P
{
#ifdef HAVE_LONG_LONG_INT_64
$$ = ECPGt_long_long;
#else
$$ = ECPGt_long;
#endif
}
| SQL_BOOL { $$ = ECPGt_bool; }
| CHAR_P { $$ = ECPGt_char; }
| DOUBLE_P { $$ = ECPGt_double; }
;
opt_signed: SQL_SIGNED
| /* EMPTY */
;
variable_list: variable
{ $$ = $1; }
| variable_list ',' variable
{ $$ = cat_str(3, $1, make_str(","), $3); }
;
variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initializer
{
struct ECPGtype * type;
char *dimension = $3.index1; /* dimension of array */
char *length = $3.index2; /* length of string */
char dim[14L];
char *vcn;
adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1), false);
switch (actual_type[struct_level].type_enum)
{
case ECPGt_struct:
case ECPGt_union:
if (atoi(dimension) < 0)
type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof);
else
type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof), dimension);
$$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
break;
case ECPGt_varchar:
if (atoi(dimension) < 0)
type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno);
else
type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno), dimension);
if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1)
*dim = '\0';
else
sprintf(dim, "[%s]", dimension);
/* cannot check for atoi <= 0 because a defined constant will yield 0 here as well */
if (atoi(length) < 0 || strcmp(length, "0") == 0)
mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented");
/* make sure varchar struct name is unique by adding linenumer of its definition */
vcn = (char *) mm_alloc(strlen($2) + sizeof(int) * CHAR_BIT * 10 / 3);
sprintf(vcn, "%s_%d", $2, yylineno);
if (strcmp(dimension, "0") == 0)
$$ = cat_str(7, make2_str(make_str(" struct varchar_"), vcn), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } *"), mm_strdup($2), $4, $5);
else
$$ = cat_str(8, make2_str(make_str(" struct varchar_"), vcn), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } "), mm_strdup($2), mm_strdup(dim), $4, $5);
break;
case ECPGt_char:
case ECPGt_unsigned_char:
if (atoi(dimension) == -1)
{
int i = strlen($5);
if (atoi(length) == -1 && i > 0) /* char <var>[] = "string" */
{
/* if we have an initializer but no string size set, let's use the initializer's length */
free(length);
length = mm_alloc(i+sizeof("sizeof()"));
sprintf(length, "sizeof(%s)", $5+2);
}
type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0);
}
else
type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension);
$$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
break;
default:
if (atoi(dimension) < 0)
type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0);
else
type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0), dimension);
$$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
break;
}
if (struct_level == 0)
new_variable($2, type, braces_open);
else
ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
free($2);
}
;
opt_initializer: /*EMPTY*/
{ $$ = EMPTY; }
| '=' c_term
{
initializer = 1;
$$ = cat2_str(make_str("="), $2);
}
;
opt_pointer: /*EMPTY*/ { $$ = EMPTY; }
| '*' { $$ = make_str("*"); }
| '*' '*' { $$ = make_str("**"); }
;
/*
* We try to simulate the correct DECLARE syntax here so we get dynamic SQL
*/
ECPGDeclare: DECLARE STATEMENT ecpg_ident
{
/* this is only supported for compatibility */
$$ = cat_str(3, make_str("/* declare statement"), $3, make_str("*/"));
}
;
/*
* the exec sql disconnect statement: disconnect from the given database
*/
ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
;
dis_name: connection_object { $$ = $1; }
| CURRENT_P { $$ = make_str("\"CURRENT\""); }
| ALL { $$ = make_str("\"ALL\""); }
| /* EMPTY */ { $$ = make_str("\"CURRENT\""); }
;
connection_object: database_name { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
| DEFAULT { $$ = make_str("\"DEFAULT\""); }
| char_variable { $$ = $1; }
;
execstring: char_variable
{ $$ = $1; }
| CSTRING
{ $$ = make3_str(make_str("\""), $1, make_str("\"")); }
;
/*
* the exec sql free command to deallocate a previously
* prepared statement
*/
ECPGFree: SQL_FREE name { $$ = $2; }
| SQL_FREE ALL { $$ = make_str("all"); }
;
/*
* open is an open cursor, at the moment this has to be removed
*/
ECPGOpen: SQL_OPEN name opt_ecpg_using { $$ = $2; };
opt_ecpg_using: /*EMPTY*/ { $$ = EMPTY; }
| ecpg_using { $$ = $1; }
;
ecpg_using: USING using_list { $$ = EMPTY; }
| using_descriptor { $$ = $1; }
;
using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
{
add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
$$ = EMPTY;
}
;
into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
{
add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
$$ = EMPTY;
}
;
opt_sql: /*EMPTY*/ | SQL_SQL;
using_list: UsingValue | UsingValue ',' using_list;
UsingValue: UsingConst
{
char *length = mm_alloc(32);
sprintf(length, "%d", (int) strlen($1));
add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator);
}
| civar { $$ = EMPTY; }
| civarind { $$ = EMPTY; }
;
UsingConst: Iconst { $$ = $1; }
| ecpg_fconst { $$ = $1; }
| ecpg_sconst { $$ = $1; }
| ecpg_bconst { $$ = $1; }
| ecpg_xconst { $$ = $1; }
;
/*
* We accept descibe but do nothing with it so far.
*/
ECPGDescribe: SQL_DESCRIBE INPUT_P name using_descriptor
{
const char *con = connection ? connection : "NULL";
mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
$$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
sprintf($$, "1, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
}
| SQL_DESCRIBE opt_output name using_descriptor
{
const char *con = connection ? connection : "NULL";
mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
$$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
}
| SQL_DESCRIBE opt_output name into_descriptor
{
const char *con = connection ? connection : "NULL";
mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
$$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
}
;
opt_output: SQL_OUTPUT { $$ = make_str("output"); }
| /* EMPTY */ { $$ = EMPTY; }
;
/*
* dynamic SQL: descriptor based access
* originall written by Christof Petig <christof.petig@wtal.de>
* and Peter Eisentraut <peter.eisentraut@credativ.de>
*/
/*
* allocate a descriptor
*/
ECPGAllocateDescr: SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
{
add_descriptor($3,connection);
$$ = $3;
}
;
/*
* deallocate a descriptor
*/
ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
{
drop_descriptor($3,connection);
$$ = $3;
}
;
/*
* manipulate a descriptor header
*/
ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
{ $$ = $3; }
;
ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
| ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
;
ECPGGetDescHeaderItem: cvariable '=' desc_header_item
{ push_assignment($1, $3); }
;
ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems
{ $$ = $3; }
;
ECPGSetDescHeaderItems: ECPGSetDescHeaderItem
| ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem
;
ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar
{
push_assignment($3, $1);
}
;
IntConstVar: Iconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
sprintf(length, "%d", (int) strlen($1));
new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
$$ = $1;
}
| cvariable { $$ = $1; }
;
desc_header_item: SQL_COUNT { $$ = ECPGd_count; }
;
/*
* manipulate a descriptor
*/
ECPGGetDescriptor: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems
{ $$.str = $5; $$.name = $3; }
;
ECPGGetDescItems: ECPGGetDescItem
| ECPGGetDescItems ',' ECPGGetDescItem
;
ECPGGetDescItem: cvariable '=' descriptor_item { push_assignment($1, $3); };
ECPGSetDescriptor: SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems
{ $$.str = $5; $$.name = $3; }
;
ECPGSetDescItems: ECPGSetDescItem
| ECPGSetDescItems ',' ECPGSetDescItem
;
ECPGSetDescItem: descriptor_item '=' AllConstVar
{
push_assignment($3, $1);
}
;
AllConstVar: ecpg_fconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
sprintf(length, "%d", (int) strlen($1));
new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
$$ = $1;
}
| IntConstVar { $$ = $1; }
| '-' ecpg_fconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
char *var = cat2_str(make_str("-"), $2);
sprintf(length, "%d", (int) strlen(var));
new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
$$ = var;
}
| '-' Iconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
char *var = cat2_str(make_str("-"), $2);
sprintf(length, "%d", (int) strlen(var));
new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
$$ = var;
}
| ecpg_sconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
char *var = $1 + 1;
var[strlen(var) - 1] = '\0';
sprintf(length, "%d", (int) strlen(var));
new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
$$ = var;
}
;
descriptor_item: SQL_CARDINALITY { $$ = ECPGd_cardinality; }
| DATA_P { $$ = ECPGd_data; }
| SQL_DATETIME_INTERVAL_CODE { $$ = ECPGd_di_code; }
| SQL_DATETIME_INTERVAL_PRECISION { $$ = ECPGd_di_precision; }
| SQL_INDICATOR { $$ = ECPGd_indicator; }
| SQL_KEY_MEMBER { $$ = ECPGd_key_member; }
| SQL_LENGTH { $$ = ECPGd_length; }
| NAME_P { $$ = ECPGd_name; }
| SQL_NULLABLE { $$ = ECPGd_nullable; }
| SQL_OCTET_LENGTH { $$ = ECPGd_octet; }
| PRECISION { $$ = ECPGd_precision; }
| SQL_RETURNED_LENGTH { $$ = ECPGd_length; }
| SQL_RETURNED_OCTET_LENGTH { $$ = ECPGd_ret_octet; }
| SQL_SCALE { $$ = ECPGd_scale; }
| TYPE_P { $$ = ECPGd_type; }
;
/*
* set/reset the automatic transaction mode, this needs a differnet handling
* as the other set commands
*/
ECPGSetAutocommit: SET SQL_AUTOCOMMIT '=' on_off { $$ = $4; }
| SET SQL_AUTOCOMMIT TO on_off { $$ = $4; }
;
on_off: ON { $$ = make_str("on"); }
| OFF { $$ = make_str("off"); }
;
/*
* set the actual connection, this needs a differnet handling as the other
* set commands
*/
ECPGSetConnection: SET CONNECTION TO connection_object { $$ = $4; }
| SET CONNECTION '=' connection_object { $$ = $4; }
| SET CONNECTION connection_object { $$ = $3; }
;
/*
* define a new type for embedded SQL
*/
ECPGTypedef: TYPE_P
{
/* reset this variable so we see if there was */
/* an initializer specified */
initializer = 0;
}
ECPGColLabelCommon IS var_type opt_array_bounds opt_reference
{
add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0);
if (auto_create_c == false)
$$ = cat_str(7, make_str("/* exec sql type"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
else
$$ = cat_str(6, make_str("typedef "), mm_strdup($5.type_str), *$7?make_str("*"):make_str(""), mm_strdup($6.str), mm_strdup($3), make_str(";"));
}
;
opt_reference: SQL_REFERENCE { $$ = make_str("reference"); }
| /*EMPTY*/ { $$ = EMPTY; }
;
/*
* define the type of one variable for embedded SQL
*/
ECPGVar: SQL_VAR
{
/* reset this variable so we see if there was */
/* an initializer specified */
initializer = 0;
}
ColLabel IS var_type opt_array_bounds opt_reference
{
struct variable *p = find_variable($3);
char *dimension = $6.index1;
char *length = $6.index2;
struct ECPGtype * type;
if (($5.type_enum == ECPGt_struct ||
$5.type_enum == ECPGt_union) &&
initializer == 1)
mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command");
else
{
adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false);
switch ($5.type_enum)
{
case ECPGt_struct:
case ECPGt_union:
if (atoi(dimension) < 0)
type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_sizeof);
else
type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum,$5.type_sizeof), dimension);
break;
case ECPGt_varchar:
if (atoi(dimension) == -1)
type = ECPGmake_simple_type($5.type_enum, length, 0);
else
type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
break;
case ECPGt_char:
case ECPGt_unsigned_char:
if (atoi(dimension) == -1)
type = ECPGmake_simple_type($5.type_enum, length, 0);
else
type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
break;
default:
if (atoi(length) >= 0)
mmerror(PARSE_ERROR, ET_ERROR, "no multidimensional array support for simple data types");
if (atoi(dimension) < 0)
type = ECPGmake_simple_type($5.type_enum, make_str("1"), 0);
else
type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, make_str("1"), 0), dimension);
break;
}
ECPGfree_type(p->type);
p->type = type;
}
$$ = cat_str(7, make_str("/* exec sql var"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
}
;
/*
* whenever statement: decide what to do in case of error/no data found
* according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION
*/
ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
{
when_error.code = $<action>3.code;
when_error.command = $<action>3.command;
$$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */"));
}
| SQL_WHENEVER NOT SQL_FOUND action
{
when_nf.code = $<action>4.code;
when_nf.command = $<action>4.command;
$$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */"));
}
| SQL_WHENEVER SQL_SQLWARNING action
{
when_warn.code = $<action>3.code;
when_warn.command = $<action>3.command;
$$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */"));
}
;
action : CONTINUE_P
{
$<action>$.code = W_NOTHING;
$<action>$.command = NULL;
$<action>$.str = make_str("continue");
}
| SQL_SQLPRINT
{
$<action>$.code = W_SQLPRINT;
$<action>$.command = NULL;
$<action>$.str = make_str("sqlprint");
}
| SQL_STOP
{
$<action>$.code = W_STOP;
$<action>$.command = NULL;
$<action>$.str = make_str("stop");
}
| SQL_GOTO name
{
$<action>$.code = W_GOTO;
$<action>$.command = strdup($2);
$<action>$.str = cat2_str(make_str("goto "), $2);
}
| SQL_GO TO name
{
$<action>$.code = W_GOTO;
$<action>$.command = strdup($3);
$<action>$.str = cat2_str(make_str("goto "), $3);
}
| DO name '(' c_args ')'
{
$<action>$.code = W_DO;
$<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
$<action>$.str = cat2_str(make_str("do"), mm_strdup($<action>$.command));
}
| DO SQL_BREAK
{
$<action>$.code = W_BREAK;
$<action>$.command = NULL;
$<action>$.str = make_str("break");
}
| SQL_CALL name '(' c_args ')'
{
$<action>$.code = W_DO;
$<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
$<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
}
| SQL_CALL name
{
$<action>$.code = W_DO;
$<action>$.command = cat2_str($2, make_str("()"));
$<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
}
;
/* some other stuff for ecpg */
/* additional unreserved keywords */
ECPGKeywords: ECPGKeywords_vanames { $$ = $1; }
| ECPGKeywords_rest { $$ = $1; }
;
ECPGKeywords_vanames: SQL_BREAK { $$ = make_str("break"); }
| SQL_CALL { $$ = make_str("call"); }
| SQL_CARDINALITY { $$ = make_str("cardinality"); }
| SQL_COUNT { $$ = make_str("count"); }
| SQL_DATETIME_INTERVAL_CODE { $$ = make_str("datetime_interval_code"); }
| SQL_DATETIME_INTERVAL_PRECISION { $$ = make_str("datetime_interval_precision"); }
| SQL_FOUND { $$ = make_str("found"); }
| SQL_GO { $$ = make_str("go"); }
| SQL_GOTO { $$ = make_str("goto"); }
| SQL_IDENTIFIED { $$ = make_str("identified"); }
| SQL_INDICATOR { $$ = make_str("indicator"); }
| SQL_KEY_MEMBER { $$ = make_str("key_member"); }
| SQL_LENGTH { $$ = make_str("length"); }
| SQL_NULLABLE { $$ = make_str("nullable"); }
| SQL_OCTET_LENGTH { $$ = make_str("octet_length"); }
| SQL_RETURNED_LENGTH { $$ = make_str("returned_length"); }
| SQL_RETURNED_OCTET_LENGTH { $$ = make_str("returned_octet_length"); }
| SQL_SCALE { $$ = make_str("scale"); }
| SQL_SECTION { $$ = make_str("section"); }
| SQL_SQL { $$ = make_str("sql"); }
| SQL_SQLERROR { $$ = make_str("sqlerror"); }
| SQL_SQLPRINT { $$ = make_str("sqlprint"); }
| SQL_SQLWARNING { $$ = make_str("sqlwarning"); }
| SQL_STOP { $$ = make_str("stop"); }
;
ECPGKeywords_rest: SQL_CONNECT { $$ = make_str("connect"); }
| SQL_DESCRIBE { $$ = make_str("describe"); }
| SQL_DISCONNECT { $$ = make_str("disconnect"); }
| SQL_OPEN { $$ = make_str("open"); }
| SQL_VAR { $$ = make_str("var"); }
| SQL_WHENEVER { $$ = make_str("whenever"); }
;
/* additional keywords that can be SQL type names (but not ECPGColLabels) */
ECPGTypeName: SQL_BOOL { $$ = make_str("bool"); }
| SQL_LONG { $$ = make_str("long"); }
| SQL_OUTPUT { $$ = make_str("output"); }
| SQL_SHORT { $$ = make_str("short"); }
| SQL_STRUCT { $$ = make_str("struct"); }
| SQL_SIGNED { $$ = make_str("signed"); }
| SQL_UNSIGNED { $$ = make_str("unsigned"); }
;
symbol: ColLabel { $$ = $1; }
;
ECPGColId: ecpg_ident { $$ = $1; }
| ECPGunreserved_interval { $$ = $1; }
| ECPGunreserved_con { $$ = $1; }
| col_name_keyword { $$ = $1; }
| ECPGKeywords { $$ = $1; }
| ECPGCKeywords { $$ = $1; }
| CHAR_P { $$ = make_str("char"); }
| VALUES { $$ = make_str("values"); }
;
/* Column label --- allowed labels in "AS" clauses.
* This presently includes *all* Postgres keywords.
*/
ColLabel: ECPGColLabel { $$ = $1; }
| ECPGTypeName { $$ = $1; }
| CHAR_P { $$ = make_str("char"); }
| INPUT_P { $$ = make_str("input"); }
| INT_P { $$ = make_str("int"); }
| UNION { $$ = make_str("union"); }
| TO { $$ = make_str("to"); }
| ECPGCKeywords { $$ = $1; }
| ECPGunreserved_interval { $$ = $1; }
;
ECPGColLabelCommon: ecpg_ident { $$ = $1; }
| col_name_keyword { $$ = $1; }
| type_func_name_keyword { $$ = $1; }
| ECPGKeywords_vanames { $$ = $1; }
;
ECPGColLabel: ECPGColLabelCommon { $$ = $1; }
| reserved_keyword { $$ = $1; }
| ECPGunreserved { $$ = $1; }
| ECPGKeywords_rest { $$ = $1; }
;
ECPGCKeywords: S_AUTO { $$ = make_str("auto"); }
| S_CONST { $$ = make_str("const"); }
| S_EXTERN { $$ = make_str("extern"); }
| S_REGISTER { $$ = make_str("register"); }
| S_STATIC { $$ = make_str("static"); }
| S_TYPEDEF { $$ = make_str("typedef"); }
| S_VOLATILE { $$ = make_str("volatile"); }
;
/*
* Keyword classification lists. Generally, every keyword present in
* the Postgres grammar should appear in exactly one of these lists.
*
* Put a new keyword into the first list that it can go into without causing
* shift or reduce conflicts. The earlier lists define "less reserved"
* categories of keywords.
*/
/* "Unreserved" keywords --- available for use as any kind of name.
*/
/* The following symbols must be excluded from ECPGColLabel and directly included into ColLabel
to enable C variables to get names from ECPGColLabel:
DAY_P, HOUR_P, MINUTE_P, MONTH_P, SECOND_P, YEAR_P
*/
unreserved_keyword: ECPGunreserved_interval | ECPGunreserved;
ECPGunreserved_interval: DAY_P { $$ = make_str("day"); }
| HOUR_P { $$ = make_str("hour"); }
| MINUTE_P { $$ = make_str("minute"); }
| MONTH_P { $$ = make_str("month"); }
| SECOND_P { $$ = make_str("second"); }
| YEAR_P { $$ = make_str("year"); }
;
/* The following symbol must be excluded from var_name but still included in ColId
to enable ecpg special postgresql variables with this name: CONNECTION
*/
ECPGunreserved: ECPGunreserved_con { $$ = $1; }
| CONNECTION { $$ = make_str("connection"); }
;
ECPGunreserved_con: ABORT_P { $$ = make_str("abort"); }
| ABSOLUTE_P { $$ = make_str("absolute"); }
| ACCESS { $$ = make_str("access"); }
| ACTION { $$ = make_str("action"); }
| ADD_P { $$ = make_str("add"); }
| ADMIN { $$ = make_str("admin"); }
| AFTER { $$ = make_str("after"); }
| AGGREGATE { $$ = make_str("aggregate"); }
| ALSO { $$ = make_str("also"); }
| ALTER { $$ = make_str("alter"); }
| ALWAYS { $$ = make_str("always"); }
| ASSERTION { $$ = make_str("assertion"); }
| ASSIGNMENT { $$ = make_str("assignment"); }
| AT { $$ = make_str("at"); }
| BACKWARD { $$ = make_str("backward"); }
| BEFORE { $$ = make_str("before"); }
| BEGIN_P { $$ = make_str("begin"); }
| BY { $$ = make_str("by"); }
| CACHE { $$ = make_str("cache"); }
| CASCADE { $$ = make_str("cascade"); }
| CASCADED { $$ = make_str("cascaded"); }
| CHAIN { $$ = make_str("chain"); }
| CHARACTERISTICS { $$ = make_str("characteristics"); }
| CHECKPOINT { $$ = make_str("checkpoint"); }
| CLASS { $$ = make_str("class"); }
| CLOSE { $$ = make_str("close"); }
| CLUSTER { $$ = make_str("cluster"); }
| COMMENT { $$ = make_str("comment"); }
| COMMIT { $$ = make_str("commit"); }
| COMMITTED { $$ = make_str("committed"); }
| CONCURRENTLY { $$ = make_str("concurrently"); }
| CONFIGURATION { $$ = make_str("configuration"); }
/* | CONNECTION { $$ = make_str("connection"); }*/
| CONSTRAINTS { $$ = make_str("constraints"); }
| CONTENT_P { $$ = make_str("content"); }
| CONTINUE_P { $$ = make_str("continue"); }
| CONVERSION_P { $$ = make_str("conversion"); }
| COPY { $$ = make_str("copy"); }
| COST { $$ = make_str("cost"); }
| CREATEDB { $$ = make_str("createdb"); }
| CREATEROLE { $$ = make_str("createrole"); }
| CREATEUSER { $$ = make_str("createuser"); }
| CSV { $$ = make_str("csv"); }
| CTYPE { $$ = make_str("ctype"); }
| CURSOR { $$ = make_str("cursor"); }
| CYCLE { $$ = make_str("cycle"); }
| DATA_P { $$ = make_str("data"); }
| DATABASE { $$ = make_str("database"); }
/* | DAY_P { $$ = make_str("day"); }*/
| DEALLOCATE { $$ = make_str("deallocate"); }
| DECLARE { $$ = make_str("declare"); }
| DEFAULTS { $$ = make_str("defaults"); }
| DEFERRED { $$ = make_str("deferred"); }
| DELETE_P { $$ = make_str("delete"); }
| DELIMITER { $$ = make_str("delimiter"); }
| DELIMITERS { $$ = make_str("delimiters"); }
| DICTIONARY { $$ = make_str("dictionary"); }
| DISABLE_P { $$ = make_str("disable"); }
| DISCARD { $$ = make_str("discard"); }
| DOCUMENT_P { $$ = make_str("document"); }
| DOMAIN_P { $$ = make_str("domain"); }
| DOUBLE_P { $$ = make_str("double"); }
| DROP { $$ = make_str("drop"); }
| EACH { $$ = make_str("each"); }
| ENABLE_P { $$ = make_str("enable"); }
| ENCODING { $$ = make_str("encoding"); }
| ENCRYPTED { $$ = make_str("encrypted"); }
/* | ENUM_P { $$ = make_str("enum"); }*/
| ESCAPE { $$ = make_str("escape"); }
| EXCLUDING { $$ = make_str("excluding"); }
| EXCLUSIVE { $$ = make_str("exclusive"); }
| EXECUTE { $$ = make_str("execute"); }
| EXPLAIN { $$ = make_str("explain"); }
| EXTERNAL { $$ = make_str("external"); }
| FAMILY { $$ = make_str("family"); }
/* | FETCH { $$ = make_str("fetch"); }*/
| FIRST_P { $$ = make_str("first"); }
| FORCE { $$ = make_str("force"); }
| FORWARD { $$ = make_str("forward"); }
| FUNCTION { $$ = make_str("function"); }
| GLOBAL { $$ = make_str("global"); }
| GRANTED { $$ = make_str("granted"); }
| HANDLER { $$ = make_str("handler"); }
| HEADER_P { $$ = make_str("header"); }
| HOLD { $$ = make_str("hold"); }
/* | HOUR_P { $$ = make_str("hour"); }*/
| IDENTITY_P { $$ = make_str("identity"); }
| IF_P { $$ = make_str("if"); }
| IMMEDIATE { $$ = make_str("immediate"); }
| IMMUTABLE { $$ = make_str("immutable"); }
| IMPLICIT_P { $$ = make_str("implicit"); }
| INCLUDING { $$ = make_str("including"); }
| INCREMENT { $$ = make_str("increment"); }
| INDEX { $$ = make_str("index"); }
| INDEXES { $$ = make_str("indexes"); }
| INHERIT { $$ = make_str("inherit"); }
| INHERITS { $$ = make_str("inherits"); }
| INSENSITIVE { $$ = make_str("insensitive"); }
| INSERT { $$ = make_str("insert"); }
| INSTEAD { $$ = make_str("instead"); }
| ISOLATION { $$ = make_str("isolation"); }
| KEY { $$ = make_str("key"); }
| LANCOMPILER { $$ = make_str("lancompiler"); }
| LANGUAGE { $$ = make_str("language"); }
| LARGE_P { $$ = make_str("large"); }
| LAST_P { $$ = make_str("last"); }
| LEVEL { $$ = make_str("level"); }
| LISTEN { $$ = make_str("listen"); }
| LOAD { $$ = make_str("load"); }
| LOCAL { $$ = make_str("local"); }
| LOCATION { $$ = make_str("location"); }
| LOCK_P { $$ = make_str("lock"); }
| LOGIN_P { $$ = make_str("login"); }
| MAPPING { $$ = make_str("mapping"); }
| MATCH { $$ = make_str("match"); }
| MAXVALUE { $$ = make_str("maxvalue"); }
/* | MINUTE_P { $$ = make_str("minute"); }*/
| MINVALUE { $$ = make_str("minvalue"); }
| MODE { $$ = make_str("mode"); }
/* | MONTH_P { $$ = make_str("month"); }*/
| MOVE { $$ = make_str("move"); }
| NAME_P { $$ = make_str("name"); }
| NAMES { $$ = make_str("names"); }
| NEXT { $$ = make_str("next"); }
| NO { $$ = make_str("no"); }
| NOCREATEDB { $$ = make_str("nocreatedb"); }
| NOCREATEROLE { $$ = make_str("nocreaterole"); }
| NOCREATEUSER { $$ = make_str("nocreateuser"); }
| NOINHERIT { $$ = make_str("noinherit"); }
| NOLOGIN_P { $$ = make_str("nologin"); }
| NOSUPERUSER { $$ = make_str("nosuperuser"); }
| NOTHING { $$ = make_str("nothing"); }
| NOTIFY { $$ = make_str("notify"); }
| NOWAIT { $$ = make_str("nowait"); }
| NULLS_P { $$ = make_str("nulls"); }
| OBJECT_P { $$ = make_str("object"); }
| OF { $$ = make_str("of"); }
| OIDS { $$ = make_str("oids"); }
| OPERATOR { $$ = make_str("operator"); }
| OPTION { $$ = make_str("option"); }
| OWNED { $$ = make_str("owned"); }
| OWNER { $$ = make_str("owner"); }
| PARSER { $$ = make_str("parser"); }
| PARTIAL { $$ = make_str("partial"); }
| PASSWORD { $$ = make_str("password"); }
| PLANS { $$ = make_str("plans"); }
| PREPARE { $$ = make_str("prepare"); }
| PREPARED { $$ = make_str("prepared"); }
| PRESERVE { $$ = make_str("preserver"); }
| PRIOR { $$ = make_str("prior"); }
| PRIVILEGES { $$ = make_str("privileges"); }
| PROCEDURAL { $$ = make_str("procedural"); }
| PROCEDURE { $$ = make_str("procedure"); }
| QUOTE { $$ = make_str("quote"); }
| READ { $$ = make_str("read"); }
| REASSIGN { $$ = make_str("reassign"); }
| RECHECK { $$ = make_str("recheck"); }
| RECURSIVE { $$ = make_str("recursive"); }
| REINDEX { $$ = make_str("reindex"); }
| RELATIVE_P { $$ = make_str("relative"); }
| RELEASE { $$ = make_str("release"); }
| RENAME { $$ = make_str("rename"); }
| REPEATABLE { $$ = make_str("repeatable"); }
| REPLACE { $$ = make_str("replace"); }
| REPLICA { $$ = make_str("replica"); }
| RESET { $$ = make_str("reset"); }
| RESTART { $$ = make_str("restart"); }
| RESTRICT { $$ = make_str("restrict"); }
| RETURNS { $$ = make_str("returns"); }
| REVOKE { $$ = make_str("revoke"); }
| ROLE { $$ = make_str("role"); }
| ROLLBACK { $$ = make_str("rollback"); }
| ROWS { $$ = make_str("rows"); }
| RULE { $$ = make_str("rule"); }
| SAVEPOINT { $$ = make_str("savepoint"); }
| SCHEMA { $$ = make_str("schema"); }
| SCROLL { $$ = make_str("scroll"); }
| SEARCH { $$ = make_str("search"); }
/* | SECOND_P { $$ = make_str("second"); }*/
| SEQUENCE { $$ = make_str("sequence"); }
| SERIALIZABLE { $$ = make_str("serializable"); }
| SESSION { $$ = make_str("session"); }
| SET { $$ = make_str("set"); }
| SHARE { $$ = make_str("share"); }
| SHOW { $$ = make_str("show"); }
| SIMPLE { $$ = make_str("simple"); }
| STABLE { $$ = make_str("stable"); }
| STANDALONE_P { $$ = make_str("standalone"); }
| START { $$ = make_str("start"); }
| STATEMENT { $$ = make_str("statement"); }
| STATISTICS { $$ = make_str("statistics"); }
| STDIN { $$ = make_str("stdin"); }
| STDOUT { $$ = make_str("stdout"); }
| STORAGE { $$ = make_str("storage"); }
| STRICT_P { $$ = make_str("strict"); }
| STRIP_P { $$ = make_str("strip"); }
| SUPERUSER_P { $$ = make_str("superuser"); }
| SYSTEM_P { $$ = make_str("system"); }
| SYSID { $$ = make_str("sysid"); }
| TABLESPACE { $$ = make_str("tablespace"); }
| TEMP { $$ = make_str("temp"); }
| TEMPLATE { $$ = make_str("template"); }
| TEMPORARY { $$ = make_str("temporary"); }
| TEXT_P { $$ = make_str("text"); }
| TRANSACTION { $$ = make_str("transaction"); }
| TRIGGER { $$ = make_str("trigger"); }
| TRUNCATE { $$ = make_str("truncate"); }
| TRUSTED { $$ = make_str("trusted"); }
| TYPE_P { $$ = make_str("type"); }
| UNCOMMITTED { $$ = make_str("uncommitted"); }
| UNENCRYPTED { $$ = make_str("unencrypted"); }
| UNKNOWN { $$ = make_str("unknown"); }
| UNLISTEN { $$ = make_str("unlisten"); }
| UNTIL { $$ = make_str("until"); }
| UPDATE { $$ = make_str("update"); }
| VACUUM { $$ = make_str("vacuum"); }
| VALID { $$ = make_str("valid"); }
| VALIDATOR { $$ = make_str("validator"); }
| VALUE_P { $$ = make_str("value"); }
| VARYING { $$ = make_str("varying"); }
| VERSION_P { $$ = make_str("version"); }
| VIEW { $$ = make_str("view"); }
| VOLATILE { $$ = make_str("volatile"); }
| WHITESPACE_P { $$ = make_str("whitespace"); }
| WITHOUT { $$ = make_str("without"); }
| WORK { $$ = make_str("work"); }
| WRITE { $$ = make_str("write"); }
| XML_P { $$ = make_str("xml"); }
| YES_P { $$ = make_str("yes"); }
/* | YEAR_P { $$ = make_str("year"); }*/
| ZONE { $$ = make_str("zone"); }
;
into_list : coutputvariable | into_list ',' coutputvariable
;
ecpgstart: SQL_START {
reset_variables();
pacounter = 1;
}
;
c_args: /*EMPTY*/ { $$ = EMPTY; }
| c_list { $$ = $1; }
;
coutputvariable: cvariable indicator
{ add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); }
| cvariable
{ add_variable_to_head(&argsresult, find_variable($1), &no_indicator); }
;
civarind: cvariable indicator
{
if (find_variable($2)->type->type == ECPGt_array)
mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
add_variable_to_head(&argsinsert, find_variable($1), find_variable($2));
$$ = create_questionmarks($1, false);
}
;
civar: cvariable
{
add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
$$ = create_questionmarks($1, false);
}
;
indicator: cvariable { check_indicator((find_variable($1))->type); $$ = $1; }
| SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; }
| SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; }
;
cvariable: CVARIABLE
{
/* As long as multidimensional arrays are not implemented we have to check for those here */
char *ptr = $1;
int brace_open=0, brace = false;
for (; *ptr; ptr++)
{
switch (*ptr)
{
case '[':
if (brace)
mmerror(PARSE_ERROR, ET_FATAL, "no multidimensional array support for simple data types");
brace_open++;
break;
case ']':
brace_open--;
if (brace_open == 0)
brace = true;
break;
case '\t':
case ' ':
break;
default:
if (brace_open == 0)
brace = false;
break;
}
}
$$ = $1;
}
;
ecpg_param: PARAM { $$ = make_name(); } ;
ecpg_bconst: BCONST { $$ = make_name(); } ;
ecpg_fconst: FCONST { $$ = make_name(); } ;
ecpg_sconst:
SCONST
{
/* could have been input as '' or $$ */
$$ = (char *)mm_alloc(strlen($1) + 3);
$$[0]='\'';
strcpy($$+1, $1);
$$[strlen($1)+1]='\'';
$$[strlen($1)+2]='\0';
free($1);
}
| ECONST
{
$$ = (char *)mm_alloc(strlen($1) + 4);
$$[0]='E';
$$[1]='\'';
strcpy($$+2, $1);
$$[strlen($1)+2]='\'';
$$[strlen($1)+3]='\0';
free($1);
}
| NCONST
{
$$ = (char *)mm_alloc(strlen($1) + 4);
$$[0]='N';
$$[1]='\'';
strcpy($$+2, $1);
$$[strlen($1)+2]='\'';
$$[strlen($1)+3]='\0';
free($1);
}
| UCONST { $$ = $1; }
| DOLCONST { $$ = $1; }
;
ecpg_xconst: XCONST { $$ = make_name(); } ;
ecpg_ident: IDENT { $$ = make_name(); }
| CSTRING { $$ = make3_str(make_str("\""), $1, make_str("\"")) }
| UIDENT { $$ = $1; }
;
quoted_ident_stringvar: name
{ $$ = make3_str(make_str("\""), $1, make_str("\"")); }
| char_variable
{ $$ = make3_str(make_str("("), $1, make_str(")")); }
;
/*
* C stuff
*/
c_stuff_item: c_anything { $$ = $1; }
| '(' ')' { $$ = make_str("()"); }
| '(' c_stuff ')'
{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
;
c_stuff: c_stuff_item { $$ = $1; }
| c_stuff c_stuff_item
{ $$ = cat2_str($1, $2); }
;
c_list: c_term { $$ = $1; }
| c_list ',' c_term { $$ = cat_str(3, $1, make_str(","), $3); }
;
c_term: c_stuff { $$ = $1; }
| '{' c_list '}' { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
;
c_thing: c_anything { $$ = $1; }
| '(' { $$ = make_str("("); }
| ')' { $$ = make_str(")"); }
| ',' { $$ = make_str(","); }
| ';' { $$ = make_str(";"); }
;
c_anything: ecpg_ident { $$ = $1; }
| Iconst { $$ = $1; }
| ecpg_fconst { $$ = $1; }
| ecpg_sconst { $$ = $1; }
| '*' { $$ = make_str("*"); }
| '+' { $$ = make_str("+"); }
| '-' { $$ = make_str("-"); }
| '/' { $$ = make_str("/"); }
| '%' { $$ = make_str("%"); }
| NULL_P { $$ = make_str("NULL"); }
| S_ADD { $$ = make_str("+="); }
| S_AND { $$ = make_str("&&"); }
| S_ANYTHING { $$ = make_name(); }
| S_AUTO { $$ = make_str("auto"); }
| S_CONST { $$ = make_str("const"); }
| S_DEC { $$ = make_str("--"); }
| S_DIV { $$ = make_str("/="); }
| S_DOTPOINT { $$ = make_str(".*"); }
| S_EQUAL { $$ = make_str("=="); }
| S_EXTERN { $$ = make_str("extern"); }
| S_INC { $$ = make_str("++"); }
| S_LSHIFT { $$ = make_str("<<"); }
| S_MEMBER { $$ = make_str("->"); }
| S_MEMPOINT { $$ = make_str("->*"); }
| S_MOD { $$ = make_str("%="); }
| S_MUL { $$ = make_str("*="); }
| S_NEQUAL { $$ = make_str("!="); }
| S_OR { $$ = make_str("||"); }
| S_REGISTER { $$ = make_str("register"); }
| S_RSHIFT { $$ = make_str(">>"); }
| S_STATIC { $$ = make_str("static"); }
| S_SUB { $$ = make_str("-="); }
| S_TYPEDEF { $$ = make_str("typedef"); }
| S_VOLATILE { $$ = make_str("volatile"); }
| SQL_BOOL { $$ = make_str("bool"); }
| ENUM_P { $$ = make_str("enum"); }
| HOUR_P { $$ = make_str("hour"); }
| INT_P { $$ = make_str("int"); }
| SQL_LONG { $$ = make_str("long"); }
| MINUTE_P { $$ = make_str("minute"); }
| MONTH_P { $$ = make_str("month"); }
| SECOND_P { $$ = make_str("second"); }
| SQL_SHORT { $$ = make_str("short"); }
| SQL_SIGNED { $$ = make_str("signed"); }
| SQL_STRUCT { $$ = make_str("struct"); }
| SQL_UNSIGNED { $$ = make_str("unsigned"); }
| YEAR_P { $$ = make_str("year"); }
| CHAR_P { $$ = make_str("char"); }
| FLOAT_P { $$ = make_str("float"); }
| TO { $$ = make_str("to"); }
| UNION { $$ = make_str("union"); }
| VARCHAR { $$ = make_str("varchar"); }
| '[' { $$ = make_str("["); }
| ']' { $$ = make_str("]"); }
| '=' { $$ = make_str("="); }
| ':' { $$ = make_str(":"); }
;
DeallocateStmt: DEALLOCATE prepared_name { $$ = $2; }
| DEALLOCATE PREPARE prepared_name { $$ = $3; }
| DEALLOCATE ALL { $$ = make_str("all"); }
| DEALLOCATE PREPARE ALL { $$ = make_str("all"); }
;
Iresult: Iconst { $$ = $1; }
| '(' Iresult ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
| Iresult '+' Iresult { $$ = cat_str(3, $1, make_str("+"), $3); }
| Iresult '-' Iresult { $$ = cat_str(3, $1, make_str("-"), $3); }
| Iresult '*' Iresult { $$ = cat_str(3, $1, make_str("*"), $3); }
| Iresult '/' Iresult { $$ = cat_str(3, $1, make_str("/"), $3); }
| Iresult '%' Iresult { $$ = cat_str(3, $1, make_str("%"), $3); }
| ecpg_sconst { $$ = $1; }
| ColId { $$ = $1; }
;
execute_rest: /* EMPTY */ { $$ = EMPTY; }
| ecpg_using ecpg_into { $$ = EMPTY; }
| ecpg_into ecpg_using { $$ = EMPTY; }
| ecpg_using { $$ = EMPTY; }
| ecpg_into { $$ = EMPTY; }
;
ecpg_into: INTO into_list { $$ = EMPTY; }
| into_descriptor { $$ = $1; }
;
%%
void base_yyerror(const char * error)
{
char buf[1024];
snprintf(buf,sizeof buf, _("%s at or near \"%s\""), error, token_start ? token_start : yytext);
buf[sizeof(buf)-1]=0;
mmerror(PARSE_ERROR, ET_ERROR, buf);
}
void parser_init(void)
{
/* This function is empty. It only exists for compatibility with the backend parser right now. */
}
/*
* Must undefine base_yylex before including pgc.c, since we want it
* to create the function base_yylex not filtered_base_yylex.
*/
#undef base_yylex
#include "pgc.c"
/* $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
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