1 /*-------------------------------------------------------------------------
4 * take an "optimizable" stmt and make the query tree that
5 * the planner requires.
7 * Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.10 1996/11/30 18:06:34 momjian Exp $
13 *-------------------------------------------------------------------------
20 #include "access/heapam.h"
21 #include "utils/tqual.h"
22 #include "access/tupmacs.h"
23 #include "utils/builtins.h"
24 #include "utils/elog.h"
25 #include "utils/palloc.h"
26 #include "utils/acl.h" /* for ACL_NO_PRIV_WARNING */
27 #include "utils/rel.h" /* Relation stuff */
29 #include "utils/syscache.h"
30 #include "catalog/pg_type.h"
31 #include "catalog/pg_operator.h"
32 #include "parser/catalog_utils.h"
33 #include "parser/parse_query.h"
34 #include "utils/lsyscache.h"
36 #include "nodes/pg_list.h"
37 #include "nodes/primnodes.h"
38 #include "nodes/parsenodes.h"
39 #include "nodes/makefuncs.h"
44 /* given refname, return a pointer to the range table entry */
46 refnameRangeTableEntry(List *rtable, char *refname)
50 foreach(temp, rtable) {
51 RangeTblEntry *rte = lfirst(temp);
53 if (!strcmp(rte->refname, refname))
59 /* given refname, return id of variable; position starts with 1 */
61 refnameRangeTablePosn(List *rtable, char *refname)
67 foreach(temp, rtable) {
68 RangeTblEntry *rte = lfirst(temp);
70 if (!strcmp(rte->refname, refname))
78 * returns range entry if found, else NULL
81 colnameRangeTableEntry(ParseState *pstate, char *colname)
85 RangeTblEntry *rte_result;
87 if (pstate->p_is_rule)
88 rtable = lnext(lnext(pstate->p_rtable));
90 rtable = pstate->p_rtable;
94 RangeTblEntry *rte = lfirst(et);
96 /* only entries on outer(non-function?) scope */
97 if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
100 if (get_attnum(rte->relid, colname) != InvalidAttrNumber) {
101 if (rte_result != NULL) {
102 if (!pstate->p_is_insert ||
103 rte != pstate->p_target_rangetblentry)
104 elog(WARN, "Column %s is ambiguous", colname);
106 else rte_result = rte;
113 * put new entry in pstate p_rtable structure, or return pointer
117 addRangeTableEntry(ParseState *pstate,
120 bool inh, bool inFromCl,
121 TimeRange *timeRange)
124 RangeTblEntry *rte = makeNode(RangeTblEntry);
126 if (pstate != NULL &&
127 refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
128 elog(WARN,"Table name %s specified more than once",refname);
130 rte->relname = pstrdup(relname);
131 rte->refname = pstrdup(refname);
133 relation = heap_openr(relname);
134 if (relation == NULL) {
136 relname, ACL_NO_PRIV_WARNING);
140 * Flags - zero or more from archive,inheritance,union,version
141 * or recursive (transitive closure)
142 * [we don't support them all -- ay 9/94 ]
146 rte->timeRange = timeRange;
149 rte->relid = RelationGetRelationId(relation);
151 rte->archive = false;
153 rte->inFromCl = inFromCl;
156 * close the relation we're done with it for now.
159 pstate->p_rtable = lappend(pstate->p_rtable, rte);
161 heap_close(relation);
168 * makes a list of attributes
169 * assumes reldesc caching works
172 expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
175 List *te_tail = NIL, *te_head = NIL;
177 int varattno, maxattrs;
182 rte = refnameRangeTableEntry(pstate->p_rtable, refname);
184 rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE, NULL);
186 rdesc = heap_open(rte->relid);
188 if (rdesc == NULL ) {
189 elog(WARN,"Unable to expand all -- heap_open failed on %s",
193 maxattrs = RelationGetNumberOfAttributes(rdesc);
195 for ( varattno = 0; varattno <= maxattrs-1 ; varattno++ ) {
197 char *resname = NULL;
198 TargetEntry *te = makeNode(TargetEntry);
200 attrname = pstrdup ((rdesc->rd_att->attrs[varattno]->attname).data);
201 varnode = (Var*)make_var(pstate, refname, attrname, &type_id);
202 type_len = (int)tlen(get_id_type(type_id));
204 handleTargetColname(pstate, &resname, refname, attrname);
208 /* Even if the elements making up a set are complex, the
209 * set itself is not. */
211 te->resdom = makeResdom((AttrNumber) (*this_resno)++,
218 te->expr = (Node *)varnode;
220 te_head = te_tail = lcons(te, NIL);
221 else te_tail = lappend(te_tail, te);
229 makeTimeRange(char *datestring1,
231 int timecode) /* 0 = snapshot , 1 = timerange */
233 TimeQual qual = NULL;
238 if (datestring1 == NULL) {
239 elog(WARN, "MakeTimeRange: bad snapshot arg");
241 t1 = nabstimein(datestring1);
242 if (!AbsoluteTimeIsValid(t1)) {
243 elog(WARN, "bad snapshot time: \"%s\"",
246 qual = TimeFormSnapshotTimeQual(t1);
249 if (datestring1 == NULL) {
250 t1 = NOSTART_ABSTIME;
252 t1 = nabstimein(datestring1);
253 if (!AbsoluteTimeIsValid(t1)) {
255 "bad range start time: \"%s\"",
259 if (datestring2 == NULL) {
262 t2 = nabstimein(datestring2);
263 if (!AbsoluteTimeIsValid(t2)) {
265 "bad range end time: \"%s\"",
269 qual = TimeFormRangedTimeQual(t1,t2);
272 elog(WARN, "MakeTimeRange: internal parser error");
278 disallow_setop(char *op, Type optype, Node *operand)
283 if (nodeTag(operand) == T_Iter) {
284 elog(NOTICE, "An operand to the '%s' operator returns a set of %s,",
286 elog(WARN, "but '%s' takes single values, not sets.",
292 make_operand(char *opname,
304 true_type = get_id_type(true_typeId);
305 disallow_setop(opname, true_type, result);
306 if (true_typeId != orig_typeId) { /* must coerce */
307 Const *con= (Const *)result;
309 Assert(nodeTag(result)==T_Const);
310 val = (Datum)textout((struct varlena *)
312 infunc = typeid_get_retinfunc(true_typeId);
313 con = makeNode(Const);
314 con->consttype = true_typeId;
315 con->constlen = tlen(true_type);
316 con->constvalue = (Datum)fmgr(infunc,
318 get_typelem(true_typeId),
319 -1 /* for varchar() type */);
320 con->constisnull = false;
321 con->constbyval = true;
322 con->constisset = false;
323 result = (Node *)con;
326 Const *con= makeNode(Const);
328 con->consttype = true_typeId;
330 con->constvalue = (Datum)(struct varlena *)NULL;
331 con->constisnull = true;
332 con->constbyval = true;
333 con->constisset = false;
334 result = (Node *)con;
342 make_op(char *opname, Node *ltree, Node *rtree)
344 Oid ltypeId, rtypeId;
346 OperatorTupleForm opform;
354 ltypeId = (ltree==NULL) ? UNKNOWNOID : exprType(ltree);
355 temp = right_oper(opname, ltypeId);
356 opform = (OperatorTupleForm) GETSTRUCT(temp);
357 left = make_operand(opname, ltree, ltypeId, opform->oprleft);
360 }else if (ltree == NULL) {
363 rtypeId = (rtree==NULL) ? UNKNOWNOID : exprType(rtree);
364 temp = left_oper(opname, rtypeId);
365 opform = (OperatorTupleForm) GETSTRUCT(temp);
366 right = make_operand(opname, rtree, rtypeId, opform->oprright);
371 /* binary operator */
372 ltypeId = (ltree==NULL) ? UNKNOWNOID : exprType(ltree);
373 rtypeId = (rtree==NULL) ? UNKNOWNOID : exprType(rtree);
374 temp = oper(opname, ltypeId, rtypeId);
375 opform = (OperatorTupleForm) GETSTRUCT(temp);
376 left = make_operand(opname, ltree, ltypeId, opform->oprleft);
377 right = make_operand(opname, rtree, rtypeId, opform->oprright);
380 newop = makeOper(oprid(temp), /* opno */
381 InvalidOid, /* opid */
382 opform->oprresult, /* operator result type */
386 result = makeNode(Expr);
387 result->typeOid = opform->oprresult;
388 result->opType = OP_EXPR;
389 result->oper = (Node *)newop;
392 result->args = lcons(right, NIL);
394 result->args = lcons(left, NIL);
396 result->args = lcons(left, lcons(right, NIL));
403 find_atttype(Oid relid, char *attrname)
409 rd = heap_open(relid);
410 if (!RelationIsValid(rd)) {
411 rd = heap_openr(tname(get_id_type(relid)));
412 if (!RelationIsValid(rd))
413 elog(WARN, "cannot compute type of att %s for relid %d",
417 attid = nf_varattno(rd, attrname);
419 if (attid == InvalidAttrNumber)
420 elog(WARN, "Invalid attribute %s\n", attrname);
422 vartype = att_typeid(rd , attid);
425 * close relation we're done with it now
434 make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id)
442 rte = refnameRangeTableEntry(pstate->p_rtable, refname);
444 rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE, NULL);
446 vnum = refnameRangeTablePosn(pstate->p_rtable, refname);
448 rd = heap_open(rte->relid);
450 attid = nf_varattno(rd, attrname);
451 if (attid == InvalidAttrNumber)
452 elog(WARN, "Invalid attribute %s\n", attrname);
453 vartypeid = att_typeid(rd, attid);
455 varnode = makeVar(vnum, attid, vartypeid, vnum, attid);
459 *type_id = vartypeid;
464 * make_array_ref() -- Make an array reference node.
466 * Array references can hang off of arbitrary nested dot (or
467 * function invocation) expressions. This routine takes a
468 * tree generated by ParseFunc() and an array index and
469 * generates a new array reference tree. We do some simple
470 * typechecking to be sure the dereference is valid in the
471 * type system, but we don't do any bounds checking here.
473 * indirection is a list of A_Indices
476 make_array_ref(Node *expr,
480 HeapTuple type_tuple;
481 TypeTupleForm type_struct_array, type_struct_element;
484 List *upperIndexpr=NIL;
485 List *lowerIndexpr=NIL;
487 typearray = exprType(expr);
489 type_tuple = SearchSysCacheTuple(TYPOID,
490 ObjectIdGetDatum(typearray),
493 if (!HeapTupleIsValid(type_tuple))
494 elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
497 /* get the array type struct from the type tuple */
498 type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple);
500 if (type_struct_array->typelem == InvalidOid) {
501 elog(WARN, "make_array_ref: type %s is not an array",
502 (Name)&(type_struct_array->typname.data[0]));
505 /* get the type tuple for the element type */
506 type_tuple = SearchSysCacheTuple(TYPOID,
507 ObjectIdGetDatum(type_struct_array->typelem),
509 if (!HeapTupleIsValid(type_tuple))
510 elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
513 type_struct_element = (TypeTupleForm) GETSTRUCT(type_tuple);
515 while(indirection!=NIL) {
516 A_Indices *ind = lfirst(indirection);
518 /* XXX assumes all lower indices non null in this case
520 lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
522 upperIndexpr = lappend(upperIndexpr, ind->uidx);
523 indirection = lnext(indirection);
525 aref = makeNode(ArrayRef);
526 aref->refattrlength = type_struct_array->typlen;
527 aref->refelemlength = type_struct_element->typlen;
528 aref->refelemtype = type_struct_array->typelem;
529 aref->refelembyval = type_struct_element->typbyval;
530 aref->refupperindexpr = upperIndexpr;
531 aref->reflowerindexpr = lowerIndexpr;
532 aref->refexpr = expr;
533 aref->refassgnexpr = NULL;
535 if (lowerIndexpr == NIL) /* accessing a single array element */
536 reftype = aref->refelemtype;
537 else /* request to clip a part of the array, the result is another array */
540 /* we change it to reflect the true type; since the original refelemtype
541 * doesn't seem to get used anywhere. - ay 10/94
543 aref->refelemtype = reftype;
549 make_array_set(Expr *target_expr,
555 HeapTuple type_tuple;
556 TypeTupleForm type_struct_array;
557 TypeTupleForm type_struct_element;
561 typearray = exprType((Node*)target_expr);
563 type_tuple = SearchSysCacheTuple(TYPOID,
564 ObjectIdGetDatum(typearray),
567 if (!HeapTupleIsValid(type_tuple))
568 elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
571 /* get the array type struct from the type tuple */
572 type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple);
574 if (type_struct_array->typelem == InvalidOid) {
575 elog(WARN, "make_array_ref: type %s is not an array",
576 (Name)&(type_struct_array->typname.data[0]));
578 /* get the type tuple for the element type */
579 type_tuple = SearchSysCacheTuple(TYPOID,
580 ObjectIdGetDatum(type_struct_array->typelem),
583 if (!HeapTupleIsValid(type_tuple))
584 elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
587 type_struct_element = (TypeTupleForm) GETSTRUCT(type_tuple);
589 aref = makeNode(ArrayRef);
590 aref->refattrlength = type_struct_array->typlen;
591 aref->refelemlength = type_struct_element->typlen;
592 aref->refelemtype = type_struct_array->typelem;
593 aref->refelembyval = type_struct_element->typbyval;
594 aref->refupperindexpr = upperIndexpr;
595 aref->reflowerindexpr = lowerIndexpr;
596 aref->refexpr = (Node*)target_expr;
597 aref->refassgnexpr = (Node*)expr;
599 if (lowerIndexpr == NIL) /* accessing a single array element */
600 reftype = aref->refelemtype;
601 else /* request to set a part of the array, by another array */
604 aref->refelemtype = reftype;
613 * - takes a lispvalue, (as returned to the yacc routine by the lexer)
614 * extracts the type, and makes the appropriate type constant
615 * by invoking the (c-callable) lisp routine c-make-const
616 * via the lisp_call() mechanism
618 * eventually, produces a "const" lisp-struct as per nodedefs.cl
621 make_const(Value *value)
627 switch(nodeTag(value)) {
630 val = Int32GetDatum(intVal(value));
638 dummy = (float64)palloc(sizeof(float64data));
639 *dummy = floatVal(value);
641 val = Float64GetDatum(dummy);
646 tp = type("unknown"); /* unknown for now, will be type coerced */
647 val = PointerGetDatum(textin(strVal(value)));
653 if (nodeTag(value)!=T_Null)
654 elog(NOTICE,"unknown type : %d\n", nodeTag(value));
657 /* if we don't set a type here, things will break. */
658 /* so set it to type 'unknown'. */
659 con = makeConst(UNKNOWNOID, 0, (Datum)NULL, TRUE, 0, FALSE);
664 con = makeConst(typeid(tp),
669 FALSE); /* not a set */
677 * keep enough information around fill out the type of param nodes
678 * used in postquel functions
681 param_type_init(Oid* typev, int nargs)
683 pfunc_num_args = nargs;
684 param_type_info = typev;
690 if ((t >pfunc_num_args) ||(t ==0)) return InvalidOid;
691 return param_type_info[t-1];
695 * handleTargetColname -
696 * use column names from insert
699 handleTargetColname(ParseState *pstate, char **resname,
700 char *refname, char *colname)
702 if (pstate->p_is_insert) {
703 if (pstate->p_insert_columns != NIL ) {
704 Ident *id = lfirst(pstate->p_insert_columns);
706 pstate->p_insert_columns = lnext(pstate->p_insert_columns);
709 elog(WARN, "insert: more expressions than target columns");
711 if (pstate->p_is_insert||pstate->p_is_update)
712 checkTargetTypes(pstate, *resname, refname, colname);
717 * checks value and target column types
720 checkTargetTypes(ParseState *pstate, char *target_colname,
721 char *refname, char *colname)
723 Oid attrtype_id, attrtype_target;
724 int resdomno_id, resdomno_target;
728 if (target_colname == NULL || colname == NULL)
732 rte = refnameRangeTableEntry(pstate->p_rtable, refname);
734 rte = colnameRangeTableEntry(pstate, colname);
735 refname = rte->refname;
739 if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
740 elog(WARN, "%s not available in this context", colname);
742 rd = heap_open(rte->relid);
744 resdomno_id = varattno(rd,colname);
745 attrtype_id = att_typeid(rd,resdomno_id);
747 resdomno_target = varattno(pstate->p_target_relation,target_colname);
748 attrtype_target = att_typeid(pstate->p_target_relation, resdomno_target);
750 if (attrtype_id != attrtype_target)
751 elog(WARN, "Type of %s does not match target column %s",
752 colname, target_colname);
754 if ((attrtype_id == BPCHAROID || attrtype_id == VARCHAROID) &&
755 rd->rd_att->attrs[resdomno_id-1]->attlen !=
756 pstate->p_target_relation->rd_att->attrs[resdomno_target-1]->attlen)
757 elog(WARN, "Length of %s does not match length of target column %s",
758 colname, target_colname);