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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * parse_relation.c
  4.  *   parser support routines dealing with relations
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.22 1999/05/25 16:10:19 momjian Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <ctype.h>
  15. #include <string.h>
  16. #include "postgres.h"
  17. #include "access/heapam.h"
  18. #include "access/htup.h"
  19. #include "catalog/pg_type.h"
  20. #include "nodes/makefuncs.h"
  21. #include "parser/parse_relation.h"
  22. #include "parser/parse_coerce.h"
  23. #include "utils/acl.h"
  24. #include "utils/builtins.h"
  25. #include "utils/lsyscache.h"
  26. static void checkTargetTypes(ParseState *pstate, char *target_colname,
  27.  char *refname, char *colname);
  28. struct
  29. {
  30. char    *field;
  31. int code;
  32. } special_attr[] =
  33. {
  34. {
  35. "ctid", SelfItemPointerAttributeNumber
  36. },
  37. {
  38. "oid", ObjectIdAttributeNumber
  39. },
  40. {
  41. "xmin", MinTransactionIdAttributeNumber
  42. },
  43. {
  44. "cmin", MinCommandIdAttributeNumber
  45. },
  46. {
  47. "xmax", MaxTransactionIdAttributeNumber
  48. },
  49. {
  50. "cmax", MaxCommandIdAttributeNumber
  51. },
  52. };
  53. #define SPECIALS (sizeof(special_attr)/sizeof(*special_attr))
  54. static char *attnum_type[SPECIALS] = {
  55. "tid",
  56. "oid",
  57. "xid",
  58. "cid",
  59. "xid",
  60. "cid",
  61. };
  62. /* given refname, return a pointer to the range table entry */
  63. RangeTblEntry *
  64. refnameRangeTableEntry(ParseState *pstate, char *refname)
  65. {
  66. List    *temp;
  67. while (pstate != NULL)
  68. {
  69. foreach(temp, pstate->p_rtable)
  70. {
  71. RangeTblEntry *rte = lfirst(temp);
  72. if (!strcmp(rte->refname, refname))
  73. return rte;
  74. }
  75. /* only allow correlated columns in WHERE clause */
  76. if (pstate->p_in_where_clause)
  77. pstate = pstate->parentParseState;
  78. else
  79. break;
  80. }
  81. return NULL;
  82. }
  83. /* given refname, return id of variable; position starts with 1 */
  84. int
  85. refnameRangeTablePosn(ParseState *pstate, char *refname, int *sublevels_up)
  86. {
  87. int index;
  88. List    *temp;
  89. if (sublevels_up)
  90. *sublevels_up = 0;
  91. while (pstate != NULL)
  92. {
  93. index = 1;
  94. foreach(temp, pstate->p_rtable)
  95. {
  96. RangeTblEntry *rte = lfirst(temp);
  97. if (!strcmp(rte->refname, refname))
  98. return index;
  99. index++;
  100. }
  101. /* only allow correlated columns in WHERE clause */
  102. if (pstate->p_in_where_clause)
  103. {
  104. pstate = pstate->parentParseState;
  105. if (sublevels_up)
  106. (*sublevels_up)++;
  107. }
  108. else
  109. break;
  110. }
  111. return 0;
  112. }
  113. /*
  114.  * returns range entry if found, else NULL
  115.  */
  116. RangeTblEntry *
  117. colnameRangeTableEntry(ParseState *pstate, char *colname)
  118. {
  119. List    *et;
  120. List    *rtable;
  121. RangeTblEntry *rte_result;
  122. rte_result = NULL;
  123. while (pstate != NULL)
  124. {
  125. if (pstate->p_is_rule)
  126. rtable = lnext(lnext(pstate->p_rtable));
  127. else
  128. rtable = pstate->p_rtable;
  129. foreach(et, rtable)
  130. {
  131. RangeTblEntry *rte = lfirst(et);
  132. /* only entries on outer(non-function?) scope */
  133. if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
  134. continue;
  135. if (get_attnum(rte->relid, colname) != InvalidAttrNumber)
  136. {
  137. if (rte_result != NULL)
  138. {
  139. if (!pstate->p_is_insert ||
  140. rte != pstate->p_target_rangetblentry)
  141. elog(ERROR, "Column '%s' is ambiguous", colname);
  142. }
  143. else
  144. rte_result = rte;
  145. }
  146. }
  147. /* only allow correlated columns in WHERE clause */
  148. if (pstate->p_in_where_clause && rte_result == NULL)
  149. pstate = pstate->parentParseState;
  150. else
  151. break;
  152. }
  153. return rte_result;
  154. }
  155. /*
  156.  * put new entry in pstate p_rtable structure, or return pointer
  157.  * if pstate null
  158. */
  159. RangeTblEntry *
  160. addRangeTableEntry(ParseState *pstate,
  161.    char *relname,
  162.    char *refname,
  163.    bool inh,
  164.    bool inFromCl)
  165. {
  166. Relation relation;
  167. RangeTblEntry *rte = makeNode(RangeTblEntry);
  168. int sublevels_up;
  169. if (pstate != NULL)
  170. {
  171. if (refnameRangeTablePosn(pstate, refname, &sublevels_up) != 0 &&
  172. (!inFromCl || sublevels_up == 0))
  173. {
  174. if (!strcmp(refname, "*CURRENT*") || !strcmp(refname, "*NEW*"))
  175. {
  176. int rt_index = refnameRangeTablePosn(pstate, refname, &sublevels_up);
  177. return (RangeTblEntry *) nth(rt_index - 1, pstate->p_rtable);
  178. }
  179. elog(ERROR, "Table name '%s' specified more than once", refname);
  180. }
  181. }
  182. rte->relname = pstrdup(relname);
  183. rte->refname = pstrdup(refname);
  184. relation = heap_openr(relname);
  185. if (relation == NULL)
  186. elog(ERROR, "%s: %s",
  187.  relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
  188. rte->relid = RelationGetRelid(relation);
  189. heap_close(relation);
  190. /*
  191.  * Flags - zero or more from inheritance,union,version or recursive
  192.  * (transitive closure) [we don't support them all -- ay 9/94 ]
  193.  */
  194. rte->inh = inh;
  195. /* RelOID */
  196. rte->inFromCl = inFromCl;
  197. /*
  198.  * close the relation we're done with it for now.
  199.  */
  200. if (pstate != NULL)
  201. pstate->p_rtable = lappend(pstate->p_rtable, rte);
  202. return rte;
  203. }
  204. /*
  205.  * expandAll -
  206.  *   makes a list of attributes
  207.  */
  208. List *
  209. expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
  210. {
  211. Relation rel;
  212. List    *te_tail = NIL,
  213.    *te_head = NIL;
  214. Var    *varnode;
  215. int varattno,
  216. maxattrs;
  217. RangeTblEntry *rte;
  218. rte = refnameRangeTableEntry(pstate, refname);
  219. if (rte == NULL)
  220. rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
  221. rel = heap_open(rte->relid);
  222. if (rel == NULL)
  223. elog(ERROR, "Unable to expand all -- heap_open failed on %s",
  224.  rte->refname);
  225. maxattrs = RelationGetNumberOfAttributes(rel);
  226. for (varattno = 0; varattno <= maxattrs - 1; varattno++)
  227. {
  228. char    *attrname;
  229. char    *resname = NULL;
  230. TargetEntry *te = makeNode(TargetEntry);
  231. attrname = pstrdup((rel->rd_att->attrs[varattno]->attname).data);
  232. varnode = (Var *) make_var(pstate, rte->relid, refname, attrname);
  233. handleTargetColname(pstate, &resname, refname, attrname);
  234. if (resname != NULL)
  235. attrname = resname;
  236. /*
  237.  * Even if the elements making up a set are complex, the set
  238.  * itself is not.
  239.  */
  240. te->resdom = makeResdom((AttrNumber) (*this_resno)++,
  241. varnode->vartype,
  242. varnode->vartypmod,
  243. attrname,
  244. (Index) 0,
  245. (Oid) 0,
  246. false);
  247. te->expr = (Node *) varnode;
  248. if (te_head == NIL)
  249. te_head = te_tail = lcons(te, NIL);
  250. else
  251. te_tail = lappend(te_tail, te);
  252. }
  253. heap_close(rel);
  254. return te_head;
  255. }
  256. /*
  257.  * given relation and att name, return id of variable
  258.  *
  259.  * This should only be used if the relation is already
  260.  * heap_open()'ed.  Use the cache version get_attnum()
  261.  * for access to non-opened relations.
  262.  */
  263. int
  264. attnameAttNum(Relation rd, char *a)
  265. {
  266. int i;
  267. for (i = 0; i < rd->rd_rel->relnatts; i++)
  268. if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a))
  269. return i + 1;
  270. for (i = 0; i < SPECIALS; i++)
  271. if (!strcmp(special_attr[i].field, a))
  272. return special_attr[i].code;
  273. /* on failure */
  274. elog(ERROR, "Relation '%s' does not have attribute '%s'",
  275.  RelationGetRelationName(rd), a);
  276. return 0; /* lint */
  277. }
  278. /*
  279.  * Given range variable, return whether attribute of this name
  280.  * is a set.
  281.  * NOTE the ASSUMPTION here that no system attributes are, or ever
  282.  * will be, sets.
  283.  *
  284.  * This should only be used if the relation is already
  285.  * heap_open()'ed.  Use the cache version get_attisset()
  286.  * for access to non-opened relations.
  287.  */
  288. bool
  289. attnameIsSet(Relation rd, char *name)
  290. {
  291. int i;
  292. /* First check if this is a system attribute */
  293. for (i = 0; i < SPECIALS; i++)
  294. {
  295. if (!strcmp(special_attr[i].field, name))
  296. {
  297. return false; /* no sys attr is a set */
  298. }
  299. }
  300. return get_attisset(RelationGetRelid(rd), name);
  301. }
  302. /*
  303.  * This should only be used if the relation is already
  304.  * heap_open()'ed.  Use the cache version
  305.  * for access to non-opened relations.
  306.  */
  307. int
  308. attnumAttNelems(Relation rd, int attid)
  309. {
  310. return rd->rd_att->attrs[attid - 1]->attnelems;
  311. }
  312. /* given attribute id, return type of that attribute */
  313. /*
  314.  * This should only be used if the relation is already
  315.  * heap_open()'ed.  Use the cache version get_atttype()
  316.  * for access to non-opened relations.
  317.  */
  318. Oid
  319. attnumTypeId(Relation rd, int attid)
  320. {
  321. if (attid < 0)
  322. return typeTypeId(typenameType(attnum_type[-attid - 1]));
  323. /*
  324.  * -1 because varattno (where attid comes from) returns one more than
  325.  * index
  326.  */
  327. return rd->rd_att->attrs[attid - 1]->atttypid;
  328. }
  329. /* handleTargetColname()
  330.  * Use column names from insert.
  331.  */
  332. void
  333. handleTargetColname(ParseState *pstate, char **resname,
  334. char *refname, char *colname)
  335. {
  336. if (pstate->p_is_insert)
  337. {
  338. if (pstate->p_insert_columns != NIL)
  339. {
  340. Ident    *id = lfirst(pstate->p_insert_columns);
  341. *resname = id->name;
  342. pstate->p_insert_columns = lnext(pstate->p_insert_columns);
  343. }
  344. else
  345. elog(ERROR, "INSERT has more expressions than target columns");
  346. }
  347. if (pstate->p_is_insert || pstate->p_is_update)
  348. checkTargetTypes(pstate, *resname, refname, colname);
  349. }
  350. /* checkTargetTypes()
  351.  * Checks value and target column types.
  352.  */
  353. static void
  354. checkTargetTypes(ParseState *pstate, char *target_colname,
  355.  char *refname, char *colname)
  356. {
  357. Oid attrtype_id,
  358. attrtype_target;
  359. int resdomno_id,
  360. resdomno_target;
  361. RangeTblEntry *rte;
  362. if (target_colname == NULL || colname == NULL)
  363. return;
  364. if (refname != NULL)
  365. rte = refnameRangeTableEntry(pstate, refname);
  366. else
  367. {
  368. rte = colnameRangeTableEntry(pstate, colname);
  369. if (rte == (RangeTblEntry *) NULL)
  370. elog(ERROR, "Attribute %s not found", colname);
  371. refname = rte->refname;
  372. }
  373. /*
  374. if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
  375. elog(ERROR, "'%s' not available in this context", colname);
  376. */
  377. resdomno_id = get_attnum(rte->relid, colname);
  378. attrtype_id = get_atttype(rte->relid, resdomno_id);
  379. resdomno_target = attnameAttNum(pstate->p_target_relation, target_colname);
  380. attrtype_target = attnumTypeId(pstate->p_target_relation, resdomno_target);
  381. #ifdef NOT_USED
  382. if ((attrtype_id != attrtype_target)
  383. || (get_atttypmod(rte->relid, resdomno_id) !=
  384.    get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target)))
  385. {
  386. if (can_coerce_type(1, &attrtype_id, &attrtype_target))
  387. {
  388. Node    *expr = coerce_type(pstate, expr, attrtype_id,
  389.    attrtype_target,
  390.    get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target));
  391. elog(ERROR, "Type %s(%d) can be coerced to match target column %s(%d)",
  392.  colname, get_atttypmod(rte->relid, resdomno_id),
  393.  target_colname, get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target));
  394. }
  395. else
  396. {
  397. elog(ERROR, "Type or size of %s(%d) does not match target column %s(%d)",
  398.  colname, get_atttypmod(rte->relid, resdomno_id),
  399.  target_colname, get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target));
  400. }
  401. }
  402. #else
  403. if (attrtype_id != attrtype_target)
  404. elog(ERROR, "Type of '%s' does not match target column '%s'",
  405.  colname, target_colname);
  406. if (attrtype_id == BPCHAROID &&
  407. get_atttypmod(rte->relid, resdomno_id) !=
  408. get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target))
  409. elog(ERROR, "Length of '%s' is not equal to the length of target column '%s'",
  410.  colname, target_colname);
  411. if (attrtype_id == VARCHAROID &&
  412. get_atttypmod(rte->relid, resdomno_id) >
  413. get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target))
  414. elog(ERROR, "Length of '%s' is longer than length of target column '%s'",
  415.  colname, target_colname);
  416. #endif
  417. }