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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * parse_node.c
  4.  *   various routines that make nodes for query plans
  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_node.c,v 1.26 1999/05/22 04:12:27 momjian Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <ctype.h>
  15. #include <string.h>
  16. #include "postgres.h"
  17. #include "access/heapam.h"
  18. #include "catalog/pg_operator.h"
  19. #include "catalog/pg_type.h"
  20. #include "fmgr.h"
  21. #include "nodes/makefuncs.h"
  22. #include "parser/parse_expr.h"
  23. #include "parser/parse_node.h"
  24. #include "parser/parse_oper.h"
  25. #include "parser/parse_relation.h"
  26. #include "parser/parse_type.h"
  27. #include "parser/parse_coerce.h"
  28. #include "utils/builtins.h"
  29. #include "utils/syscache.h"
  30. #include "utils/lsyscache.h"
  31. static void disallow_setop(char *op, Type optype, Node *operand);
  32. static Node *make_operand(char *opname,
  33.  Node *tree,
  34.  Oid orig_typeId,
  35.  Oid true_typeId);
  36. /* make_parsestate()
  37.  * Allocate and initialize a new ParseState.
  38.  * The CALLER is responsible for freeing the ParseState* returned.
  39.  */
  40. ParseState *
  41. make_parsestate(ParseState *parentParseState)
  42. {
  43. ParseState *pstate;
  44. pstate = palloc(sizeof(ParseState));
  45. MemSet(pstate, 0, sizeof(ParseState));
  46. pstate->p_last_resno = 1;
  47. pstate->parentParseState = parentParseState;
  48. return pstate;
  49. }
  50. /* make_operand()
  51.  * Ensure argument type match by forcing conversion of constants.
  52.  */
  53. static Node *
  54. make_operand(char *opname,
  55.  Node *tree,
  56.  Oid orig_typeId,
  57.  Oid true_typeId)
  58. {
  59. Node    *result;
  60. Type true_type;
  61. if (tree != NULL)
  62. {
  63. result = tree;
  64. true_type = typeidType(true_typeId);
  65. disallow_setop(opname, true_type, result);
  66. /* must coerce? */
  67. if (true_typeId != orig_typeId)
  68. result = coerce_type(NULL, tree, orig_typeId, true_typeId, -1);
  69. }
  70. /* otherwise, this is a NULL value */
  71. else
  72. {
  73. Const    *con = makeNode(Const);
  74. con->consttype = true_typeId;
  75. con->constlen = 0;
  76. con->constvalue = (Datum) (struct varlena *) NULL;
  77. con->constisnull = true;
  78. con->constbyval = true;
  79. con->constisset = false;
  80. result = (Node *) con;
  81. }
  82. return result;
  83. } /* make_operand() */
  84. static void
  85. disallow_setop(char *op, Type optype, Node *operand)
  86. {
  87. if (operand == NULL)
  88. return;
  89. if (nodeTag(operand) == T_Iter)
  90. {
  91. elog(ERROR, "An operand to the '%s' operator returns a set of %s,"
  92.  "ntbut '%s' takes single values, not sets.",
  93.  op, typeTypeName(optype), op);
  94. }
  95. }
  96. /* make_op()
  97.  * Operator construction.
  98.  *
  99.  * Transform operator expression ensuring type compatibility.
  100.  * This is where some type conversion happens.
  101.  */
  102. Expr *
  103. make_op(char *opname, Node *ltree, Node *rtree)
  104. {
  105. Oid ltypeId,
  106. rtypeId;
  107. Operator tup;
  108. Form_pg_operator opform;
  109. Oper    *newop;
  110. Node    *left,
  111.    *right;
  112. Expr    *result;
  113. /* right operator? */
  114. if (rtree == NULL)
  115. {
  116. ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
  117. tup = right_oper(opname, ltypeId);
  118. opform = (Form_pg_operator) GETSTRUCT(tup);
  119. left = make_operand(opname, ltree, ltypeId, opform->oprleft);
  120. right = NULL;
  121. }
  122. /* left operator? */
  123. else if (ltree == NULL)
  124. {
  125. rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
  126. tup = left_oper(opname, rtypeId);
  127. opform = (Form_pg_operator) GETSTRUCT(tup);
  128. right = make_operand(opname, rtree, rtypeId, opform->oprright);
  129. left = NULL;
  130. }
  131. /* otherwise, binary operator */
  132. else
  133. {
  134. /* binary operator */
  135. ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
  136. rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
  137. /* check for exact match on this operator... */
  138. if (HeapTupleIsValid(tup = oper_exact(opname, ltypeId, rtypeId, &ltree, &rtree, TRUE)))
  139. {
  140. ltypeId = exprType(ltree);
  141. rtypeId = exprType(rtree);
  142. }
  143. /* try to find a match on likely candidates... */
  144. else if (!HeapTupleIsValid(tup = oper_inexact(opname, ltypeId, rtypeId, &ltree, &rtree, FALSE)))
  145. {
  146. /* Won't return from oper_inexact() without a candidate... */
  147. }
  148. opform = (Form_pg_operator) GETSTRUCT(tup);
  149. left = make_operand(opname, ltree, ltypeId, opform->oprleft);
  150. right = make_operand(opname, rtree, rtypeId, opform->oprright);
  151. }
  152. newop = makeOper(oprid(tup),/* opno */
  153.  InvalidOid,/* opid */
  154.  opform->oprresult, /* operator result type */
  155.  0,
  156.  NULL);
  157. result = makeNode(Expr);
  158. result->typeOid = opform->oprresult;
  159. result->opType = OP_EXPR;
  160. result->oper = (Node *) newop;
  161. if (!left)
  162. result->args = lcons(right, NIL);
  163. else if (!right)
  164. result->args = lcons(left, NIL);
  165. else
  166. result->args = lcons(left, lcons(right, NIL));
  167. return result;
  168. } /* make_op() */
  169. Var *
  170. make_var(ParseState *pstate, Oid relid, char *refname,
  171.  char *attrname)
  172. {
  173. Var    *varnode;
  174. int vnum,
  175. attid;
  176. Oid vartypeid;
  177. int32 type_mod;
  178. int sublevels_up;
  179. vnum = refnameRangeTablePosn(pstate, refname, &sublevels_up);
  180. attid = get_attnum(relid, attrname);
  181. if (attid == InvalidAttrNumber)
  182. elog(ERROR, "Relation %s does not have attribute %s",
  183.  refname, attrname);
  184. vartypeid = get_atttype(relid, attid);
  185. type_mod = get_atttypmod(relid, attid);
  186. varnode = makeVar(vnum, attid, vartypeid, type_mod,
  187.   sublevels_up, vnum, attid);
  188. return varnode;
  189. }
  190. /*
  191.  * make_array_ref() -- Make an array reference node.
  192.  *
  193.  * Array references can hang off of arbitrary nested dot (or
  194.  * function invocation) expressions.  This routine takes a
  195.  * tree generated by ParseFunc() and an array index and
  196.  * generates a new array reference tree.  We do some simple
  197.  * typechecking to be sure the dereference is valid in the
  198.  * type system, but we don't do any bounds checking here.
  199.  *
  200.  * indirection is a list of A_Indices
  201.  */
  202. ArrayRef   *
  203. make_array_ref(Node *expr,
  204.    List *indirection)
  205. {
  206. Oid typearray;
  207. HeapTuple type_tuple;
  208. Form_pg_type type_struct_array,
  209. type_struct_element;
  210. ArrayRef   *aref;
  211. Oid reftype;
  212. List    *upperIndexpr = NIL;
  213. List    *lowerIndexpr = NIL;
  214. typearray = exprType(expr);
  215. type_tuple = SearchSysCacheTuple(TYPOID,
  216.  ObjectIdGetDatum(typearray),
  217.  0, 0, 0);
  218. if (!HeapTupleIsValid(type_tuple))
  219. elog(ERROR, "make_array_ref: Cache lookup failed for type %un",
  220.  typearray);
  221. /* get the array type struct from the type tuple */
  222. type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple);
  223. if (type_struct_array->typelem == InvalidOid)
  224. elog(ERROR, "make_array_ref: type %s is not an array",
  225.  type_struct_array->typname);
  226. /* get the type tuple for the element type */
  227. type_tuple = SearchSysCacheTuple(TYPOID,
  228. ObjectIdGetDatum(type_struct_array->typelem),
  229.  0, 0, 0);
  230. if (!HeapTupleIsValid(type_tuple))
  231. elog(ERROR, "make_array_ref: Cache lookup failed for type %un",
  232.  typearray);
  233. type_struct_element = (Form_pg_type) GETSTRUCT(type_tuple);
  234. while (indirection != NIL)
  235. {
  236. A_Indices  *ind = lfirst(indirection);
  237. if (ind->lidx)
  238. /*
  239.  * XXX assumes all lower indices non null in this case
  240.  */
  241. lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
  242. upperIndexpr = lappend(upperIndexpr, ind->uidx);
  243. indirection = lnext(indirection);
  244. }
  245. aref = makeNode(ArrayRef);
  246. aref->refattrlength = type_struct_array->typlen;
  247. aref->refelemlength = type_struct_element->typlen;
  248. aref->refelemtype = type_struct_array->typelem;
  249. aref->refelembyval = type_struct_element->typbyval;
  250. aref->refupperindexpr = upperIndexpr;
  251. aref->reflowerindexpr = lowerIndexpr;
  252. aref->refexpr = expr;
  253. aref->refassgnexpr = NULL;
  254. if (lowerIndexpr == NIL) /* accessing a single array element */
  255. reftype = aref->refelemtype;
  256. else
  257. /* request to clip a part of the array, the result is another array */
  258. reftype = typearray;
  259. /*
  260.  * we change it to reflect the true type; since the original
  261.  * refelemtype doesn't seem to get used anywhere. - ay 10/94
  262.  */
  263. aref->refelemtype = reftype;
  264. return aref;
  265. }
  266. /* make_array_set()
  267.  */
  268. ArrayRef   *
  269. make_array_set(Expr *target_expr,
  270.    List *upperIndexpr,
  271.    List *lowerIndexpr,
  272.    Expr *expr)
  273. {
  274. Oid typearray;
  275. HeapTuple type_tuple;
  276. Form_pg_type type_struct_array;
  277. Form_pg_type type_struct_element;
  278. ArrayRef   *aref;
  279. Oid reftype;
  280. typearray = exprType((Node *) target_expr);
  281. type_tuple = SearchSysCacheTuple(TYPOID,
  282.  ObjectIdGetDatum(typearray),
  283.  0, 0, 0);
  284. if (!HeapTupleIsValid(type_tuple))
  285. elog(ERROR, "make_array_ref: Cache lookup failed for type %un",
  286.  typearray);
  287. /* get the array type struct from the type tuple */
  288. type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple);
  289. if (type_struct_array->typelem == InvalidOid)
  290. elog(ERROR, "make_array_ref: type %s is not an array",
  291.  type_struct_array->typname);
  292. /* get the type tuple for the element type */
  293. type_tuple = SearchSysCacheTuple(TYPOID,
  294. ObjectIdGetDatum(type_struct_array->typelem),
  295.  0, 0, 0);
  296. if (!HeapTupleIsValid(type_tuple))
  297. elog(ERROR, "make_array_ref: Cache lookup failed for type %un",
  298.  typearray);
  299. type_struct_element = (Form_pg_type) GETSTRUCT(type_tuple);
  300. aref = makeNode(ArrayRef);
  301. aref->refattrlength = type_struct_array->typlen;
  302. aref->refelemlength = type_struct_element->typlen;
  303. aref->refelemtype = type_struct_array->typelem;
  304. aref->refelembyval = type_struct_element->typbyval;
  305. aref->refupperindexpr = upperIndexpr;
  306. aref->reflowerindexpr = lowerIndexpr;
  307. aref->refexpr = (Node *) target_expr;
  308. aref->refassgnexpr = (Node *) expr;
  309. /* accessing a single array element? */
  310. if (lowerIndexpr == NIL)
  311. reftype = aref->refelemtype;
  312. /* otherwise, request to set a part of the array, by another array */
  313. else
  314. reftype = typearray;
  315. aref->refelemtype = reftype;
  316. return aref;
  317. }
  318. /*
  319.  *
  320.  * make_const -
  321.  *
  322.  * - takes a lispvalue, (as returned to the yacc routine by the lexer)
  323.  *  extracts the type, and makes the appropriate type constant
  324.  *  by invoking the (c-callable) lisp routine c-make-const
  325.  *  via the lisp_call() mechanism
  326.  *
  327.  * eventually, produces a "const" lisp-struct as per nodedefs.cl
  328.  */
  329. Const *
  330. make_const(Value *value)
  331. {
  332. Type tp;
  333. Datum val;
  334. Const    *con;
  335. switch (nodeTag(value))
  336. {
  337. case T_Integer:
  338. tp = typeidType(INT4OID);
  339. val = Int32GetDatum(intVal(value));
  340. break;
  341. case T_Float:
  342. {
  343. float64 dummy;
  344. tp = typeidType(FLOAT8OID);
  345. dummy = (float64) palloc(sizeof(float64data));
  346. *dummy = floatVal(value);
  347. val = Float64GetDatum(dummy);
  348. }
  349. break;
  350. case T_String:
  351. tp = typeidType(UNKNOWNOID); /* unknown for now, will
  352.  * be type coerced */
  353. val = PointerGetDatum(textin(strVal(value)));
  354. break;
  355. case T_Null:
  356. default:
  357. {
  358. if (nodeTag(value) != T_Null)
  359. elog(NOTICE, "make_const: unknown type %dn", nodeTag(value));
  360. /* null const */
  361. con = makeConst(0, 0, (Datum) NULL, true, false, false, false);
  362. return con;
  363. }
  364. }
  365. con = makeConst(typeTypeId(tp),
  366. typeLen(tp),
  367. val,
  368. false,
  369. typeByVal(tp),
  370. false, /* not a set */
  371. false);
  372. return con;
  373. }