Make SPI's execution of querystrings follow the rules agreed to for
command status at the interactive level. SPI_processed, etc are set in the same way as the returned command status would have been set if the same querystring were issued interactively. Per gripe from Michael Paesold 25-Sep-02.
This commit is contained in:
parent
ba0edcf451
commit
9ff695c944
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.74 2002/09/04 20:31:18 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.75 2002/10/14 23:49:20 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -88,7 +88,6 @@ SPI_connect(void)
|
||||||
_SPI_connected++;
|
_SPI_connected++;
|
||||||
|
|
||||||
_SPI_current = &(_SPI_stack[_SPI_connected]);
|
_SPI_current = &(_SPI_stack[_SPI_connected]);
|
||||||
_SPI_current->qtlist = NULL;
|
|
||||||
_SPI_current->processed = 0;
|
_SPI_current->processed = 0;
|
||||||
_SPI_current->tuptable = NULL;
|
_SPI_current->tuptable = NULL;
|
||||||
|
|
||||||
|
@ -258,7 +257,6 @@ SPI_prepare(char *src, int nargs, Oid *argtypes)
|
||||||
_SPI_end_call(true);
|
_SPI_end_call(true);
|
||||||
|
|
||||||
return (void *) plan;
|
return (void *) plan;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
@ -716,9 +714,9 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
/* Ensure that the plan contains only one regular SELECT query */
|
/* Ensure that the plan contains only one regular SELECT query */
|
||||||
if (length(ptlist) != 1)
|
if (length(ptlist) != 1 || length(qtlist) != 1)
|
||||||
elog(ERROR, "cannot open multi-query plan as cursor");
|
elog(ERROR, "cannot open multi-query plan as cursor");
|
||||||
queryTree = (Query *) lfirst(qtlist);
|
queryTree = (Query *) lfirst((List *) lfirst(qtlist));
|
||||||
planTree = (Plan *) lfirst(ptlist);
|
planTree = (Plan *) lfirst(ptlist);
|
||||||
|
|
||||||
if (queryTree->commandType != CMD_SELECT)
|
if (queryTree->commandType != CMD_SELECT)
|
||||||
|
@ -948,29 +946,22 @@ spi_printtup(HeapTuple tuple, TupleDesc tupdesc, DestReceiver *self)
|
||||||
* Static functions
|
* Static functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Plan and optionally execute a querystring.
|
||||||
|
*
|
||||||
|
* If plan != NULL, just prepare plan tree, else execute immediately.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
_SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
_SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
||||||
{
|
{
|
||||||
List *queryTree_list;
|
StringInfoData stri;
|
||||||
List *planTree_list;
|
List *raw_parsetree_list;
|
||||||
List *queryTree_list_item;
|
List *query_list_list;
|
||||||
QueryDesc *qdesc;
|
List *plan_list;
|
||||||
Query *queryTree;
|
List *list_item;
|
||||||
Plan *planTree;
|
|
||||||
EState *state;
|
|
||||||
int nargs = 0;
|
int nargs = 0;
|
||||||
Oid *argtypes = NULL;
|
Oid *argtypes = NULL;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
bool islastquery;
|
|
||||||
|
|
||||||
/* Increment CommandCounter to see changes made by now */
|
|
||||||
CommandCounterIncrement();
|
|
||||||
|
|
||||||
SPI_processed = 0;
|
|
||||||
SPI_lastoid = InvalidOid;
|
|
||||||
SPI_tuptable = NULL;
|
|
||||||
_SPI_current->tuptable = NULL;
|
|
||||||
_SPI_current->qtlist = NULL;
|
|
||||||
|
|
||||||
if (plan)
|
if (plan)
|
||||||
{
|
{
|
||||||
|
@ -978,72 +969,149 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
||||||
argtypes = plan->argtypes;
|
argtypes = plan->argtypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
queryTree_list = pg_parse_and_rewrite(src, argtypes, nargs);
|
/* Increment CommandCounter to see changes made by now */
|
||||||
|
CommandCounterIncrement();
|
||||||
|
|
||||||
_SPI_current->qtlist = queryTree_list;
|
/* Reset state (only needed in case string is empty) */
|
||||||
|
SPI_processed = 0;
|
||||||
|
SPI_lastoid = InvalidOid;
|
||||||
|
SPI_tuptable = NULL;
|
||||||
|
_SPI_current->tuptable = NULL;
|
||||||
|
|
||||||
planTree_list = NIL;
|
/*
|
||||||
|
* Parse the request string into a list of raw parse trees.
|
||||||
|
*/
|
||||||
|
initStringInfo(&stri);
|
||||||
|
appendStringInfo(&stri, "%s", src);
|
||||||
|
|
||||||
foreach(queryTree_list_item, queryTree_list)
|
raw_parsetree_list = pg_parse_query(&stri, argtypes, nargs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do parse analysis and rule rewrite for each raw parsetree.
|
||||||
|
*
|
||||||
|
* We save the querytrees from each raw parsetree as a separate
|
||||||
|
* sublist. This allows _SPI_execute_plan() to know where the
|
||||||
|
* boundaries between original queries fall.
|
||||||
|
*/
|
||||||
|
query_list_list = NIL;
|
||||||
|
plan_list = NIL;
|
||||||
|
|
||||||
|
foreach(list_item, raw_parsetree_list)
|
||||||
{
|
{
|
||||||
queryTree = (Query *) lfirst(queryTree_list_item);
|
Node *parsetree = (Node *) lfirst(list_item);
|
||||||
islastquery = (lnext(queryTree_list_item) == NIL);
|
CmdType origCmdType;
|
||||||
|
bool foundOriginalQuery = false;
|
||||||
|
List *query_list;
|
||||||
|
List *query_list_item;
|
||||||
|
|
||||||
|
switch (nodeTag(parsetree))
|
||||||
|
{
|
||||||
|
case T_InsertStmt:
|
||||||
|
origCmdType = CMD_INSERT;
|
||||||
|
break;
|
||||||
|
case T_DeleteStmt:
|
||||||
|
origCmdType = CMD_DELETE;
|
||||||
|
break;
|
||||||
|
case T_UpdateStmt:
|
||||||
|
origCmdType = CMD_UPDATE;
|
||||||
|
break;
|
||||||
|
case T_SelectStmt:
|
||||||
|
origCmdType = CMD_SELECT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Otherwise, never match commandType */
|
||||||
|
origCmdType = CMD_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plan)
|
||||||
|
plan->origCmdType = origCmdType;
|
||||||
|
|
||||||
|
query_list = pg_analyze_and_rewrite(parsetree);
|
||||||
|
|
||||||
|
query_list_list = lappend(query_list_list, query_list);
|
||||||
|
|
||||||
|
/* Reset state for each original parsetree */
|
||||||
|
SPI_processed = 0;
|
||||||
|
SPI_lastoid = InvalidOid;
|
||||||
|
SPI_tuptable = NULL;
|
||||||
|
_SPI_current->tuptable = NULL;
|
||||||
|
|
||||||
|
foreach(query_list_item, query_list)
|
||||||
|
{
|
||||||
|
Query *queryTree = (Query *) lfirst(query_list_item);
|
||||||
|
Plan *planTree;
|
||||||
|
bool canSetResult;
|
||||||
|
QueryDesc *qdesc;
|
||||||
|
EState *state;
|
||||||
|
|
||||||
planTree = pg_plan_query(queryTree);
|
planTree = pg_plan_query(queryTree);
|
||||||
planTree_list = lappend(planTree_list, planTree);
|
plan_list = lappend(plan_list, planTree);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This query can set the SPI result if it is the original
|
||||||
|
* query, or if it is an INSTEAD query of the same kind as the
|
||||||
|
* original and we haven't yet seen the original query.
|
||||||
|
*/
|
||||||
|
if (queryTree->querySource == QSRC_ORIGINAL)
|
||||||
|
{
|
||||||
|
canSetResult = true;
|
||||||
|
foundOriginalQuery = true;
|
||||||
|
}
|
||||||
|
else if (!foundOriginalQuery &&
|
||||||
|
queryTree->commandType == origCmdType &&
|
||||||
|
(queryTree->querySource == QSRC_INSTEAD_RULE ||
|
||||||
|
queryTree->querySource == QSRC_QUAL_INSTEAD_RULE))
|
||||||
|
canSetResult = true;
|
||||||
|
else
|
||||||
|
canSetResult = false;
|
||||||
|
|
||||||
if (queryTree->commandType == CMD_UTILITY)
|
if (queryTree->commandType == CMD_UTILITY)
|
||||||
{
|
{
|
||||||
if (nodeTag(queryTree->utilityStmt) == T_CopyStmt)
|
if (IsA(queryTree->utilityStmt, CopyStmt))
|
||||||
{
|
{
|
||||||
CopyStmt *stmt = (CopyStmt *) (queryTree->utilityStmt);
|
CopyStmt *stmt = (CopyStmt *) queryTree->utilityStmt;
|
||||||
|
|
||||||
if (stmt->filename == NULL)
|
if (stmt->filename == NULL)
|
||||||
return SPI_ERROR_COPY;
|
return SPI_ERROR_COPY;
|
||||||
}
|
}
|
||||||
else if (nodeTag(queryTree->utilityStmt) == T_ClosePortalStmt ||
|
else if (IsA(queryTree->utilityStmt, ClosePortalStmt) ||
|
||||||
nodeTag(queryTree->utilityStmt) == T_FetchStmt)
|
IsA(queryTree->utilityStmt, FetchStmt))
|
||||||
return SPI_ERROR_CURSOR;
|
return SPI_ERROR_CURSOR;
|
||||||
else if (nodeTag(queryTree->utilityStmt) == T_TransactionStmt)
|
else if (IsA(queryTree->utilityStmt, TransactionStmt))
|
||||||
return SPI_ERROR_TRANSACTION;
|
return SPI_ERROR_TRANSACTION;
|
||||||
res = SPI_OK_UTILITY;
|
res = SPI_OK_UTILITY;
|
||||||
if (plan == NULL)
|
if (plan == NULL)
|
||||||
{
|
{
|
||||||
ProcessUtility(queryTree->utilityStmt, None, NULL);
|
ProcessUtility(queryTree->utilityStmt, None, NULL);
|
||||||
if (!islastquery)
|
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
else
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
else if (islastquery)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if (plan == NULL)
|
else if (plan == NULL)
|
||||||
{
|
{
|
||||||
qdesc = CreateQueryDesc(queryTree, planTree,
|
qdesc = CreateQueryDesc(queryTree, planTree,
|
||||||
islastquery ? SPI : None, NULL);
|
canSetResult ? SPI : None, NULL);
|
||||||
state = CreateExecutorState();
|
state = CreateExecutorState();
|
||||||
res = _SPI_pquery(qdesc, state, islastquery ? tcount : 0);
|
res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0);
|
||||||
if (res < 0 || islastquery)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qdesc = CreateQueryDesc(queryTree, planTree,
|
qdesc = CreateQueryDesc(queryTree, planTree,
|
||||||
islastquery ? SPI : None, NULL);
|
canSetResult ? SPI : None, NULL);
|
||||||
res = _SPI_pquery(qdesc, NULL, islastquery ? tcount : 0);
|
res = _SPI_pquery(qdesc, NULL, 0);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
if (islastquery)
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plan)
|
if (plan)
|
||||||
{
|
{
|
||||||
plan->qtlist = queryTree_list;
|
plan->qtlist = query_list_list;
|
||||||
plan->ptlist = planTree_list;
|
plan->ptlist = plan_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -1052,55 +1120,82 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
||||||
static int
|
static int
|
||||||
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
|
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
|
||||||
{
|
{
|
||||||
List *queryTree_list = plan->qtlist;
|
List *query_list_list = plan->qtlist;
|
||||||
List *planTree_list = plan->ptlist;
|
List *plan_list = plan->ptlist;
|
||||||
List *queryTree_list_item;
|
List *query_list_list_item;
|
||||||
QueryDesc *qdesc;
|
|
||||||
Query *queryTree;
|
|
||||||
Plan *planTree;
|
|
||||||
EState *state;
|
|
||||||
int nargs = plan->nargs;
|
int nargs = plan->nargs;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
bool islastquery;
|
|
||||||
int k;
|
|
||||||
|
|
||||||
/* Increment CommandCounter to see changes made by now */
|
/* Increment CommandCounter to see changes made by now */
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
|
|
||||||
|
/* Reset state (only needed in case string is empty) */
|
||||||
SPI_processed = 0;
|
SPI_processed = 0;
|
||||||
SPI_lastoid = InvalidOid;
|
SPI_lastoid = InvalidOid;
|
||||||
SPI_tuptable = NULL;
|
SPI_tuptable = NULL;
|
||||||
_SPI_current->tuptable = NULL;
|
_SPI_current->tuptable = NULL;
|
||||||
_SPI_current->qtlist = NULL;
|
|
||||||
|
|
||||||
foreach(queryTree_list_item, queryTree_list)
|
foreach(query_list_list_item, query_list_list)
|
||||||
{
|
{
|
||||||
queryTree = (Query *) lfirst(queryTree_list_item);
|
List *query_list = lfirst(query_list_list_item);
|
||||||
planTree = lfirst(planTree_list);
|
List *query_list_item;
|
||||||
planTree_list = lnext(planTree_list);
|
bool foundOriginalQuery = false;
|
||||||
islastquery = (planTree_list == NIL); /* assume lists are same
|
|
||||||
* len */
|
/* Reset state for each original parsetree */
|
||||||
|
SPI_processed = 0;
|
||||||
|
SPI_lastoid = InvalidOid;
|
||||||
|
SPI_tuptable = NULL;
|
||||||
|
_SPI_current->tuptable = NULL;
|
||||||
|
|
||||||
|
foreach(query_list_item, query_list)
|
||||||
|
{
|
||||||
|
Query *queryTree = (Query *) lfirst(query_list_item);
|
||||||
|
Plan *planTree;
|
||||||
|
bool canSetResult;
|
||||||
|
QueryDesc *qdesc;
|
||||||
|
EState *state;
|
||||||
|
|
||||||
|
planTree = lfirst(plan_list);
|
||||||
|
plan_list = lnext(plan_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This query can set the SPI result if it is the original
|
||||||
|
* query, or if it is an INSTEAD query of the same kind as the
|
||||||
|
* original and we haven't yet seen the original query.
|
||||||
|
*/
|
||||||
|
if (queryTree->querySource == QSRC_ORIGINAL)
|
||||||
|
{
|
||||||
|
canSetResult = true;
|
||||||
|
foundOriginalQuery = true;
|
||||||
|
}
|
||||||
|
else if (!foundOriginalQuery &&
|
||||||
|
queryTree->commandType == plan->origCmdType &&
|
||||||
|
(queryTree->querySource == QSRC_INSTEAD_RULE ||
|
||||||
|
queryTree->querySource == QSRC_QUAL_INSTEAD_RULE))
|
||||||
|
canSetResult = true;
|
||||||
|
else
|
||||||
|
canSetResult = false;
|
||||||
|
|
||||||
if (queryTree->commandType == CMD_UTILITY)
|
if (queryTree->commandType == CMD_UTILITY)
|
||||||
{
|
{
|
||||||
|
res = SPI_OK_UTILITY;
|
||||||
ProcessUtility(queryTree->utilityStmt, None, NULL);
|
ProcessUtility(queryTree->utilityStmt, None, NULL);
|
||||||
if (!islastquery)
|
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
else
|
|
||||||
return SPI_OK_UTILITY;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qdesc = CreateQueryDesc(queryTree, planTree,
|
qdesc = CreateQueryDesc(queryTree, planTree,
|
||||||
islastquery ? SPI : None, NULL);
|
canSetResult ? SPI : None, NULL);
|
||||||
state = CreateExecutorState();
|
state = CreateExecutorState();
|
||||||
if (nargs > 0)
|
if (nargs > 0)
|
||||||
{
|
{
|
||||||
ParamListInfo paramLI;
|
ParamListInfo paramLI;
|
||||||
|
int k;
|
||||||
|
|
||||||
paramLI = (ParamListInfo) palloc((nargs + 1) *
|
paramLI = (ParamListInfo)
|
||||||
sizeof(ParamListInfoData));
|
palloc((nargs + 1) * sizeof(ParamListInfoData));
|
||||||
MemSet(paramLI, 0, (nargs + 1) * sizeof(ParamListInfoData));
|
MemSet(paramLI, 0,
|
||||||
|
(nargs + 1) * sizeof(ParamListInfoData));
|
||||||
|
|
||||||
state->es_param_list_info = paramLI;
|
state->es_param_list_info = paramLI;
|
||||||
for (k = 0; k < plan->nargs; paramLI++, k++)
|
for (k = 0; k < plan->nargs; paramLI++, k++)
|
||||||
|
@ -1114,12 +1209,13 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state->es_param_list_info = NULL;
|
state->es_param_list_info = NULL;
|
||||||
res = _SPI_pquery(qdesc, state, islastquery ? tcount : 0);
|
res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0);
|
||||||
if (res < 0 || islastquery)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1169,7 +1265,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
|
||||||
return SPI_ERROR_OPUNKNOWN;
|
return SPI_ERROR_OPUNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == NULL) /* plan preparation */
|
if (state == NULL) /* plan preparation, don't execute */
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
#ifdef SPI_EXECUTOR_STATS
|
#ifdef SPI_EXECUTOR_STATS
|
||||||
|
@ -1340,12 +1436,10 @@ static int
|
||||||
_SPI_end_call(bool procmem)
|
_SPI_end_call(bool procmem)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We' returning to procedure where _SPI_curid == _SPI_connected - 1
|
* We're returning to procedure where _SPI_curid == _SPI_connected - 1
|
||||||
*/
|
*/
|
||||||
_SPI_curid--;
|
_SPI_curid--;
|
||||||
|
|
||||||
_SPI_current->qtlist = NULL;
|
|
||||||
|
|
||||||
if (procmem) /* switch to the procedure memory context */
|
if (procmem) /* switch to the procedure memory context */
|
||||||
{
|
{
|
||||||
_SPI_procmem();
|
_SPI_procmem();
|
||||||
|
@ -1420,6 +1514,7 @@ _SPI_copy_plan(_SPI_plan *plan, int location)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
newplan->argtypes = NULL;
|
newplan->argtypes = NULL;
|
||||||
|
newplan->origCmdType = plan->origCmdType;
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldcxt);
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.302 2002/10/14 22:14:35 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.303 2002/10/14 23:49:20 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* this is the "main" module of the postgres backend and
|
* this is the "main" module of the postgres backend and
|
||||||
|
@ -119,8 +119,6 @@ int XfuncMode = 0;
|
||||||
static int InteractiveBackend(StringInfo inBuf);
|
static int InteractiveBackend(StringInfo inBuf);
|
||||||
static int SocketBackend(StringInfo inBuf);
|
static int SocketBackend(StringInfo inBuf);
|
||||||
static int ReadCommand(StringInfo inBuf);
|
static int ReadCommand(StringInfo inBuf);
|
||||||
static List *pg_parse_query(StringInfo query_string, Oid *typev, int nargs);
|
|
||||||
static List *pg_analyze_and_rewrite(Node *parsetree);
|
|
||||||
static void start_xact_command(void);
|
static void start_xact_command(void);
|
||||||
static void finish_xact_command(bool forceCommit);
|
static void finish_xact_command(bool forceCommit);
|
||||||
static void SigHupHandler(SIGNAL_ARGS);
|
static void SigHupHandler(SIGNAL_ARGS);
|
||||||
|
@ -367,7 +365,7 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */
|
||||||
* we've seen a COMMIT or ABORT command; when we are in abort state, other
|
* we've seen a COMMIT or ABORT command; when we are in abort state, other
|
||||||
* commands are not processed any further than the raw parse stage.
|
* commands are not processed any further than the raw parse stage.
|
||||||
*/
|
*/
|
||||||
static List *
|
List *
|
||||||
pg_parse_query(StringInfo query_string, Oid *typev, int nargs)
|
pg_parse_query(StringInfo query_string, Oid *typev, int nargs)
|
||||||
{
|
{
|
||||||
List *raw_parsetree_list;
|
List *raw_parsetree_list;
|
||||||
|
@ -395,7 +393,7 @@ pg_parse_query(StringInfo query_string, Oid *typev, int nargs)
|
||||||
*
|
*
|
||||||
* NOTE: for reasons mentioned above, this must be separate from raw parsing.
|
* NOTE: for reasons mentioned above, this must be separate from raw parsing.
|
||||||
*/
|
*/
|
||||||
static List *
|
List *
|
||||||
pg_analyze_and_rewrite(Node *parsetree)
|
pg_analyze_and_rewrite(Node *parsetree)
|
||||||
{
|
{
|
||||||
List *querytree_list;
|
List *querytree_list;
|
||||||
|
@ -1769,7 +1767,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||||
if (!IsUnderPostmaster)
|
if (!IsUnderPostmaster)
|
||||||
{
|
{
|
||||||
puts("\nPOSTGRES backend interactive interface ");
|
puts("\nPOSTGRES backend interactive interface ");
|
||||||
puts("$Revision: 1.302 $ $Date: 2002/10/14 22:14:35 $\n");
|
puts("$Revision: 1.303 $ $Date: 2002/10/14 23:49:20 $\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* spi.c
|
* spi_priv.h
|
||||||
* Server Programming Interface private declarations
|
* Server Programming Interface private declarations
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/include/executor/spi_priv.h,v 1.12 2002/05/21 22:05:55 tgl Exp $
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
|
*
|
||||||
|
* $Id: spi_priv.h,v 1.13 2002/10/14 23:49:20 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -12,9 +15,9 @@
|
||||||
|
|
||||||
#include "executor/spi.h"
|
#include "executor/spi.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
List *qtlist;
|
|
||||||
uint32 processed; /* by Executor */
|
uint32 processed; /* by Executor */
|
||||||
SPITupleTable *tuptable;
|
SPITupleTable *tuptable;
|
||||||
MemoryContext procCxt; /* procedure context */
|
MemoryContext procCxt; /* procedure context */
|
||||||
|
@ -24,13 +27,20 @@ typedef struct
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
/* context containing _SPI_plan itself as well as subsidiary structures */
|
||||||
MemoryContext plancxt;
|
MemoryContext plancxt;
|
||||||
|
/* List of List of querytrees; one sublist per original parsetree */
|
||||||
List *qtlist;
|
List *qtlist;
|
||||||
|
/* List of plan trees --- length == # of querytrees, but flat list */
|
||||||
List *ptlist;
|
List *ptlist;
|
||||||
|
/* Argument types, if a prepared plan */
|
||||||
int nargs;
|
int nargs;
|
||||||
Oid *argtypes;
|
Oid *argtypes;
|
||||||
|
/* Command type of last original parsetree */
|
||||||
|
CmdType origCmdType;
|
||||||
} _SPI_plan;
|
} _SPI_plan;
|
||||||
|
|
||||||
|
|
||||||
#define _SPI_CPLAN_CURCXT 0
|
#define _SPI_CPLAN_CURCXT 0
|
||||||
#define _SPI_CPLAN_PROCXT 1
|
#define _SPI_CPLAN_PROCXT 1
|
||||||
#define _SPI_CPLAN_TOPCXT 2
|
#define _SPI_CPLAN_TOPCXT 2
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: tcopprot.h,v 1.49 2002/06/20 20:29:52 momjian Exp $
|
* $Id: tcopprot.h,v 1.50 2002/10/14 23:49:20 tgl Exp $
|
||||||
*
|
*
|
||||||
* OLD COMMENTS
|
* OLD COMMENTS
|
||||||
* This file was created so that other c files could get the two
|
* This file was created so that other c files could get the two
|
||||||
|
@ -35,12 +35,15 @@ extern bool ShowPortNumber;
|
||||||
|
|
||||||
#ifndef BOOTSTRAP_INCLUDE
|
#ifndef BOOTSTRAP_INCLUDE
|
||||||
|
|
||||||
|
extern List *pg_parse_query(StringInfo query_string, Oid *typev, int nargs);
|
||||||
|
extern List *pg_analyze_and_rewrite(Node *parsetree);
|
||||||
extern List *pg_parse_and_rewrite(char *query_string,
|
extern List *pg_parse_and_rewrite(char *query_string,
|
||||||
Oid *typev, int nargs);
|
Oid *typev, int nargs);
|
||||||
extern Plan *pg_plan_query(Query *querytree);
|
extern Plan *pg_plan_query(Query *querytree);
|
||||||
extern void pg_exec_query_string(StringInfo query_string,
|
extern void pg_exec_query_string(StringInfo query_string,
|
||||||
CommandDest dest,
|
CommandDest dest,
|
||||||
MemoryContext parse_context);
|
MemoryContext parse_context);
|
||||||
|
|
||||||
#endif /* BOOTSTRAP_INCLUDE */
|
#endif /* BOOTSTRAP_INCLUDE */
|
||||||
|
|
||||||
extern void die(SIGNAL_ARGS);
|
extern void die(SIGNAL_ARGS);
|
||||||
|
|
Loading…
Reference in New Issue