]> granicus.if.org Git - postgresql/blob - src/backend/parser/parse_query.c
This patch changes quite a few instances of references of Oid's
[postgresql] / src / backend / parser / parse_query.c
1 /*-------------------------------------------------------------------------
2  *
3  * parse_query.c--
4  *    take an "optimizable" stmt and make the query tree that
5  *     the planner requires.
6  *
7  * Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *    $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.10 1996/11/30 18:06:34 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include <ctype.h>
16 #include <string.h>
17 #include "postgres.h"
18
19 #include "fmgr.h"
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 */
28
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"
35
36 #include "nodes/pg_list.h"
37 #include "nodes/primnodes.h"
38 #include "nodes/parsenodes.h"
39 #include "nodes/makefuncs.h"
40
41 Oid *param_type_info;
42 int pfunc_num_args;
43
44 /* given refname, return a pointer to the range table entry */
45 RangeTblEntry *
46 refnameRangeTableEntry(List *rtable, char *refname)
47 {
48     List *temp;
49     
50     foreach(temp, rtable) {
51         RangeTblEntry *rte = lfirst(temp);
52
53         if (!strcmp(rte->refname, refname))
54             return rte;
55     }
56     return NULL;
57 }
58
59 /* given refname, return id of variable; position starts with 1 */
60 int
61 refnameRangeTablePosn(List *rtable, char *refname)
62 {
63     int index;
64     List *temp;
65     
66     index = 1;
67     foreach(temp, rtable) {
68         RangeTblEntry *rte = lfirst(temp);
69
70         if (!strcmp(rte->refname, refname))
71             return index;
72         index++;
73     }
74     return(0);
75 }
76
77 /*
78  * returns range entry if found, else NULL
79  */
80 RangeTblEntry *
81 colnameRangeTableEntry(ParseState *pstate, char *colname)
82 {
83     List *et;
84     List *rtable;
85     RangeTblEntry *rte_result;
86
87     if (pstate->p_is_rule)
88         rtable = lnext(lnext(pstate->p_rtable));
89     else
90         rtable = pstate->p_rtable;
91
92     rte_result = NULL;
93     foreach(et, rtable) {
94         RangeTblEntry *rte = lfirst(et);
95
96                 /* only entries on outer(non-function?) scope */
97         if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
98             continue;
99
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);
105             }
106             else rte_result = rte;
107         }
108     }
109     return rte_result;
110 }
111
112 /*
113  * put new entry in pstate p_rtable structure, or return pointer
114  * if pstate null
115 */
116 RangeTblEntry *
117 addRangeTableEntry(ParseState *pstate,
118                     char *relname,
119                     char *refname,
120                     bool inh, bool inFromCl,
121                     TimeRange *timeRange)
122 {
123     Relation relation;
124     RangeTblEntry *rte = makeNode(RangeTblEntry);
125
126     if (pstate != NULL &&
127         refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
128         elog(WARN,"Table name %s specified more than once",refname);
129         
130     rte->relname = pstrdup(relname);
131     rte->refname = pstrdup(refname);
132
133     relation = heap_openr(relname);
134     if (relation == NULL) {
135         elog(WARN,"%s: %s",
136              relname, ACL_NO_PRIV_WARNING);
137     }
138
139     /*
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 ]
143      */
144     rte->inh = inh;
145
146     rte->timeRange = timeRange;
147     
148     /* RelOID */
149     rte->relid = RelationGetRelationId(relation);
150
151     rte->archive = false;
152
153     rte->inFromCl = inFromCl;
154
155     /*
156      * close the relation we're done with it for now.
157      */
158     if (pstate != NULL)
159         pstate->p_rtable = lappend(pstate->p_rtable, rte);
160
161     heap_close(relation);
162
163     return rte;
164 }
165
166 /*
167  * expandAll -
168  *    makes a list of attributes
169  *    assumes reldesc caching works
170  */
171 List *
172 expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
173 {
174     Relation rdesc;
175     List *te_tail = NIL, *te_head = NIL;
176     Var *varnode;
177     int varattno, maxattrs;
178     Oid type_id;
179     int type_len;
180     RangeTblEntry *rte;
181    
182     rte = refnameRangeTableEntry(pstate->p_rtable, refname);
183     if (rte == NULL)
184         rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE, NULL);
185     
186     rdesc = heap_open(rte->relid);
187     
188     if (rdesc == NULL ) {
189         elog(WARN,"Unable to expand all -- heap_open failed on %s",
190              rte->refname);
191         return NIL;
192     }
193     maxattrs = RelationGetNumberOfAttributes(rdesc);
194     
195     for ( varattno = 0; varattno <= maxattrs-1 ; varattno++ ) {
196         char *attrname;
197         char *resname = NULL;
198         TargetEntry *te = makeNode(TargetEntry);
199         
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));
203
204         handleTargetColname(pstate, &resname, refname, attrname);
205         if (resname != NULL)
206                 attrname = resname;
207         
208         /* Even if the elements making up a set are complex, the
209          * set itself is not. */
210         
211         te->resdom = makeResdom((AttrNumber) (*this_resno)++,
212                                  type_id,
213                                  (Size)type_len,
214                                  attrname,
215                                  (Index)0,
216                                  (Oid)0,
217                                  0);
218         te->expr = (Node *)varnode;
219         if (te_head == NIL)
220                 te_head = te_tail = lcons(te, NIL);
221         else    te_tail = lappend(te_tail, te);
222     }
223     
224     heap_close(rdesc);
225     return(te_head);
226 }
227
228 TimeQual
229 makeTimeRange(char *datestring1,
230               char *datestring2,
231               int timecode)     /* 0 = snapshot , 1 = timerange */
232 {
233     TimeQual    qual = NULL;
234     AbsoluteTime t1,t2;
235     
236     switch (timecode) {
237     case 0:
238         if (datestring1 == NULL) {
239             elog(WARN, "MakeTimeRange: bad snapshot arg");
240         }
241         t1 = nabstimein(datestring1);
242         if (!AbsoluteTimeIsValid(t1)) {
243             elog(WARN, "bad snapshot time: \"%s\"",
244                  datestring1);
245         }
246         qual = TimeFormSnapshotTimeQual(t1);
247         break;
248     case 1:
249         if (datestring1 == NULL) {
250             t1 = NOSTART_ABSTIME;
251         } else {
252             t1 = nabstimein(datestring1);
253             if (!AbsoluteTimeIsValid(t1)) {
254                 elog(WARN,
255                      "bad range start time: \"%s\"",
256                      datestring1);
257             }
258         }
259         if (datestring2 == NULL) {
260             t2 = NOEND_ABSTIME;
261         } else {
262             t2 = nabstimein(datestring2);
263             if (!AbsoluteTimeIsValid(t2)) {
264                 elog(WARN,
265                      "bad range end time: \"%s\"",
266                      datestring2);
267             }
268         }
269         qual = TimeFormRangedTimeQual(t1,t2);
270         break;
271     default:
272         elog(WARN, "MakeTimeRange: internal parser error");
273     }
274     return qual;
275 }
276
277 static void
278 disallow_setop(char *op, Type optype, Node *operand)
279 {
280     if (operand==NULL)
281         return;
282     
283     if (nodeTag(operand) == T_Iter) {
284         elog(NOTICE, "An operand to the '%s' operator returns a set of %s,",
285              op, tname(optype));
286         elog(WARN, "but '%s' takes single values, not sets.",
287              op);
288     }
289 }
290
291 static Node *
292 make_operand(char *opname,
293              Node *tree,
294              Oid orig_typeId,
295              Oid true_typeId)
296 {
297     Node *result;
298     Type true_type;
299     Datum val;
300     Oid infunc;
301     
302     if (tree != NULL) {
303         result = tree;
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;
308
309             Assert(nodeTag(result)==T_Const);
310             val = (Datum)textout((struct varlena *)
311                                  con->constvalue);
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,
317                                           val,
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;
324         }
325     }else {
326         Const *con= makeNode(Const);
327
328         con->consttype = true_typeId;
329         con->constlen = 0;
330         con->constvalue = (Datum)(struct varlena *)NULL;
331         con->constisnull = true;
332         con->constbyval = true;
333         con->constisset = false;
334         result = (Node *)con;
335     }
336     
337     return result;
338 }
339
340
341 Expr *
342 make_op(char *opname, Node *ltree, Node *rtree)
343 {
344     Oid ltypeId, rtypeId;
345     Operator temp;
346     OperatorTupleForm opform;
347     Oper *newop;
348     Node *left, *right;
349     Expr *result;
350     
351     if (rtree == NULL) {
352
353         /* right operator */
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);
358         right = NULL;
359
360     }else if (ltree == NULL) {
361
362         /* left operator */
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);
367         left = NULL;
368
369     }else {
370
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);
378     }
379
380     newop = makeOper(oprid(temp),       /* opno */
381                      InvalidOid,        /* opid */
382                      opform->oprresult, /* operator result type */
383                      0,
384                      NULL);
385
386     result = makeNode(Expr);
387     result->typeOid = opform->oprresult;
388     result->opType = OP_EXPR;
389     result->oper = (Node *)newop;
390
391     if (!left) {
392         result->args = lcons(right, NIL);
393     } else if (!right) {
394         result->args = lcons(left, NIL);
395     } else {
396         result->args = lcons(left, lcons(right, NIL));
397     }
398
399     return result;
400 }
401
402 Oid
403 find_atttype(Oid relid, char *attrname)
404 {
405     int attid;
406     Oid vartype;
407     Relation rd;
408     
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",
414                  attrname, relid);
415     }
416     
417     attid =  nf_varattno(rd, attrname);
418     
419     if (attid == InvalidAttrNumber) 
420         elog(WARN, "Invalid attribute %s\n", attrname);
421     
422     vartype = att_typeid(rd , attid);
423     
424     /*
425      * close relation we're done with it now
426      */
427     heap_close(rd);
428     
429     return (vartype);
430 }
431
432
433 Var *
434 make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id)
435 {
436     Var *varnode;
437     int vnum, attid;
438     Oid vartypeid;
439     Relation rd;
440     RangeTblEntry *rte;
441
442     rte = refnameRangeTableEntry(pstate->p_rtable, refname);
443     if (rte == NULL)
444         rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE, NULL);
445
446     vnum = refnameRangeTablePosn(pstate->p_rtable, refname);
447
448     rd = heap_open(rte->relid);
449
450     attid =  nf_varattno(rd, attrname);
451     if (attid == InvalidAttrNumber) 
452         elog(WARN, "Invalid attribute %s\n", attrname);
453     vartypeid = att_typeid(rd, attid);
454
455     varnode = makeVar(vnum, attid, vartypeid, vnum, attid);
456
457     heap_close(rd);
458
459     *type_id = vartypeid;
460     return varnode;
461 }
462
463 /*
464  *  make_array_ref() -- Make an array reference node.
465  *
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.
472  *
473  *  indirection is a list of A_Indices
474  */
475 ArrayRef *
476 make_array_ref(Node *expr,
477                List *indirection)
478 {
479     Oid           typearray;
480     HeapTuple     type_tuple;
481     TypeTupleForm type_struct_array, type_struct_element;
482     ArrayRef      *aref;
483     Oid           reftype;
484     List *upperIndexpr=NIL;
485     List *lowerIndexpr=NIL;
486     
487     typearray = exprType(expr);
488     
489     type_tuple = SearchSysCacheTuple(TYPOID, 
490                                      ObjectIdGetDatum(typearray), 
491                                      0,0,0);
492     
493     if (!HeapTupleIsValid(type_tuple))
494         elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
495              typearray);
496     
497     /* get the array type struct from the type tuple */
498     type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple);
499     
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]));
503     }
504     
505     /* get the type tuple for the element type */
506     type_tuple = SearchSysCacheTuple(TYPOID, 
507                              ObjectIdGetDatum(type_struct_array->typelem),
508                                      0,0,0);
509     if (!HeapTupleIsValid(type_tuple))
510         elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
511              typearray);
512     
513     type_struct_element = (TypeTupleForm) GETSTRUCT(type_tuple);
514
515     while(indirection!=NIL) {
516         A_Indices *ind = lfirst(indirection);
517         if (ind->lidx) {
518             /* XXX assumes all lower indices non null in this case
519              */
520             lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
521         }
522         upperIndexpr = lappend(upperIndexpr, ind->uidx);
523         indirection = lnext(indirection);
524     }
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;
534
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 */
538         reftype = typearray;
539
540     /* we change it to reflect the true type; since the original refelemtype
541      * doesn't seem to get used anywhere. - ay 10/94
542      */
543     aref->refelemtype = reftype;        
544
545     return aref;
546 }
547
548 ArrayRef *
549 make_array_set(Expr *target_expr,
550                List *upperIndexpr,
551                List *lowerIndexpr,
552                Expr *expr)
553 {
554     Oid           typearray;
555     HeapTuple     type_tuple;
556     TypeTupleForm type_struct_array;
557     TypeTupleForm type_struct_element;
558     ArrayRef      *aref;
559     Oid           reftype;
560     
561     typearray = exprType((Node*)target_expr);
562     
563     type_tuple = SearchSysCacheTuple(TYPOID, 
564                                      ObjectIdGetDatum(typearray), 
565                                      0,0,0);
566     
567     if (!HeapTupleIsValid(type_tuple))
568         elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
569              typearray);
570     
571     /* get the array type struct from the type tuple */
572     type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple);
573     
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]));
577     }
578     /* get the type tuple for the element type */
579     type_tuple = SearchSysCacheTuple(TYPOID, 
580                                      ObjectIdGetDatum(type_struct_array->typelem),
581                                      0,0,0);
582     
583     if (!HeapTupleIsValid(type_tuple))
584         elog(WARN, "make_array_ref: Cache lookup failed for type %d\n",
585              typearray);
586     
587     type_struct_element = (TypeTupleForm) GETSTRUCT(type_tuple);
588     
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;
598
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 */
602         reftype = typearray;
603
604     aref->refelemtype = reftype;
605     
606     return aref;
607 }
608
609 /*
610  * 
611  * make_const -
612  * 
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
617  *
618  * eventually, produces a "const" lisp-struct as per nodedefs.cl
619  */ 
620 Const *
621 make_const(Value *value)
622 {
623     Type tp;
624     Datum val;
625     Const *con;
626     
627     switch(nodeTag(value)) {
628     case T_Integer:
629         tp = type("int4");
630         val = Int32GetDatum(intVal(value));
631         break;
632         
633     case T_Float:
634         {
635             float64 dummy;
636             tp = type("float8");
637             
638             dummy = (float64)palloc(sizeof(float64data));
639             *dummy = floatVal(value);
640             
641             val = Float64GetDatum(dummy);
642         }
643         break;
644         
645     case T_String:
646         tp = type("unknown"); /* unknown for now, will be type coerced */
647         val = PointerGetDatum(textin(strVal(value)));
648         break;
649
650     case T_Null:
651     default:
652         {
653             if (nodeTag(value)!=T_Null)
654                 elog(NOTICE,"unknown type : %d\n", nodeTag(value));
655
656             /* null const */
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);
660             return con;
661         }
662     }
663
664     con = makeConst(typeid(tp),
665                     tlen(tp),
666                     val,
667                     FALSE,
668                     tbyval(tp),
669                     FALSE); /* not a set */
670
671     return (con);
672 }
673
674 /*
675  * param_type_init()
676  *
677  * keep enough information around fill out the type of param nodes
678  * used in postquel functions
679  */
680 void
681 param_type_init(Oid* typev, int nargs)
682 {
683     pfunc_num_args = nargs;
684     param_type_info = typev;
685 }
686
687 Oid
688 param_type(int t)
689 {
690     if ((t >pfunc_num_args) ||(t ==0)) return InvalidOid;
691     return param_type_info[t-1];
692 }
693
694 /*
695  * handleTargetColname -
696  *    use column names from insert
697  */
698 void
699 handleTargetColname(ParseState *pstate, char **resname,
700                                         char *refname, char *colname)
701 {
702     if (pstate->p_is_insert) {
703         if (pstate->p_insert_columns != NIL ) {
704             Ident *id = lfirst(pstate->p_insert_columns);
705             *resname = id->name;
706             pstate->p_insert_columns = lnext(pstate->p_insert_columns);
707         }
708         else
709             elog(WARN, "insert: more expressions than target columns");
710     }
711     if (pstate->p_is_insert||pstate->p_is_update)
712         checkTargetTypes(pstate, *resname, refname, colname);
713 }
714
715 /*
716  * checkTargetTypes -
717  *    checks value and target column types
718  */
719 void
720 checkTargetTypes(ParseState *pstate, char *target_colname,
721                                         char *refname, char *colname)
722 {
723     Oid attrtype_id, attrtype_target;
724     int resdomno_id, resdomno_target;
725     Relation rd;
726     RangeTblEntry *rte;
727     
728     if (target_colname == NULL || colname == NULL)
729         return;
730         
731     if (refname != NULL)
732         rte = refnameRangeTableEntry(pstate->p_rtable, refname);
733     else {
734         rte = colnameRangeTableEntry(pstate, colname);
735         refname = rte->refname;
736     }
737
738 /*
739     if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
740         elog(WARN, "%s not available in this context", colname);
741 */
742     rd = heap_open(rte->relid);
743
744     resdomno_id = varattno(rd,colname);
745     attrtype_id = att_typeid(rd,resdomno_id);
746
747     resdomno_target = varattno(pstate->p_target_relation,target_colname);
748     attrtype_target = att_typeid(pstate->p_target_relation, resdomno_target);
749
750     if (attrtype_id != attrtype_target)
751         elog(WARN, "Type of %s does not match target column %s",
752             colname, target_colname);
753
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);
759
760     heap_close(rd);
761 }
762