]> granicus.if.org Git - postgresql/blob - src/backend/parser/parse_node.c
0b48beb049155984e0aa4093f05887e0526b35fe
[postgresql] / src / backend / parser / parse_node.c
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: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.36 2000/01/17 02:04:16 tgl Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <ctype.h>
15
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_coerce.h"
23 #include "parser/parse_expr.h"
24 #include "parser/parse_node.h"
25 #include "parser/parse_oper.h"
26 #include "parser/parse_relation.h"
27 #include "parser/parse_target.h"
28 #include "parser/parse_type.h"
29 #include "utils/builtins.h"
30 #include "utils/lsyscache.h"
31 #include "utils/syscache.h"
32
33 static void disallow_setop(char *op, Type optype, Node *operand);
34
35 /* make_parsestate()
36  * Allocate and initialize a new ParseState.
37  * The CALLER is responsible for freeing the ParseState* returned.
38  */
39 ParseState *
40 make_parsestate(ParseState *parentParseState)
41 {
42         ParseState *pstate;
43
44         pstate = palloc(sizeof(ParseState));
45         MemSet(pstate, 0, sizeof(ParseState));
46
47         pstate->p_last_resno = 1;
48         pstate->parentParseState = parentParseState;
49
50         return pstate;
51 }
52
53
54 /* make_operand()
55  * Ensure argument type match by forcing conversion of constants.
56  */
57 Node *
58 make_operand(char *opname,
59                          Node *tree,
60                          Oid orig_typeId,
61                          Oid target_typeId)
62 {
63         Node       *result;
64         Type            target_type = typeidType(target_typeId);
65
66         if (tree != NULL)
67         {
68                 disallow_setop(opname, target_type, tree);
69                 /* must coerce? */
70                 if (target_typeId != orig_typeId)
71                         result = coerce_type(NULL, tree, orig_typeId, target_typeId, -1);
72                 else
73                         result = tree;
74         }
75         else
76         {
77                 /* otherwise, this is a NULL value */
78                 Const      *con = makeNode(Const);
79
80                 con->consttype = target_typeId;
81                 con->constlen = typeLen(target_type);
82                 con->constvalue = (Datum) NULL;
83                 con->constisnull = true;
84                 con->constbyval = typeByVal(target_type);
85                 con->constisset = false;
86                 result = (Node *) con;
87         }
88
89         return result;
90 }       /* make_operand() */
91
92
93 static void
94 disallow_setop(char *op, Type optype, Node *operand)
95 {
96         if (operand == NULL)
97                 return;
98
99         if (nodeTag(operand) == T_Iter)
100         {
101                 elog(ERROR, "An operand to the '%s' operator returns a set of %s,"
102                          "\n\tbut '%s' takes single values, not sets.",
103                          op, typeTypeName(optype), op);
104         }
105 }
106
107
108 /* make_op()
109  * Operator construction.
110  *
111  * Transform operator expression ensuring type compatibility.
112  * This is where some type conversion happens.
113  */
114 Expr *
115 make_op(char *opname, Node *ltree, Node *rtree)
116 {
117         Oid                     ltypeId,
118                                 rtypeId;
119         Operator        tup;
120         Form_pg_operator opform;
121         Oper       *newop;
122         Node       *left,
123                            *right;
124         Expr       *result;
125
126         ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
127         rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
128
129         /* right operator? */
130         if (rtree == NULL)
131         {
132                 tup = right_oper(opname, ltypeId);
133                 opform = (Form_pg_operator) GETSTRUCT(tup);
134                 left = make_operand(opname, ltree, ltypeId, opform->oprleft);
135                 right = NULL;
136         }
137
138         /* left operator? */
139         else if (ltree == NULL)
140         {
141                 tup = left_oper(opname, rtypeId);
142                 opform = (Form_pg_operator) GETSTRUCT(tup);
143                 right = make_operand(opname, rtree, rtypeId, opform->oprright);
144                 left = NULL;
145         }
146
147         /* otherwise, binary operator */
148         else
149         {
150                 tup = oper(opname, ltypeId, rtypeId, FALSE);
151                 opform = (Form_pg_operator) GETSTRUCT(tup);
152                 left = make_operand(opname, ltree, ltypeId, opform->oprleft);
153                 right = make_operand(opname, rtree, rtypeId, opform->oprright);
154         }
155
156         newop = makeOper(oprid(tup),/* opno */
157                                          InvalidOid,/* opid */
158                                          opform->oprresult, /* operator result type */
159                                          0,
160                                          NULL);
161
162         result = makeNode(Expr);
163         result->typeOid = opform->oprresult;
164         result->opType = OP_EXPR;
165         result->oper = (Node *) newop;
166
167         if (!left)
168                 result->args = lcons(right, NIL);
169         else if (!right)
170                 result->args = lcons(left, NIL);
171         else
172                 result->args = lcons(left, lcons(right, NIL));
173
174         return result;
175 }       /* make_op() */
176
177
178 /*
179  * make_var
180  *              Build a Var node for an attribute identified by name
181  */
182 Var *
183 make_var(ParseState *pstate, Oid relid, char *refname,
184                  char *attrname)
185 {
186         HeapTuple       tp;
187         Form_pg_attribute att_tup;
188         int                     vnum,
189                                 attid;
190         Oid                     vartypeid;
191         int32           type_mod;
192         int                     sublevels_up;
193
194         vnum = refnameRangeTablePosn(pstate, refname, &sublevels_up);
195
196         tp = SearchSysCacheTuple(ATTNAME,
197                                                          ObjectIdGetDatum(relid),
198                                                          PointerGetDatum(attrname),
199                                                          0, 0);
200         if (!HeapTupleIsValid(tp))
201                 elog(ERROR, "Relation %s does not have attribute %s",
202                          refname, attrname);
203         att_tup = (Form_pg_attribute) GETSTRUCT(tp);
204         attid = att_tup->attnum;
205         vartypeid = att_tup->atttypid;
206         type_mod = att_tup->atttypmod;
207
208         return makeVar(vnum, attid, vartypeid, type_mod, sublevels_up);
209 }
210
211 /*
212  * transformArraySubscripts()
213  *              Transform array subscripting.  This is used for both
214  *              array fetch and array assignment.
215  *
216  * In an array fetch, we are given a source array value and we produce an
217  * expression that represents the result of extracting a single array element
218  * or an array slice.
219  *
220  * In an array assignment, we are given a destination array value plus a
221  * source value that is to be assigned to a single element or a slice of
222  * that array.  We produce an expression that represents the new array value
223  * with the source data inserted into the right part of the array.
224  *
225  * pstate               Parse state
226  * arrayBase    Already-transformed expression for the array as a whole
227  * indirection  Untransformed list of subscripts (must not be NIL)
228  * forceSlice   If true, treat subscript as array slice in all cases
229  * assignFrom   NULL for array fetch, else transformed expression for source.
230  */
231 ArrayRef *
232 transformArraySubscripts(ParseState *pstate,
233                                                  Node *arrayBase,
234                                                  List *indirection,
235                                                  bool forceSlice,
236                                                  Node *assignFrom)
237 {
238         Oid                     typearray,
239                                 typeelement,
240                                 typeresult;
241         HeapTuple       type_tuple;
242         Form_pg_type type_struct_array,
243                                 type_struct_element;
244         bool            isSlice = forceSlice;
245         List       *upperIndexpr = NIL;
246         List       *lowerIndexpr = NIL;
247         List       *idx;
248         ArrayRef   *aref;
249
250         /* Get the type tuple for the array */
251         typearray = exprType(arrayBase);
252
253         type_tuple = SearchSysCacheTuple(TYPEOID,
254                                                                          ObjectIdGetDatum(typearray),
255                                                                          0, 0, 0);
256         if (!HeapTupleIsValid(type_tuple))
257                 elog(ERROR, "transformArraySubscripts: Cache lookup failed for array type %u",
258                          typearray);
259         type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple);
260
261         typeelement = type_struct_array->typelem;
262         if (typeelement == InvalidOid)
263                 elog(ERROR, "transformArraySubscripts: type %s is not an array",
264                          NameStr(type_struct_array->typname));
265
266         /* Get the type tuple for the array element type */
267         type_tuple = SearchSysCacheTuple(TYPEOID,
268                                                                          ObjectIdGetDatum(typeelement),
269                                                                          0, 0, 0);
270         if (!HeapTupleIsValid(type_tuple))
271                 elog(ERROR, "transformArraySubscripts: Cache lookup failed for array element type %u",
272                          typeelement);
273         type_struct_element = (Form_pg_type) GETSTRUCT(type_tuple);
274
275         /*
276          * A list containing only single subscripts refers to a single array
277          * element.  If any of the items are double subscripts (lower:upper),
278          * then the subscript expression means an array slice operation.
279          * In this case, we supply a default lower bound of 1 for any items
280          * that contain only a single subscript.
281          * The forceSlice parameter forces us to treat the operation as a
282          * slice, even if no lower bounds are mentioned.  Otherwise,
283          * we have to prescan the indirection list to see if there are any
284          * double subscripts.
285          */
286         if (! isSlice)
287         {
288                 foreach (idx, indirection)
289                 {
290                         A_Indices  *ai = (A_Indices *) lfirst(idx);
291                         if (ai->lidx != NULL)
292                         {
293                                 isSlice = true;
294                                 break;
295                         }
296                 }
297         }
298
299         /* The type represented by the subscript expression is the element type
300          * if we are fetching a single element, but it is the same as the array
301          * type if we are fetching a slice or storing.
302          */
303         if (isSlice || assignFrom != NULL)
304                 typeresult = typearray;
305         else
306                 typeresult = typeelement;
307
308         /*
309          * Transform the subscript expressions.
310          */
311         foreach (idx, indirection)
312         {
313                 A_Indices  *ai = (A_Indices *) lfirst(idx);
314                 Node       *subexpr;
315
316                 if (isSlice)
317                 {
318                         if (ai->lidx)
319                         {
320                                 subexpr = transformExpr(pstate, ai->lidx, EXPR_COLUMN_FIRST);
321                                 /* If it's not int4 already, try to coerce */
322                                 subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
323                                                                                    INT4OID, -1);
324                                 if (subexpr == NULL)
325                                         elog(ERROR, "array index expressions must be integers");
326                         }
327                         else
328                         {
329                                 /* Make a constant 1 */
330                                 subexpr = (Node *) makeConst(INT4OID,
331                                                                                          sizeof(int32),
332                                                                                          Int32GetDatum(1),
333                                                                                          false,
334                                                                                          true, /* pass by value */
335                                                                                          false,
336                                                                                          false);
337                         }
338                         lowerIndexpr = lappend(lowerIndexpr, subexpr);
339                 }
340                 subexpr = transformExpr(pstate, ai->uidx, EXPR_COLUMN_FIRST);
341                 /* If it's not int4 already, try to coerce */
342                 subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
343                                                                    INT4OID, -1);
344                 if (subexpr == NULL)
345                         elog(ERROR, "array index expressions must be integers");
346                 upperIndexpr = lappend(upperIndexpr, subexpr);
347         }
348
349         /*
350          * If doing an array store, coerce the source value to the right type.
351          */
352         if (assignFrom != NULL)
353         {
354                 Oid                     typesource = exprType(assignFrom);
355                 Oid                     typeneeded = isSlice ? typearray : typeelement;
356
357                 if (typesource != InvalidOid)
358                 {
359                         if (typesource != typeneeded)
360                         {
361                                 /* XXX fixme: need to get the array's atttypmod? */
362                                 assignFrom = CoerceTargetExpr(pstate, assignFrom,
363                                                                                           typesource, typeneeded,
364                                                                                           -1);
365                                 if (assignFrom == NULL)
366                                         elog(ERROR, "Array assignment requires type '%s'"
367                                                  " but expression is of type '%s'"
368                                                  "\n\tYou will need to rewrite or cast the expression",
369                                                  typeidTypeName(typeneeded),
370                                                  typeidTypeName(typesource));
371                         }
372                 }
373         }
374
375         /*
376          * Ready to build the ArrayRef node.
377          */
378         aref = makeNode(ArrayRef);
379         aref->refattrlength = type_struct_array->typlen;
380         aref->refelemlength = type_struct_element->typlen;
381         aref->refelemtype = typeresult; /* XXX should save element type too */
382         aref->refelembyval = type_struct_element->typbyval;
383         aref->refupperindexpr = upperIndexpr;
384         aref->reflowerindexpr = lowerIndexpr;
385         aref->refexpr = arrayBase;
386         aref->refassgnexpr = assignFrom;
387
388         return aref;
389 }
390
391 /*
392  * make_const
393  *
394  *      Convert a Value node (as returned by the grammar) to a Const node
395  *      of the "natural" type for the constant.  For strings we produce
396  *      a constant of type UNKNOWN ---- representation is the same as text,
397  *      but this indicates to later type resolution that we're not sure that
398  *      it should be considered text.  Explicit "NULL" constants are also
399  *      typed as UNKNOWN.
400  */
401 Const *
402 make_const(Value *value)
403 {
404         Datum           val;
405         Oid                     typeid;
406         int                     typelen;
407         bool            typebyval;
408         Const      *con;
409
410         switch (nodeTag(value))
411         {
412                 case T_Integer:
413                         val = Int32GetDatum(intVal(value));
414
415                         typeid = INT4OID;
416                         typelen = sizeof(int32);
417                         typebyval = true;
418                         break;
419
420                 case T_Float:
421                         {
422                                 float64         dummy;
423
424                                 dummy = (float64) palloc(sizeof(float64data));
425                                 *dummy = floatVal(value);
426
427                                 val = Float64GetDatum(dummy);
428
429                                 typeid = FLOAT8OID;
430                                 typelen = sizeof(float64data);
431                                 typebyval = false;
432                         }
433                         break;
434
435                 case T_String:
436                         val = PointerGetDatum(textin(strVal(value)));
437
438                         typeid = UNKNOWNOID; /* will be coerced later */
439                         typelen = -1;           /* variable len */
440                         typebyval = false;
441                         break;
442
443                 case T_Null:
444                 default:
445                         if (nodeTag(value) != T_Null)
446                                 elog(NOTICE, "make_const: unknown type %d\n", nodeTag(value));
447
448                         /* return a null const */
449                         con = makeConst(UNKNOWNOID,
450                                                         -1,
451                                                         (Datum) NULL,
452                                                         true,
453                                                         false,
454                                                         false,
455                                                         false);
456                         return con;
457         }
458
459         con = makeConst(typeid,
460                                         typelen,
461                                         val,
462                                         false,
463                                         typebyval,
464                                         false,          /* not a set */
465                                         false);         /* not coerced */
466
467         return con;
468 }