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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * junk.c
  4.  *   Junk attribute support stuff....
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.17 1999/05/17 17:03:10 momjian Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <string.h>
  15. #include "postgres.h"
  16. #include "utils/palloc.h"
  17. #include "access/heapam.h"
  18. #include "executor/executor.h"
  19. #include "nodes/relation.h"
  20. #include "nodes/makefuncs.h"
  21. /*-------------------------------------------------------------------------
  22.  * XXX this stuff should be rewritten to take advantage
  23.  * of ExecProject() and the ProjectionInfo node.
  24.  * -cim 6/3/91
  25.  *
  26.  * An attribute of a tuple living inside the executor, can be
  27.  * either a normal attribute or a "junk" attribute. "junk" attributes
  28.  * never make it out of the executor, i.e. they are never printed,
  29.  * returned or stored in disk. Their only purpose in life is to
  30.  * store some information useful only to the executor, mainly the values
  31.  * of some system attributes like "ctid" or rule locks.
  32.  *
  33.  * The general idea is the following: A target list consists of a list of
  34.  * Resdom nodes & expression pairs. Each Resdom node has an attribute
  35.  * called 'resjunk'. If the value of this attribute is true then the
  36.  * corresponding attribute is a "junk" attribute.
  37.  *
  38.  * When we initialize a plan  we call 'ExecInitJunkFilter' to create
  39.  * and store the appropriate information in the 'es_junkFilter' attribute of
  40.  * EState.
  41.  *
  42.  * We then execute the plan ignoring the "resjunk" attributes.
  43.  *
  44.  * Finally, when at the top level we get back a tuple, we can call
  45.  * 'ExecGetJunkAttribute' to retrieve the value of the junk attributes we
  46.  * are interested in, and 'ExecRemoveJunk' to remove all the junk attributes
  47.  * from a tuple. This new "clean" tuple is then printed, replaced, deleted
  48.  * or inserted.
  49.  *
  50.  *-------------------------------------------------------------------------
  51.  */
  52. /*-------------------------------------------------------------------------
  53.  * ExecInitJunkFilter
  54.  *
  55.  * Initialize the Junk filter.
  56.  *-------------------------------------------------------------------------
  57.  */
  58. JunkFilter *
  59. ExecInitJunkFilter(List *targetList)
  60. {
  61. JunkFilter *junkfilter;
  62. List    *cleanTargetList;
  63. int len,
  64. cleanLength;
  65. TupleDesc tupType,
  66. cleanTupType;
  67. List    *t;
  68. TargetEntry *tle;
  69. Resdom    *resdom,
  70.    *cleanResdom;
  71. bool resjunk;
  72. AttrNumber cleanResno;
  73. AttrNumber *cleanMap;
  74. Size size;
  75. Node    *expr;
  76. /* ---------------------
  77.  * First find the "clean" target list, i.e. all the entries
  78.  * in the original target list which have a false 'resjunk'
  79.  * NOTE: make copy of the Resdom nodes, because we have
  80.  * to change the 'resno's...
  81.  * ---------------------
  82.  */
  83. cleanTargetList = NIL;
  84. cleanResno = 1;
  85. foreach(t, targetList)
  86. {
  87. TargetEntry *rtarget = lfirst(t);
  88. if (rtarget->resdom != NULL)
  89. {
  90. resdom = rtarget->resdom;
  91. expr = rtarget->expr;
  92. resjunk = resdom->resjunk;
  93. if (!resjunk)
  94. {
  95. /*
  96.  * make a copy of the resdom node, changing its resno.
  97.  */
  98. cleanResdom = (Resdom *) copyObject(resdom);
  99. cleanResdom->resno = cleanResno;
  100. cleanResno++;
  101. /*
  102.  * create a new target list entry
  103.  */
  104. tle = makeTargetEntry(cleanResdom, expr);
  105. cleanTargetList = lappend(cleanTargetList, tle);
  106. }
  107. }
  108. else
  109. {
  110. #ifdef SETS_FIXED
  111. List    *fjListP;
  112. Fjoin    *cleanFjoin;
  113. List    *cleanFjList;
  114. List    *fjList = lfirst(t);
  115. Fjoin    *fjNode = (Fjoin *) tl_node(fjList);
  116. cleanFjoin = (Fjoin) copyObject((Node) fjNode);
  117. cleanFjList = lcons(cleanFjoin, NIL);
  118. resdom = (Resdom) lfirst(get_fj_innerNode(fjNode));
  119. expr = lsecond(get_fj_innerNode(fjNode));
  120. cleanResdom = (Resdom) copyObject((Node) resdom);
  121. set_resno(cleanResdom, cleanResno);
  122. cleanResno++;
  123. tle = (List) makeTargetEntry(cleanResdom, (Node *) expr);
  124. set_fj_innerNode(cleanFjoin, tle);
  125. foreach(fjListP, lnext(fjList))
  126. {
  127. TargetEntry *tle = lfirst(fjListP);
  128. resdom = tle->resdom;
  129. expr = tle->expr;
  130. cleanResdom = (Resdom *) copyObject((Node) resdom);
  131. cleanResno++;
  132. cleanResdom->Resno = cleanResno;
  133. /*
  134.  * create a new target list entry
  135.  */
  136. tle = (List) makeTargetEntry(cleanResdom, (Node *) expr);
  137. cleanFjList = lappend(cleanFjList, tle);
  138. }
  139. lappend(cleanTargetList, cleanFjList);
  140. #endif
  141. }
  142. }
  143. /* ---------------------
  144.  * Now calculate the tuple types for the original and the clean tuple
  145.  *
  146.  * XXX ExecTypeFromTL should be used sparingly.  Don't we already
  147.  *    have the tupType corresponding to the targetlist we are passed?
  148.  *    -cim 5/31/91
  149.  * ---------------------
  150.  */
  151. tupType = (TupleDesc) ExecTypeFromTL(targetList);
  152. cleanTupType = (TupleDesc) ExecTypeFromTL(cleanTargetList);
  153. len = ExecTargetListLength(targetList);
  154. cleanLength = ExecTargetListLength(cleanTargetList);
  155. /* ---------------------
  156.  * Now calculate the "map" between the original tuples attributes
  157.  * and the "clean" tuple's attributes.
  158.  *
  159.  * The "map" is an array of "cleanLength" attribute numbers, i.e.
  160.  * one entry for every attribute of the "clean" tuple.
  161.  * The value of this entry is the attribute number of the corresponding
  162.  * attribute of the "original" tuple.
  163.  * ---------------------
  164.  */
  165. if (cleanLength > 0)
  166. {
  167. size = cleanLength * sizeof(AttrNumber);
  168. cleanMap = (AttrNumber *) palloc(size);
  169. cleanResno = 1;
  170. foreach(t, targetList)
  171. {
  172. TargetEntry *tle = lfirst(t);
  173. if (tle->resdom != NULL)
  174. {
  175. resdom = tle->resdom;
  176. expr = tle->expr;
  177. resjunk = resdom->resjunk;
  178. if (!resjunk)
  179. {
  180. cleanMap[cleanResno - 1] = resdom->resno;
  181. cleanResno++;
  182. }
  183. }
  184. else
  185. {
  186. #ifdef SETS_FIXED
  187. List fjListP;
  188. List fjList = lfirst(t);
  189. Fjoin fjNode = (Fjoin) lfirst(fjList);
  190. /* what the hell is this????? */
  191. resdom = (Resdom) lfirst(get_fj_innerNode(fjNode));
  192. #endif
  193. cleanMap[cleanResno - 1] = tle->resdom->resno;
  194. cleanResno++;
  195. #ifdef SETS_FIXED
  196. foreach(fjListP, lnext(fjList))
  197. {
  198. TargetEntry *tle = lfirst(fjListP);
  199. resdom = tle->resdom;
  200. cleanMap[cleanResno - 1] = resdom->resno;
  201. cleanResno++;
  202. }
  203. #endif
  204. }
  205. }
  206. }
  207. else
  208. cleanMap = NULL;
  209. /* ---------------------
  210.  * Finally create and initialize the JunkFilter.
  211.  * ---------------------
  212.  */
  213. junkfilter = makeNode(JunkFilter);
  214. junkfilter->jf_targetList = targetList;
  215. junkfilter->jf_length = len;
  216. junkfilter->jf_tupType = tupType;
  217. junkfilter->jf_cleanTargetList = cleanTargetList;
  218. junkfilter->jf_cleanLength = cleanLength;
  219. junkfilter->jf_cleanTupType = cleanTupType;
  220. junkfilter->jf_cleanMap = cleanMap;
  221. return junkfilter;
  222. }
  223. /*-------------------------------------------------------------------------
  224.  * ExecGetJunkAttribute
  225.  *
  226.  * Given a tuple (slot), the junk filter and a junk attribute's name,
  227.  * extract & return the value of this attribute.
  228.  *
  229.  * It returns false iff no junk attribute with such name was found.
  230.  *
  231.  * NOTE: isNull might be NULL !
  232.  *-------------------------------------------------------------------------
  233.  */
  234. bool
  235. ExecGetJunkAttribute(JunkFilter *junkfilter,
  236.  TupleTableSlot *slot,
  237.  char *attrName,
  238.  Datum *value,
  239.  bool *isNull)
  240. {
  241. List    *targetList;
  242. List    *t;
  243. Resdom    *resdom;
  244. AttrNumber resno;
  245. char    *resname;
  246. bool resjunk;
  247. TupleDesc tupType;
  248. HeapTuple tuple;
  249. /* ---------------------
  250.  * first look in the junkfilter's target list for
  251.  * an attribute with the given name
  252.  * ---------------------
  253.  */
  254. resno = InvalidAttrNumber;
  255. targetList = junkfilter->jf_targetList;
  256. foreach(t, targetList)
  257. {
  258. TargetEntry *tle = lfirst(t);
  259. resdom = tle->resdom;
  260. resname = resdom->resname;
  261. resjunk = resdom->resjunk;
  262. if (resjunk && (strcmp(resname, attrName) == 0))
  263. {
  264. /* We found it ! */
  265. resno = resdom->resno;
  266. break;
  267. }
  268. }
  269. if (resno == InvalidAttrNumber)
  270. {
  271. /* Ooops! We couldn't find this attribute... */
  272. return false;
  273. }
  274. /* ---------------------
  275.  * Now extract the attribute value from the tuple.
  276.  * ---------------------
  277.  */
  278. tuple = slot->val;
  279. tupType = (TupleDesc) junkfilter->jf_tupType;
  280. *value = heap_getattr(tuple, resno, tupType, isNull);
  281. return true;
  282. }
  283. /*-------------------------------------------------------------------------
  284.  * ExecRemoveJunk
  285.  *
  286.  * Construct and return a tuple with all the junk attributes removed.
  287.  *-------------------------------------------------------------------------
  288.  */
  289. HeapTuple
  290. ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
  291. {
  292. HeapTuple tuple;
  293. HeapTuple cleanTuple;
  294. AttrNumber *cleanMap;
  295. TupleDesc cleanTupType;
  296. TupleDesc tupType;
  297. int cleanLength;
  298. bool isNull;
  299. int i;
  300. Size size;
  301. Datum    *values;
  302. char    *nulls;
  303. Datum values_array[64];
  304. char nulls_array[64];
  305. /* ----------------
  306.  * get info from the slot and the junk filter
  307.  * ----------------
  308.  */
  309. tuple = slot->val;
  310. tupType = (TupleDesc) junkfilter->jf_tupType;
  311. cleanTupType = (TupleDesc) junkfilter->jf_cleanTupType;
  312. cleanLength = junkfilter->jf_cleanLength;
  313. cleanMap = junkfilter->jf_cleanMap;
  314. /* ---------------------
  315.  * Handle the trivial case first.
  316.  * ---------------------
  317.  */
  318. if (cleanLength == 0)
  319. return (HeapTuple) NULL;
  320. /* ---------------------
  321.  * Create the arrays that will hold the attribute values
  322.  * and the null information for the new "clean" tuple.
  323.  *
  324.  * Note: we use memory on the stack to optimize things when
  325.  *  we are dealing with a small number of tuples.
  326.  *  for large tuples we just use palloc.
  327.  * ---------------------
  328.  */
  329. if (cleanLength > 64)
  330. {
  331. size = cleanLength * sizeof(Datum);
  332. values = (Datum *) palloc(size);
  333. size = cleanLength * sizeof(char);
  334. nulls = (char *) palloc(size);
  335. }
  336. else
  337. {
  338. values = values_array;
  339. nulls = nulls_array;
  340. }
  341. /* ---------------------
  342.  * Exctract one by one all the values of the "clean" tuple.
  343.  * ---------------------
  344.  */
  345. for (i = 0; i < cleanLength; i++)
  346. {
  347. values[i] = heap_getattr(tuple, cleanMap[i], tupType, &isNull);
  348. if (isNull)
  349. nulls[i] = 'n';
  350. else
  351. nulls[i] = ' ';
  352. }
  353. /* ---------------------
  354.  * Now form the new tuple.
  355.  * ---------------------
  356.  */
  357. cleanTuple = heap_formtuple(cleanTupType,
  358. values,
  359. nulls);
  360. /* ---------------------
  361.  * We are done.  Free any space allocated for 'values' and 'nulls'
  362.  * and return the new tuple.
  363.  * ---------------------
  364.  */
  365. if (cleanLength > 64)
  366. {
  367. pfree(values);
  368. pfree(nulls);
  369. }
  370. return cleanTuple;
  371. }