]> granicus.if.org Git - postgresql/blob - src/backend/parser/parse_node.c
Implement feature of new FE/BE protocol whereby RowDescription identifies
[postgresql] / src / backend / parser / parse_node.c
1 /*-------------------------------------------------------------------------
2  *
3  * parse_node.c
4  *        various routines that make nodes for querytrees
5  *
6  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.78 2003/04/29 22:13:10 tgl Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "catalog/pg_type.h"
18 #include "nodes/makefuncs.h"
19 #include "parser/parsetree.h"
20 #include "parser/parse_coerce.h"
21 #include "parser/parse_expr.h"
22 #include "parser/parse_node.h"
23 #include "parser/parse_relation.h"
24 #include "utils/builtins.h"
25 #include "utils/int8.h"
26 #include "utils/syscache.h"
27 #include "utils/varbit.h"
28
29
30 /* make_parsestate()
31  * Allocate and initialize a new ParseState.
32  * The CALLER is responsible for freeing the ParseState* returned.
33  */
34 ParseState *
35 make_parsestate(ParseState *parentParseState)
36 {
37         ParseState *pstate;
38
39         pstate = palloc0(sizeof(ParseState));
40
41         pstate->parentParseState = parentParseState;
42
43         /* Fill in fields that don't start at null/false/zero */
44         pstate->p_next_resno = 1;
45
46         if (parentParseState)
47                 pstate->p_variableparams = parentParseState->p_variableparams;
48
49         return pstate;
50 }
51
52
53 /*
54  * make_var
55  *              Build a Var node for an attribute identified by RTE and attrno
56  */
57 Var *
58 make_var(ParseState *pstate, RangeTblEntry *rte, int attrno)
59 {
60         int                     vnum,
61                                 sublevels_up;
62         Oid                     vartypeid;
63         int32           type_mod;
64
65         vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
66         get_rte_attribute_type(rte, attrno, &vartypeid, &type_mod);
67         return makeVar(vnum, attrno, vartypeid, type_mod, sublevels_up);
68 }
69
70 /*
71  * transformArraySubscripts()
72  *              Transform array subscripting.  This is used for both
73  *              array fetch and array assignment.
74  *
75  * In an array fetch, we are given a source array value and we produce an
76  * expression that represents the result of extracting a single array element
77  * or an array slice.
78  *
79  * In an array assignment, we are given a destination array value plus a
80  * source value that is to be assigned to a single element or a slice of
81  * that array.  We produce an expression that represents the new array value
82  * with the source data inserted into the right part of the array.
83  *
84  * pstate               Parse state
85  * arrayBase    Already-transformed expression for the array as a whole
86  *                              (may be NULL if we are handling an INSERT)
87  * arrayType    OID of array's datatype
88  * arrayTypMod  typmod to be applied to array elements
89  * indirection  Untransformed list of subscripts (must not be NIL)
90  * forceSlice   If true, treat subscript as array slice in all cases
91  * assignFrom   NULL for array fetch, else transformed expression for source.
92  */
93 ArrayRef *
94 transformArraySubscripts(ParseState *pstate,
95                                                  Node *arrayBase,
96                                                  Oid arrayType,
97                                                  int32 arrayTypMod,
98                                                  List *indirection,
99                                                  bool forceSlice,
100                                                  Node *assignFrom)
101 {
102         Oid                     elementType,
103                                 resultType;
104         HeapTuple       type_tuple_array;
105         Form_pg_type type_struct_array;
106         bool            isSlice = forceSlice;
107         List       *upperIndexpr = NIL;
108         List       *lowerIndexpr = NIL;
109         List       *idx;
110         ArrayRef   *aref;
111
112         /* Get the type tuple for the array */
113         type_tuple_array = SearchSysCache(TYPEOID,
114                                                                           ObjectIdGetDatum(arrayType),
115                                                                           0, 0, 0);
116         if (!HeapTupleIsValid(type_tuple_array))
117                 elog(ERROR, "transformArraySubscripts: Cache lookup failed for array type %u",
118                          arrayType);
119         type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple_array);
120
121         elementType = type_struct_array->typelem;
122         if (elementType == InvalidOid)
123                 elog(ERROR, "transformArraySubscripts: type %s is not an array",
124                          NameStr(type_struct_array->typname));
125
126         /*
127          * A list containing only single subscripts refers to a single array
128          * element.  If any of the items are double subscripts (lower:upper),
129          * then the subscript expression means an array slice operation. In
130          * this case, we supply a default lower bound of 1 for any items that
131          * contain only a single subscript. The forceSlice parameter forces us
132          * to treat the operation as a slice, even if no lower bounds are
133          * mentioned.  Otherwise, we have to prescan the indirection list to
134          * see if there are any double subscripts.
135          */
136         if (!isSlice)
137         {
138                 foreach(idx, indirection)
139                 {
140                         A_Indices  *ai = (A_Indices *) lfirst(idx);
141
142                         if (ai->lidx != NULL)
143                         {
144                                 isSlice = true;
145                                 break;
146                         }
147                 }
148         }
149
150         /*
151          * The type represented by the subscript expression is the element
152          * type if we are fetching a single element, but it is the same as the
153          * array type if we are fetching a slice or storing.
154          */
155         if (isSlice || assignFrom != NULL)
156                 resultType = arrayType;
157         else
158                 resultType = elementType;
159
160         /*
161          * Transform the subscript expressions.
162          */
163         foreach(idx, indirection)
164         {
165                 A_Indices  *ai = (A_Indices *) lfirst(idx);
166                 Node       *subexpr;
167
168                 if (isSlice)
169                 {
170                         if (ai->lidx)
171                         {
172                                 subexpr = transformExpr(pstate, ai->lidx);
173                                 /* If it's not int4 already, try to coerce */
174                                 subexpr = coerce_to_target_type(pstate,
175                                                                                                 subexpr, exprType(subexpr),
176                                                                                                 INT4OID, -1,
177                                                                                                 COERCION_ASSIGNMENT,
178                                                                                                 COERCE_IMPLICIT_CAST);
179                                 if (subexpr == NULL)
180                                         elog(ERROR, "array index expressions must be integers");
181                         }
182                         else
183                         {
184                                 /* Make a constant 1 */
185                                 subexpr = (Node *) makeConst(INT4OID,
186                                                                                          sizeof(int32),
187                                                                                          Int32GetDatum(1),
188                                                                                          false,
189                                                                                          true);         /* pass by value */
190                         }
191                         lowerIndexpr = lappend(lowerIndexpr, subexpr);
192                 }
193                 subexpr = transformExpr(pstate, ai->uidx);
194                 /* If it's not int4 already, try to coerce */
195                 subexpr = coerce_to_target_type(pstate,
196                                                                                 subexpr, exprType(subexpr),
197                                                                                 INT4OID, -1,
198                                                                                 COERCION_ASSIGNMENT,
199                                                                                 COERCE_IMPLICIT_CAST);
200                 if (subexpr == NULL)
201                         elog(ERROR, "array index expressions must be integers");
202                 upperIndexpr = lappend(upperIndexpr, subexpr);
203         }
204
205         /*
206          * If doing an array store, coerce the source value to the right type.
207          */
208         if (assignFrom != NULL)
209         {
210                 Oid                     typesource = exprType(assignFrom);
211                 Oid                     typeneeded = isSlice ? arrayType : elementType;
212
213                 if (typesource != InvalidOid)
214                 {
215                         assignFrom = coerce_to_target_type(pstate,
216                                                                                            assignFrom, typesource,
217                                                                                            typeneeded, arrayTypMod,
218                                                                                            COERCION_ASSIGNMENT,
219                                                                                            COERCE_IMPLICIT_CAST);
220                         if (assignFrom == NULL)
221                                 elog(ERROR, "Array assignment requires type %s"
222                                          " but expression is of type %s"
223                                          "\n\tYou will need to rewrite or cast the expression",
224                                          format_type_be(typeneeded),
225                                          format_type_be(typesource));
226                 }
227         }
228
229         /*
230          * Ready to build the ArrayRef node.
231          */
232         aref = makeNode(ArrayRef);
233         aref->refrestype = resultType;
234         aref->refarraytype = arrayType;
235         aref->refelemtype = elementType;
236         aref->refupperindexpr = upperIndexpr;
237         aref->reflowerindexpr = lowerIndexpr;
238         aref->refexpr = (Expr *) arrayBase;
239         aref->refassgnexpr = (Expr *) assignFrom;
240
241         ReleaseSysCache(type_tuple_array);
242
243         return aref;
244 }
245
246 /*
247  * make_const
248  *
249  *      Convert a Value node (as returned by the grammar) to a Const node
250  *      of the "natural" type for the constant.  Note that this routine is
251  *      only used when there is no explicit cast for the constant, so we
252  *      have to guess what type is wanted.
253  *
254  *      For string literals we produce a constant of type UNKNOWN ---- whose
255  *      representation is the same as text, but it indicates to later type
256  *      resolution that we're not sure that it should be considered text.
257  *      Explicit "NULL" constants are also typed as UNKNOWN.
258  *
259  *      For integers and floats we produce int4, int8, or numeric depending
260  *      on the value of the number.  XXX This should include int2 as well,
261  *      but additional cleanup is needed before we can do that; else cases
262  *      like "WHERE int4var = 42" will fail to be indexable.
263  */
264 Const *
265 make_const(Value *value)
266 {
267         Datum           val;
268         int64           val64;
269         Oid                     typeid;
270         int                     typelen;
271         bool            typebyval;
272         Const      *con;
273
274         switch (nodeTag(value))
275         {
276                 case T_Integer:
277                         val = Int32GetDatum(intVal(value));
278
279                         typeid = INT4OID;
280                         typelen = sizeof(int32);
281                         typebyval = true;
282                         break;
283
284                 case T_Float:
285                         /* could be an oversize integer as well as a float ... */
286                         if (scanint8(strVal(value), true, &val64))
287                         {
288                                 val = Int64GetDatum(val64);
289
290                                 typeid = INT8OID;
291                                 typelen = sizeof(int64);
292                                 typebyval = false;              /* XXX might change someday */
293                         }
294                         else
295                         {
296                                 val = DirectFunctionCall3(numeric_in,
297                                                                                   CStringGetDatum(strVal(value)),
298                                                                                   ObjectIdGetDatum(InvalidOid),
299                                                                                   Int32GetDatum(-1));
300
301                                 typeid = NUMERICOID;
302                                 typelen = -1;   /* variable len */
303                                 typebyval = false;
304                         }
305                         break;
306
307                 case T_String:
308                         val = DirectFunctionCall1(unknownin,
309                                                                           CStringGetDatum(strVal(value)));
310
311                         typeid = UNKNOWNOID;    /* will be coerced later */
312                         typelen = -1;           /* variable len */
313                         typebyval = false;
314                         break;
315
316                 case T_BitString:
317                         val = DirectFunctionCall3(bit_in,
318                                                                           CStringGetDatum(strVal(value)),
319                                                                           ObjectIdGetDatum(InvalidOid),
320                                                                           Int32GetDatum(-1));
321                         typeid = BITOID;
322                         typelen = -1;
323                         typebyval = false;
324                         break;
325
326                 default:
327                         elog(WARNING, "make_const: unknown type %d", nodeTag(value));
328                         /* FALLTHROUGH */
329
330                 case T_Null:
331                         /* return a null const */
332                         con = makeConst(UNKNOWNOID,
333                                                         -1,
334                                                         (Datum) NULL,
335                                                         true,
336                                                         false);
337                         return con;
338         }
339
340         con = makeConst(typeid,
341                                         typelen,
342                                         val,
343                                         false,
344                                         typebyval);
345
346         return con;
347 }