mirror of https://github.com/postgres/postgres
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
386 lines
11 KiB
386 lines
11 KiB
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.4.2.1 2009/11/27 16:11:50 meskes Exp $ */
|
|
|
|
ECPG: stmtClosePortalStmt block
|
|
{
|
|
if (INFORMIX_MODE)
|
|
{
|
|
if (pg_strcasecmp($1+strlen("close "), "database") == 0)
|
|
{
|
|
if (connection)
|
|
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in CLOSE DATABASE statement");
|
|
|
|
fprintf(yyout, "{ ECPGdisconnect(__LINE__, \"CURRENT\");");
|
|
whenever_action(2);
|
|
free($1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
output_statement($1, 0, ECPGst_normal);
|
|
}
|
|
ECPG: stmtDeallocateStmt block
|
|
{
|
|
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, "AT option not allowed in CONNECT statement");
|
|
|
|
fprintf(yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit);
|
|
reset_variables();
|
|
whenever_action(2);
|
|
free($1);
|
|
}
|
|
| ECPGCursorStmt
|
|
{
|
|
output_simple_statement($1);
|
|
}
|
|
| ECPGDeallocateDescr
|
|
{
|
|
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, "AT option not allowed in DISCONNECT statement");
|
|
|
|
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, "AT option not allowed in SET CONNECTION statement");
|
|
|
|
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, "AT option not allowed in TYPE statement");
|
|
|
|
fprintf(yyout, "%s", $1);
|
|
free($1);
|
|
output_line_number();
|
|
}
|
|
| ECPGVar
|
|
{
|
|
if (connection)
|
|
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in VAR statement");
|
|
|
|
output_simple_statement($1);
|
|
}
|
|
| ECPGWhenever
|
|
{
|
|
if (connection)
|
|
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in WHENEVER statement");
|
|
|
|
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 is not possible");
|
|
else if (strcmp($6, "from") == 0 && strcmp($7, "stdout") == 0)
|
|
mmerror(PARSE_ERROR, ET_ERROR, "COPY FROM STDOUT is not possible");
|
|
else if (strcmp($6, "from") == 0 && strcmp($7, "stdin") == 0)
|
|
mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented");
|
|
ECPG: CopyStmtCOPYselect_with_parensTOcopy_file_nameopt_withcopy_opt_list addon
|
|
if (strcmp($4, "stdin") == 0)
|
|
mmerror(PARSE_ERROR, ET_ERROR, "COPY TO STDIN is not possible");
|
|
ECPG: ConstraintAttributeSpecConstraintDeferrabilitySpecConstraintTimeSpec addon
|
|
if (strcmp($1, "deferrable") != 0 && strcmp($2, "initially deferrable") == 0 )
|
|
mmerror(PARSE_ERROR, ET_ERROR, "constraint declared INITIALLY DEFERRED must be DEFERRABLE");
|
|
ECPG: ConstraintAttributeSpecConstraintTimeSpecConstraintDeferrabilitySpec addon
|
|
if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
|
|
mmerror(PARSE_ERROR, ET_ERROR, "constraint declared INITIALLY DEFERRED must be DEFERRABLE");
|
|
ECPG: var_valueNumericOnly addon
|
|
ECPG: fetch_directionSignedIconst addon
|
|
if ($1[0] == '$')
|
|
{
|
|
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[0] == '$')
|
|
{
|
|
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;
|
|
char *c1, *c2;
|
|
|
|
for (ptr = cur; ptr != NULL; ptr = ptr->next)
|
|
{
|
|
if (strcmp($2, ptr->name) == 0)
|
|
mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", $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;
|
|
|
|
c1 = mm_strdup(this->command);
|
|
if ((c2 = strstr(c1, "*/")) != NULL)
|
|
{
|
|
/* We put this text into a comment, so we better remove [*][/]. */
|
|
c2[0] = '.';
|
|
c2[1] = '.';
|
|
}
|
|
|
|
if (INFORMIX_MODE)
|
|
$$ = cat_str(5, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), make_str("/*"), c1, make_str("*/"));
|
|
else
|
|
$$ = cat_str(3, make_str("/*"), c1, 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, "subquery in FROM must have an alias");
|
|
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 is not implemented");
|
|
$$ = 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 query that is not in a rule");
|
|
ECPG: SpecialRuleRelationNEW addon
|
|
if (!QueryIsRule)
|
|
mmerror(PARSE_ERROR, ET_ERROR, "NEW used in query that is not in a rule");
|
|
ECPG: select_limitLIMITselect_limit_value','select_offset_value block
|
|
{
|
|
mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server");
|
|
$$ = cat_str(4, make_str("limit"), $2, make_str(","), $4);
|
|
}
|
|
ECPG: SignedIconstIconst rule
|
|
| civar { $$ = $1; }
|
|
|