pquery.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:9k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * pquery.c
  4.  *   POSTGRES process query command code
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.23 1999/05/25 16:11:41 momjian Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <string.h>
  15. #include "postgres.h"
  16. #include "tcop/tcopdebug.h"
  17. #include "utils/palloc.h"
  18. #include "nodes/nodes.h"
  19. #include "utils/mcxt.h"
  20. #include "miscadmin.h"
  21. #include "utils/portal.h"
  22. #include "nodes/pg_list.h"
  23. #include "nodes/primnodes.h"
  24. #include "nodes/plannodes.h"
  25. #include "nodes/execnodes.h"
  26. #include "nodes/memnodes.h"
  27. #include "tcop/dest.h"
  28. #include "executor/execdefs.h"
  29. #include "executor/execdesc.h"
  30. #include "executor/executor.h"
  31. #include "tcop/pquery.h"
  32. #include "utils/ps_status.h"
  33. #include "commands/command.h"
  34. static char *CreateOperationTag(int operationType);
  35. static void ProcessQueryDesc(QueryDesc *queryDesc, Node *limoffset,
  36.  Node *limcount);
  37. /* ----------------------------------------------------------------
  38.  * CreateQueryDesc
  39.  * ----------------------------------------------------------------
  40.  */
  41. QueryDesc  *
  42. CreateQueryDesc(Query *parsetree,
  43. Plan *plantree,
  44. CommandDest dest)
  45. {
  46. QueryDesc  *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
  47. qd->operation = parsetree->commandType; /* operation */
  48. qd->parsetree = parsetree; /* parse tree */
  49. qd->plantree = plantree; /* plan */
  50. qd->dest = dest; /* output dest */
  51. return qd;
  52. }
  53. /* ----------------------------------------------------------------
  54.  * CreateExecutorState
  55.  *
  56.  * Note: this may someday take parameters -cim 9/18/89
  57.  * ----------------------------------------------------------------
  58.  */
  59. EState *
  60. CreateExecutorState(void)
  61. {
  62. EState    *state;
  63. extern int NBuffers;
  64. long    *refcount;
  65. /* ----------------
  66.  * create a new executor state
  67.  * ----------------
  68.  */
  69. state = makeNode(EState);
  70. /* ----------------
  71.  * initialize the Executor State structure
  72.  * ----------------
  73.  */
  74. state->es_direction = ForwardScanDirection;
  75. state->es_range_table = NIL;
  76. state->es_into_relation_descriptor = NULL;
  77. state->es_result_relation_info = NULL;
  78. state->es_param_list_info = NULL;
  79. state->es_param_exec_vals = NULL;
  80. state->es_BaseId = 0;
  81. state->es_tupleTable = NULL;
  82. state->es_junkFilter = NULL;
  83. refcount = (long *) palloc(NBuffers * sizeof(long));
  84. MemSet((char *) refcount, 0, NBuffers * sizeof(long));
  85. state->es_refcount = (int *) refcount;
  86. /* ----------------
  87.  * return the executor state structure
  88.  * ----------------
  89.  */
  90. return state;
  91. }
  92. /* ----------------------------------------------------------------
  93.  * CreateOperationTag
  94.  *
  95.  * utility to get a string representation of the
  96.  * query operation.
  97.  * ----------------------------------------------------------------
  98.  */
  99. static char *
  100. CreateOperationTag(int operationType)
  101. {
  102. char    *tag;
  103. switch (operationType)
  104. {
  105. case CMD_SELECT:
  106. tag = "SELECT";
  107. break;
  108. case CMD_INSERT:
  109. tag = "INSERT";
  110. break;
  111. case CMD_DELETE:
  112. tag = "DELETE";
  113. break;
  114. case CMD_UPDATE:
  115. tag = "UPDATE";
  116. break;
  117. default:
  118. elog(DEBUG, "CreateOperationTag: unknown operation type %d",
  119.  operationType);
  120. tag = NULL;
  121. break;
  122. }
  123. return tag;
  124. }
  125. /* ----------------
  126.  * ProcessPortal
  127.  * ----------------
  128.  */
  129. void
  130. ProcessPortal(char *portalName,
  131.   Query *parseTree,
  132.   Plan *plan,
  133.   EState *state,
  134.   TupleDesc attinfo,
  135.   CommandDest dest)
  136. {
  137. Portal portal;
  138. MemoryContext portalContext;
  139. /* ----------------
  140.  *  convert the current blank portal into the user-specified
  141.  *  portal and initialize the state and query descriptor.
  142.  * ----------------
  143.  */
  144. if (PortalNameIsSpecial(portalName))
  145. elog(ERROR,
  146.  "The portal name %s is reserved for internal use",
  147.  portalName);
  148. portal = BlankPortalAssignName(portalName);
  149. PortalSetQuery(portal,
  150.    CreateQueryDesc(parseTree, plan, dest),
  151.    attinfo,
  152.    state,
  153.    PortalCleanup);
  154. /* ----------------
  155.  * now create a new blank portal and switch to it.
  156.  * Otherwise, the new named portal will be cleaned.
  157.  *
  158.  * Note: portals will only be supported within a BEGIN...END
  159.  * block in the near future.  Later, someone will fix it to
  160.  * do what is possible across transaction boundries. -hirohama
  161.  * ----------------
  162.  */
  163. portalContext = (MemoryContext) PortalGetHeapMemory(GetPortalByName(NULL));
  164. MemoryContextSwitchTo(portalContext);
  165. StartPortalAllocMode(DefaultAllocMode, 0);
  166. }
  167. /* ----------------------------------------------------------------
  168.  * ProcessQueryDesc
  169.  *
  170.  * Read the comments for ProcessQuery() below...
  171.  * ----------------------------------------------------------------
  172.  */
  173. static void
  174. ProcessQueryDesc(QueryDesc *queryDesc, Node *limoffset, Node *limcount)
  175. {
  176. Query    *parseTree;
  177. Plan    *plan;
  178. int operation;
  179. char    *tag = NULL;
  180. EState    *state;
  181. TupleDesc attinfo;
  182. bool isRetrieveIntoPortal;
  183. bool isRetrieveIntoRelation;
  184. char    *intoName = NULL;
  185. CommandDest dest;
  186. /* ----------------
  187.  * get info from the query desc
  188.  * ----------------
  189.  */
  190. parseTree = queryDesc->parsetree;
  191. plan = queryDesc->plantree;
  192. operation = queryDesc->operation;
  193. PS_SET_STATUS(tag = CreateOperationTag(operation));
  194. dest = queryDesc->dest;
  195. /* ----------------
  196.  * initialize portal/into relation status
  197.  * ----------------
  198.  */
  199. isRetrieveIntoPortal = false;
  200. isRetrieveIntoRelation = false;
  201. if (operation == CMD_SELECT)
  202. {
  203. if (parseTree->isPortal)
  204. {
  205. isRetrieveIntoPortal = true;
  206. intoName = parseTree->into;
  207. if (parseTree->isBinary)
  208. {
  209. /*
  210.  * For internal format portals, we change Remote
  211.  * (externalized form) to RemoteInternal (internalized
  212.  * form)
  213.  */
  214. dest = queryDesc->dest = RemoteInternal;
  215. }
  216. }
  217. else if (parseTree->into != NULL)
  218. {
  219. /* select into table */
  220. isRetrieveIntoRelation = true;
  221. }
  222. }
  223. /* ----------------
  224.  * when performing a retrieve into, we override the normal
  225.  * communication destination during the processing of the
  226.  * the query. This only affects the tuple-output function
  227.  * - the correct destination will still see BeginCommand()
  228.  * and EndCommand() messages.
  229.  * ----------------
  230.  */
  231. if (isRetrieveIntoRelation)
  232. queryDesc->dest = (int) None;
  233. /* ----------------
  234.  * create a default executor state..
  235.  * ----------------
  236.  */
  237. state = CreateExecutorState();
  238. /* ----------------
  239.  * call ExecStart to prepare the plan for execution
  240.  * ----------------
  241.  */
  242. attinfo = ExecutorStart(queryDesc, state);
  243. /* ----------------
  244.  *  report the query's result type information
  245.  *  back to the front end or to whatever destination
  246.  *  we're dealing with.
  247.  * ----------------
  248.  */
  249. BeginCommand(NULL,
  250.  operation,
  251.  attinfo,
  252.  isRetrieveIntoRelation,
  253.  isRetrieveIntoPortal,
  254.  tag,
  255.  dest);
  256. /* ----------------
  257.  * Named portals do not do a "fetch all" initially, so now
  258.  * we return since ExecMain has been called with EXEC_START
  259.  * to initialize the query plan.
  260.  *
  261.  * Note: ProcessPortal transforms the current "blank" portal
  262.  *   into a named portal and creates a new blank portal so
  263.  *   everything we allocated in the current "blank" memory
  264.  *   context will be preserved across queries.  -cim 2/22/91
  265.  * ----------------
  266.  */
  267. if (isRetrieveIntoPortal)
  268. {
  269. PortalExecutorHeapMemory = NULL;
  270. ProcessPortal(intoName,
  271.   parseTree,
  272.   plan,
  273.   state,
  274.   attinfo,
  275.   dest);
  276. EndCommand(tag, dest);
  277. return;
  278. }
  279. /* ----------------
  280.  *  Now we get to the important call to ExecutorRun() where we
  281.  *  actually run the plan..
  282.  * ----------------
  283.  */
  284. ExecutorRun(queryDesc, state, EXEC_RUN, limoffset, limcount);
  285. /* save infos for EndCommand */
  286. UpdateCommandInfo(operation, state->es_lastoid, state->es_processed);
  287. /* ----------------
  288.  *  now, we close down all the scans and free allocated resources...
  289.  * with ExecutorEnd()
  290.  * ----------------
  291.  */
  292. ExecutorEnd(queryDesc, state);
  293. /* ----------------
  294.  * Notify the destination of end of processing.
  295.  * ----------------
  296.  */
  297. EndCommand(tag, dest);
  298. }
  299. /* ----------------------------------------------------------------
  300.  * ProcessQuery
  301.  *
  302.  * Execute a plan, the non-parallel version
  303.  * ----------------------------------------------------------------
  304.  */
  305. void
  306. ProcessQuery(Query *parsetree,
  307.  Plan *plan,
  308.  CommandDest dest)
  309. {
  310. QueryDesc  *queryDesc;
  311. extern int dontExecute; /* from postgres.c */
  312. extern void print_plan(Plan *p, Query *parsetree); /* from print.c */
  313. queryDesc = CreateQueryDesc(parsetree, plan, dest);
  314. if (dontExecute)
  315. {
  316. /* don't execute it, just show the query plan */
  317. print_plan(plan, parsetree);
  318. }
  319. else
  320. ProcessQueryDesc(queryDesc, parsetree->limitOffset,
  321.  parsetree->limitCount);
  322. }