diff options
Diffstat (limited to 'src/backend/tcop/pquery.c')
-rw-r--r-- | src/backend/tcop/pquery.c | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c new file mode 100644 index 00000000000..cbe6c6d0ab5 --- /dev/null +++ b/src/backend/tcop/pquery.c @@ -0,0 +1,362 @@ +/*------------------------------------------------------------------------- + * + * pquery.c-- + * POSTGRES process query command code + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.1.1.1 1996/07/09 06:22:00 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "tcop/tcopdebug.h" + +#include "utils/elog.h" +#include "utils/palloc.h" +#include "utils/mcxt.h" +#include "miscadmin.h" +#include "utils/portal.h" + +#include "nodes/pg_list.h" +#include "nodes/primnodes.h" +#include "nodes/plannodes.h" +#include "nodes/execnodes.h" +#include "nodes/memnodes.h" + +#include "tcop/dest.h" + +#include "executor/execdefs.h" +#include "executor/execdesc.h" +#include "executor/executor.h" +#include "tcop/pquery.h" + +#include "commands/command.h" + +static char* CreateOperationTag(int operationType); + +/* ---------------------------------------------------------------- + * CreateQueryDesc + * ---------------------------------------------------------------- + */ +QueryDesc * +CreateQueryDesc(Query *parsetree, + Plan *plantree, + CommandDest dest) +{ + QueryDesc *qd = (QueryDesc *)palloc(sizeof(QueryDesc)); + + qd->operation = parsetree->commandType; /* operation */ + qd->parsetree = parsetree; /* parse tree */ + qd->plantree = plantree; /* plan */ + qd->dest = dest; /* output dest */ + return qd; +} + +/* ---------------------------------------------------------------- + * CreateExecutorState + * + * Note: this may someday take parameters -cim 9/18/89 + * ---------------------------------------------------------------- + */ +EState * +CreateExecutorState() +{ + EState *state; + extern int NBuffers; + long *refcount; + + /* ---------------- + * create a new executor state + * ---------------- + */ + state = makeNode(EState); + + /* ---------------- + * initialize the Executor State structure + * ---------------- + */ + state->es_direction = EXEC_FRWD; + state->es_range_table = NIL; + + state->es_into_relation_descriptor = NULL; + state->es_result_relation_info = NULL; + + state->es_param_list_info = NULL; + + state->es_BaseId = 0; + state->es_tupleTable = NULL; + + state->es_junkFilter = NULL; + + refcount = (long *) palloc(NBuffers * sizeof(long)); + memset((char *) refcount, 0, NBuffers * sizeof(long)); + state->es_refcount = (int *) refcount; + + /* ---------------- + * return the executor state structure + * ---------------- + */ + return state; +} + +/* ---------------------------------------------------------------- + * CreateOperationTag + * + * utility to get a string representation of the + * query operation. + * ---------------------------------------------------------------- + */ +static char* +CreateOperationTag(int operationType) +{ + char* tag; + + switch (operationType) { + case CMD_SELECT: + tag = "SELECT"; + break; + case CMD_INSERT: + tag = "INSERT"; + break; + case CMD_DELETE: + tag = "DELETE"; + break; + case CMD_UPDATE: + tag = "UPDATE"; + break; + default: + elog(DEBUG, "CreateOperationTag: unknown operation type %d", + operationType); + tag = NULL; + break; + } + + return tag; +} + +/* ---------------- + * ProcessPortal + * ---------------- + */ + +void +ProcessPortal(char* portalName, + Query *parseTree, + Plan *plan, + EState *state, + TupleDesc attinfo, + CommandDest dest) +{ + Portal portal; + MemoryContext portalContext; + + /* ---------------- + * convert the current blank portal into the user-specified + * portal and initialize the state and query descriptor. + * ---------------- + */ + + if (PortalNameIsSpecial(portalName)) + elog(WARN, + "The portal name %s is reserved for internal use", + portalName); + + portal = BlankPortalAssignName(portalName); + + PortalSetQuery(portal, + CreateQueryDesc(parseTree, plan, dest), + attinfo, + state, + PortalCleanup); + + /* ---------------- + * now create a new blank portal and switch to it. + * Otherwise, the new named portal will be cleaned. + * + * Note: portals will only be supported within a BEGIN...END + * block in the near future. Later, someone will fix it to + * do what is possible across transaction boundries. -hirohama + * ---------------- + */ + portalContext = (MemoryContext) + PortalGetHeapMemory(GetPortalByName(NULL)); + + MemoryContextSwitchTo(portalContext); + + StartPortalAllocMode(DefaultAllocMode, 0); +} + + +/* ---------------------------------------------------------------- + * ProcessQueryDesc + * + * Read the comments for ProcessQuery() below... + * ---------------------------------------------------------------- + */ +void +ProcessQueryDesc(QueryDesc *queryDesc) +{ + Query *parseTree; + Plan *plan; + int operation; + char* tag; + EState *state; + TupleDesc attinfo; + + bool isRetrieveIntoPortal; + bool isRetrieveIntoRelation; + char* intoName; + CommandDest dest; + + /* ---------------- + * get info from the query desc + * ---------------- + */ + parseTree = queryDesc->parsetree; + plan = queryDesc->plantree; + + operation = queryDesc->operation; + tag = CreateOperationTag(operation); + dest = queryDesc->dest; + + /* ---------------- + * initialize portal/into relation status + * ---------------- + */ + isRetrieveIntoPortal = false; + isRetrieveIntoRelation = false; + + if (operation == CMD_SELECT) { + if (parseTree->isPortal) { + isRetrieveIntoPortal = true; + intoName = parseTree->into; + if (parseTree->isBinary) { + /* + * For internal format portals, we change Remote + * (externalized form) to RemoteInternal (internalized + * form) + */ + dest = queryDesc->dest = RemoteInternal; + } + } else if (parseTree->into != NULL) { + /* select into table */ + isRetrieveIntoRelation = true; + } + + } + + /* ---------------- + * when performing a retrieve into, we override the normal + * communication destination during the processing of the + * the query. This only affects the tuple-output function + * - the correct destination will still see BeginCommand() + * and EndCommand() messages. + * ---------------- + */ + if (isRetrieveIntoRelation) + queryDesc->dest = (int) None; + + /* ---------------- + * create a default executor state.. + * ---------------- + */ + state = CreateExecutorState(); + + /* ---------------- + * call ExecStart to prepare the plan for execution + * ---------------- + */ + attinfo = ExecutorStart(queryDesc, state); + + /* ---------------- + * report the query's result type information + * back to the front end or to whatever destination + * we're dealing with. + * ---------------- + */ + BeginCommand(NULL, + operation, + attinfo, + isRetrieveIntoRelation, + isRetrieveIntoPortal, + tag, + dest); + + /* ---------------- + * Named portals do not do a "fetch all" initially, so now + * we return since ExecMain has been called with EXEC_START + * to initialize the query plan. + * + * Note: ProcessPortal transforms the current "blank" portal + * into a named portal and creates a new blank portal so + * everything we allocated in the current "blank" memory + * context will be preserved across queries. -cim 2/22/91 + * ---------------- + */ + if (isRetrieveIntoPortal) { + PortalExecutorHeapMemory = NULL; + + ProcessPortal(intoName, + parseTree, + plan, + state, + attinfo, + dest); + + EndCommand(tag, dest); + return; + } + + /* ---------------- + * Now we get to the important call to ExecutorRun() where we + * actually run the plan.. + * ---------------- + */ + ExecutorRun(queryDesc, state, EXEC_RUN, 0); + + /* ---------------- + * now, we close down all the scans and free allocated resources... + * with ExecutorEnd() + * ---------------- + */ + ExecutorEnd(queryDesc, state); + + /* ---------------- + * Notify the destination of end of processing. + * ---------------- + */ + EndCommand(tag, dest); +} + +/* ---------------------------------------------------------------- + * ProcessQuery + * + * Execute a plan, the non-parallel version + * ---------------------------------------------------------------- + */ + +void +ProcessQuery(Query *parsetree, + Plan *plan, + char *argv[], + Oid *typev, + int nargs, + CommandDest dest) +{ + QueryDesc *queryDesc; + extern int dontExecute; /* from postgres.c */ + extern void print_plan (Plan* p, Query* parsetree); /* from print.c */ + + queryDesc = CreateQueryDesc(parsetree, plan, dest); + + if (dontExecute) { + /* don't execute it, just show the query plan */ + print_plan(plan, parsetree); + } else + ProcessQueryDesc(queryDesc); +} + |