/Users/deen/code/yugabyte-db/src/postgres/src/backend/parser/parse_node.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * parse_node.c |
4 | | * various routines that make nodes for querytrees |
5 | | * |
6 | | * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group |
7 | | * Portions Copyright (c) 1994, Regents of the University of California |
8 | | * |
9 | | * |
10 | | * IDENTIFICATION |
11 | | * src/backend/parser/parse_node.c |
12 | | * |
13 | | *------------------------------------------------------------------------- |
14 | | */ |
15 | | #include "postgres.h" |
16 | | |
17 | | #include "access/heapam.h" |
18 | | #include "access/htup_details.h" |
19 | | #include "catalog/pg_type.h" |
20 | | #include "mb/pg_wchar.h" |
21 | | #include "nodes/makefuncs.h" |
22 | | #include "nodes/nodeFuncs.h" |
23 | | #include "parser/parsetree.h" |
24 | | #include "parser/parse_coerce.h" |
25 | | #include "parser/parse_expr.h" |
26 | | #include "parser/parse_relation.h" |
27 | | #include "utils/builtins.h" |
28 | | #include "utils/int8.h" |
29 | | #include "utils/lsyscache.h" |
30 | | #include "utils/syscache.h" |
31 | | #include "utils/varbit.h" |
32 | | |
33 | | |
34 | | static void pcb_error_callback(void *arg); |
35 | | |
36 | | |
37 | | /* |
38 | | * make_parsestate |
39 | | * Allocate and initialize a new ParseState. |
40 | | * |
41 | | * Caller should eventually release the ParseState via free_parsestate(). |
42 | | */ |
43 | | ParseState * |
44 | | make_parsestate(ParseState *parentParseState) |
45 | 777k | { |
46 | 777k | ParseState *pstate; |
47 | | |
48 | 777k | pstate = palloc0(sizeof(ParseState)); |
49 | | |
50 | 777k | pstate->parentParseState = parentParseState; |
51 | | |
52 | | /* Fill in fields that don't start at null/false/zero */ |
53 | 777k | pstate->p_next_resno = 1; |
54 | 777k | pstate->p_resolve_unknowns = true; |
55 | | |
56 | 777k | if (parentParseState) |
57 | 17.3k | { |
58 | 17.3k | pstate->p_sourcetext = parentParseState->p_sourcetext; |
59 | | /* all hooks are copied from parent */ |
60 | 17.3k | pstate->p_pre_columnref_hook = parentParseState->p_pre_columnref_hook; |
61 | 17.3k | pstate->p_post_columnref_hook = parentParseState->p_post_columnref_hook; |
62 | 17.3k | pstate->p_paramref_hook = parentParseState->p_paramref_hook; |
63 | 17.3k | pstate->p_coerce_param_hook = parentParseState->p_coerce_param_hook; |
64 | 17.3k | pstate->p_ref_hook_state = parentParseState->p_ref_hook_state; |
65 | | /* query environment stays in context for the whole parse analysis */ |
66 | 17.3k | pstate->p_queryEnv = parentParseState->p_queryEnv; |
67 | 17.3k | } |
68 | | |
69 | 777k | return pstate; |
70 | 777k | } |
71 | | |
72 | | /* |
73 | | * free_parsestate |
74 | | * Release a ParseState and any subsidiary resources. |
75 | | */ |
76 | | void |
77 | | free_parsestate(ParseState *pstate) |
78 | 761k | { |
79 | | /* |
80 | | * Check that we did not produce too many resnos; at the very least we |
81 | | * cannot allow more than 2^16, since that would exceed the range of a |
82 | | * AttrNumber. It seems safest to use MaxTupleAttributeNumber. |
83 | | */ |
84 | 761k | if (pstate->p_next_resno - 1 > MaxTupleAttributeNumber) |
85 | 761k | ereport(ERROR, |
86 | 761k | (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), |
87 | 761k | errmsg("target lists can have at most %d entries", |
88 | 761k | MaxTupleAttributeNumber))); |
89 | | |
90 | 761k | if (pstate->p_target_relation != NULL) |
91 | 304k | heap_close(pstate->p_target_relation, NoLock); |
92 | | |
93 | 761k | pfree(pstate); |
94 | 761k | } |
95 | | |
96 | | |
97 | | /* |
98 | | * parser_errposition |
99 | | * Report a parse-analysis-time cursor position, if possible. |
100 | | * |
101 | | * This is expected to be used within an ereport() call. The return value |
102 | | * is a dummy (always 0, in fact). |
103 | | * |
104 | | * The locations stored in raw parsetrees are byte offsets into the source |
105 | | * string. We have to convert them to 1-based character indexes for reporting |
106 | | * to clients. (We do things this way to avoid unnecessary overhead in the |
107 | | * normal non-error case: computing character indexes would be much more |
108 | | * expensive than storing token offsets.) |
109 | | */ |
110 | | int |
111 | | parser_errposition(ParseState *pstate, int location) |
112 | 1.10k | { |
113 | 1.10k | int pos; |
114 | | |
115 | | /* No-op if location was not provided */ |
116 | 1.10k | if (location < 0) |
117 | 6 | return 0; |
118 | | /* Can't do anything if source text is not available */ |
119 | 1.09k | if (pstate == NULL || pstate->p_sourcetext == NULL1.09k ) |
120 | 8 | return 0; |
121 | | /* Convert offset to character number */ |
122 | 1.09k | pos = pg_mbstrlen_with_len(pstate->p_sourcetext, location) + 1; |
123 | | /* And pass it to the ereport mechanism */ |
124 | 1.09k | return errposition(pos); |
125 | 1.09k | } |
126 | | |
127 | | |
128 | | /* |
129 | | * setup_parser_errposition_callback |
130 | | * Arrange for non-parser errors to report an error position |
131 | | * |
132 | | * Sometimes the parser calls functions that aren't part of the parser |
133 | | * subsystem and can't reasonably be passed a ParseState; yet we would |
134 | | * like any errors thrown in those functions to be tagged with a parse |
135 | | * error location. Use this function to set up an error context stack |
136 | | * entry that will accomplish that. Usage pattern: |
137 | | * |
138 | | * declare a local variable "ParseCallbackState pcbstate" |
139 | | * ... |
140 | | * setup_parser_errposition_callback(&pcbstate, pstate, location); |
141 | | * call function that might throw error; |
142 | | * cancel_parser_errposition_callback(&pcbstate); |
143 | | */ |
144 | | void |
145 | | setup_parser_errposition_callback(ParseCallbackState *pcbstate, |
146 | | ParseState *pstate, int location) |
147 | 795k | { |
148 | | /* Setup error traceback support for ereport() */ |
149 | 795k | pcbstate->pstate = pstate; |
150 | 795k | pcbstate->location = location; |
151 | 795k | pcbstate->errcallback.callback = pcb_error_callback; |
152 | 795k | pcbstate->errcallback.arg = (void *) pcbstate; |
153 | 795k | pcbstate->errcallback.previous = error_context_stack; |
154 | 795k | error_context_stack = &pcbstate->errcallback; |
155 | 795k | } |
156 | | |
157 | | /* |
158 | | * Cancel a previously-set-up errposition callback. |
159 | | */ |
160 | | void |
161 | | cancel_parser_errposition_callback(ParseCallbackState *pcbstate) |
162 | 794k | { |
163 | | /* Pop the error context stack */ |
164 | 794k | error_context_stack = pcbstate->errcallback.previous; |
165 | 794k | } |
166 | | |
167 | | /* |
168 | | * Error context callback for inserting parser error location. |
169 | | * |
170 | | * Note that this will be called for *any* error occurring while the |
171 | | * callback is installed. We avoid inserting an irrelevant error location |
172 | | * if the error is a query cancel --- are there any other important cases? |
173 | | */ |
174 | | static void |
175 | | pcb_error_callback(void *arg) |
176 | 748 | { |
177 | 748 | ParseCallbackState *pcbstate = (ParseCallbackState *) arg; |
178 | | |
179 | 748 | if (geterrcode() != ERRCODE_QUERY_CANCELED) |
180 | 748 | (void) parser_errposition(pcbstate->pstate, pcbstate->location); |
181 | 748 | } |
182 | | |
183 | | |
184 | | /* |
185 | | * make_var |
186 | | * Build a Var node for an attribute identified by RTE and attrno |
187 | | */ |
188 | | Var * |
189 | | make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location) |
190 | 370k | { |
191 | 370k | Var *result; |
192 | 370k | int vnum, |
193 | 370k | sublevels_up; |
194 | 370k | Oid vartypeid; |
195 | 370k | int32 type_mod; |
196 | 370k | Oid varcollid; |
197 | | |
198 | 370k | vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); |
199 | 370k | get_rte_attribute_type(rte, attrno, &vartypeid, &type_mod, &varcollid); |
200 | 370k | result = makeVar(vnum, attrno, vartypeid, type_mod, varcollid, sublevels_up); |
201 | 370k | result->location = location; |
202 | 370k | return result; |
203 | 370k | } |
204 | | |
205 | | /* |
206 | | * transformArrayType() |
207 | | * Identify the types involved in a subscripting operation |
208 | | * |
209 | | * On entry, arrayType/arrayTypmod identify the type of the input value |
210 | | * to be subscripted (which could be a domain type). These are modified |
211 | | * if necessary to identify the actual array type and typmod, and the |
212 | | * array's element type is returned. An error is thrown if the input isn't |
213 | | * an array type. |
214 | | */ |
215 | | Oid |
216 | | transformArrayType(Oid *arrayType, int32 *arrayTypmod) |
217 | 538 | { |
218 | 538 | Oid origArrayType = *arrayType; |
219 | 538 | Oid elementType; |
220 | 538 | HeapTuple type_tuple_array; |
221 | 538 | Form_pg_type type_struct_array; |
222 | | |
223 | | /* |
224 | | * If the input is a domain, smash to base type, and extract the actual |
225 | | * typmod to be applied to the base type. Subscripting a domain is an |
226 | | * operation that necessarily works on the base array type, not the domain |
227 | | * itself. (Note that we provide no method whereby the creator of a |
228 | | * domain over an array type could hide its ability to be subscripted.) |
229 | | */ |
230 | 538 | *arrayType = getBaseTypeAndTypmod(*arrayType, arrayTypmod); |
231 | | |
232 | | /* |
233 | | * We treat int2vector and oidvector as though they were domains over |
234 | | * int2[] and oid[]. This is needed because array slicing could create an |
235 | | * array that doesn't satisfy the dimensionality constraints of the |
236 | | * xxxvector type; so we want the result of a slice operation to be |
237 | | * considered to be of the more general type. |
238 | | */ |
239 | 538 | if (*arrayType == INT2VECTOROID) |
240 | 0 | *arrayType = INT2ARRAYOID; |
241 | 538 | else if (*arrayType == OIDVECTOROID) |
242 | 0 | *arrayType = OIDARRAYOID; |
243 | | |
244 | | /* Get the type tuple for the array */ |
245 | 538 | type_tuple_array = SearchSysCache1(TYPEOID, ObjectIdGetDatum(*arrayType)); |
246 | 538 | if (!HeapTupleIsValid(type_tuple_array)) |
247 | 0 | elog(ERROR, "cache lookup failed for type %u", *arrayType); |
248 | 538 | type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple_array); |
249 | | |
250 | | /* needn't check typisdefined since this will fail anyway */ |
251 | | |
252 | 538 | elementType = type_struct_array->typelem; |
253 | 538 | if (elementType == InvalidOid) |
254 | 538 | ereport(ERROR, |
255 | 538 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
256 | 538 | errmsg("cannot subscript type %s because it is not an array", |
257 | 538 | format_type_be(origArrayType)))); |
258 | | |
259 | 538 | ReleaseSysCache(type_tuple_array); |
260 | | |
261 | 538 | return elementType; |
262 | 538 | } |
263 | | |
264 | | /* |
265 | | * transformArraySubscripts() |
266 | | * Transform array subscripting. This is used for both |
267 | | * array fetch and array assignment. |
268 | | * |
269 | | * In an array fetch, we are given a source array value and we produce an |
270 | | * expression that represents the result of extracting a single array element |
271 | | * or an array slice. |
272 | | * |
273 | | * In an array assignment, we are given a destination array value plus a |
274 | | * source value that is to be assigned to a single element or a slice of |
275 | | * that array. We produce an expression that represents the new array value |
276 | | * with the source data inserted into the right part of the array. |
277 | | * |
278 | | * For both cases, if the source array is of a domain-over-array type, |
279 | | * the result is of the base array type or its element type; essentially, |
280 | | * we must fold a domain to its base type before applying subscripting. |
281 | | * (Note that int2vector and oidvector are treated as domains here.) |
282 | | * |
283 | | * pstate Parse state |
284 | | * arrayBase Already-transformed expression for the array as a whole |
285 | | * arrayType OID of array's datatype (should match type of arrayBase, |
286 | | * or be the base type of arrayBase's domain type) |
287 | | * elementType OID of array's element type (fetch with transformArrayType, |
288 | | * or pass InvalidOid to do it here) |
289 | | * arrayTypMod typmod for the array (which is also typmod for the elements) |
290 | | * indirection Untransformed list of subscripts (must not be NIL) |
291 | | * assignFrom NULL for array fetch, else transformed expression for source. |
292 | | */ |
293 | | ArrayRef * |
294 | | transformArraySubscripts(ParseState *pstate, |
295 | | Node *arrayBase, |
296 | | Oid arrayType, |
297 | | Oid elementType, |
298 | | int32 arrayTypMod, |
299 | | List *indirection, |
300 | | Node *assignFrom) |
301 | 538 | { |
302 | 538 | bool isSlice = false; |
303 | 538 | List *upperIndexpr = NIL; |
304 | 538 | List *lowerIndexpr = NIL; |
305 | 538 | ListCell *idx; |
306 | 538 | ArrayRef *aref; |
307 | | |
308 | | /* |
309 | | * Caller may or may not have bothered to determine elementType. Note |
310 | | * that if the caller did do so, arrayType/arrayTypMod must be as modified |
311 | | * by transformArrayType, ie, smash domain to base type. |
312 | | */ |
313 | 538 | if (!OidIsValid(elementType)) |
314 | 418 | elementType = transformArrayType(&arrayType, &arrayTypMod); |
315 | | |
316 | | /* |
317 | | * A list containing only simple subscripts refers to a single array |
318 | | * element. If any of the items are slice specifiers (lower:upper), then |
319 | | * the subscript expression means an array slice operation. In this case, |
320 | | * we convert any non-slice items to slices by treating the single |
321 | | * subscript as the upper bound and supplying an assumed lower bound of 1. |
322 | | * We have to prescan the list to see if there are any slice items. |
323 | | */ |
324 | 538 | foreach(idx, indirection) |
325 | 559 | { |
326 | 559 | A_Indices *ai = (A_Indices *) lfirst(idx); |
327 | | |
328 | 559 | if (ai->is_slice) |
329 | 59 | { |
330 | 59 | isSlice = true; |
331 | 59 | break; |
332 | 59 | } |
333 | 559 | } |
334 | | |
335 | | /* |
336 | | * Transform the subscript expressions. |
337 | | */ |
338 | 538 | foreach(idx, indirection) |
339 | 583 | { |
340 | 583 | A_Indices *ai = lfirst_node(A_Indices, idx); |
341 | 583 | Node *subexpr; |
342 | | |
343 | 583 | if (isSlice) |
344 | 85 | { |
345 | 85 | if (ai->lidx) |
346 | 63 | { |
347 | 63 | subexpr = transformExpr(pstate, ai->lidx, pstate->p_expr_kind); |
348 | | /* If it's not int4 already, try to coerce */ |
349 | 63 | subexpr = coerce_to_target_type(pstate, |
350 | 63 | subexpr, exprType(subexpr), |
351 | 63 | INT4OID, -1, |
352 | 63 | COERCION_ASSIGNMENT, |
353 | 63 | COERCE_IMPLICIT_CAST, |
354 | 63 | -1); |
355 | 63 | if (subexpr == NULL) |
356 | 63 | ereport(ERROR, |
357 | 63 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
358 | 63 | errmsg("array subscript must have type integer"), |
359 | 63 | parser_errposition(pstate, exprLocation(ai->lidx)))); |
360 | 63 | } |
361 | 22 | else if (!ai->is_slice) |
362 | 9 | { |
363 | | /* Make a constant 1 */ |
364 | 9 | subexpr = (Node *) makeConst(INT4OID, |
365 | 9 | -1, |
366 | 9 | InvalidOid, |
367 | 9 | sizeof(int32), |
368 | 9 | Int32GetDatum(1), |
369 | 9 | false, |
370 | 9 | true); /* pass by value */ |
371 | 9 | } |
372 | 13 | else |
373 | 13 | { |
374 | | /* Slice with omitted lower bound, put NULL into the list */ |
375 | 13 | subexpr = NULL; |
376 | 13 | } |
377 | 85 | lowerIndexpr = lappend(lowerIndexpr, subexpr); |
378 | 85 | } |
379 | 498 | else |
380 | 583 | Assert(ai->lidx == NULL && !ai->is_slice); |
381 | | |
382 | 583 | if (ai->uidx) |
383 | 570 | { |
384 | 570 | subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind); |
385 | | /* If it's not int4 already, try to coerce */ |
386 | 570 | subexpr = coerce_to_target_type(pstate, |
387 | 570 | subexpr, exprType(subexpr), |
388 | 570 | INT4OID, -1, |
389 | 570 | COERCION_ASSIGNMENT, |
390 | 570 | COERCE_IMPLICIT_CAST, |
391 | 570 | -1); |
392 | 570 | if (subexpr == NULL) |
393 | 570 | ereport(ERROR, |
394 | 570 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
395 | 570 | errmsg("array subscript must have type integer"), |
396 | 570 | parser_errposition(pstate, exprLocation(ai->uidx)))); |
397 | 570 | } |
398 | 13 | else |
399 | 13 | { |
400 | | /* Slice with omitted upper bound, put NULL into the list */ |
401 | 13 | Assert(isSlice && ai->is_slice); |
402 | 13 | subexpr = NULL; |
403 | 13 | } |
404 | 583 | upperIndexpr = lappend(upperIndexpr, subexpr); |
405 | 583 | } |
406 | | |
407 | | /* |
408 | | * If doing an array store, coerce the source value to the right type. |
409 | | * (This should agree with the coercion done by transformAssignedExpr.) |
410 | | */ |
411 | 538 | if (assignFrom != NULL) |
412 | 120 | { |
413 | 120 | Oid typesource = exprType(assignFrom); |
414 | 120 | Oid typeneeded = isSlice ? arrayType35 : elementType85 ; |
415 | 120 | Node *newFrom; |
416 | | |
417 | 120 | newFrom = coerce_to_target_type(pstate, |
418 | 120 | assignFrom, typesource, |
419 | 120 | typeneeded, arrayTypMod, |
420 | 120 | COERCION_ASSIGNMENT, |
421 | 120 | COERCE_IMPLICIT_CAST, |
422 | 120 | -1); |
423 | 120 | if (newFrom == NULL) |
424 | 120 | ereport(ERROR, |
425 | 120 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
426 | 120 | errmsg("array assignment requires type %s" |
427 | 120 | " but expression is of type %s", |
428 | 120 | format_type_be(typeneeded), |
429 | 120 | format_type_be(typesource)), |
430 | 120 | errhint("You will need to rewrite or cast the expression."), |
431 | 120 | parser_errposition(pstate, exprLocation(assignFrom)))); |
432 | 120 | assignFrom = newFrom; |
433 | 120 | } |
434 | | |
435 | | /* |
436 | | * Ready to build the ArrayRef node. |
437 | | */ |
438 | 538 | aref = makeNode(ArrayRef); |
439 | 0 | aref->refarraytype = arrayType; |
440 | 538 | aref->refelemtype = elementType; |
441 | 538 | aref->reftypmod = arrayTypMod; |
442 | | /* refcollid will be set by parse_collate.c */ |
443 | 538 | aref->refupperindexpr = upperIndexpr; |
444 | 538 | aref->reflowerindexpr = lowerIndexpr; |
445 | 538 | aref->refexpr = (Expr *) arrayBase; |
446 | 538 | aref->refassgnexpr = (Expr *) assignFrom; |
447 | | |
448 | 538 | return aref; |
449 | 538 | } |
450 | | |
451 | | /* |
452 | | * make_const |
453 | | * |
454 | | * Convert a Value node (as returned by the grammar) to a Const node |
455 | | * of the "natural" type for the constant. Note that this routine is |
456 | | * only used when there is no explicit cast for the constant, so we |
457 | | * have to guess what type is wanted. |
458 | | * |
459 | | * For string literals we produce a constant of type UNKNOWN ---- whose |
460 | | * representation is the same as cstring, but it indicates to later type |
461 | | * resolution that we're not sure yet what type it should be considered. |
462 | | * Explicit "NULL" constants are also typed as UNKNOWN. |
463 | | * |
464 | | * For integers and floats we produce int4, int8, or numeric depending |
465 | | * on the value of the number. XXX We should produce int2 as well, |
466 | | * but additional cleanup is needed before we can do that; there are |
467 | | * too many examples that fail if we try. |
468 | | */ |
469 | | Const * |
470 | | make_const(ParseState *pstate, Value *value, int location) |
471 | 2.90M | { |
472 | 2.90M | Const *con; |
473 | 2.90M | Datum val; |
474 | 2.90M | int64 val64; |
475 | 2.90M | Oid typeid; |
476 | 2.90M | int typelen; |
477 | 2.90M | bool typebyval; |
478 | 2.90M | ParseCallbackState pcbstate; |
479 | | |
480 | 2.90M | switch (nodeTag(value)) |
481 | 2.90M | { |
482 | 2.61M | case T_Integer: |
483 | 2.61M | val = Int32GetDatum(intVal(value)); |
484 | | |
485 | 2.61M | typeid = INT4OID; |
486 | 2.61M | typelen = sizeof(int32); |
487 | 2.61M | typebyval = true; |
488 | 2.61M | break; |
489 | | |
490 | 4.65k | case T_Float: |
491 | | /* could be an oversize integer as well as a float ... */ |
492 | 4.65k | if (scanint8(strVal(value), true, &val64)) |
493 | 291 | { |
494 | | /* |
495 | | * It might actually fit in int32. Probably only INT_MIN can |
496 | | * occur, but we'll code the test generally just to be sure. |
497 | | */ |
498 | 291 | int32 val32 = (int32) val64; |
499 | | |
500 | 291 | if (val64 == (int64) val32) |
501 | 29 | { |
502 | 29 | val = Int32GetDatum(val32); |
503 | | |
504 | 29 | typeid = INT4OID; |
505 | 29 | typelen = sizeof(int32); |
506 | 29 | typebyval = true; |
507 | 29 | } |
508 | 262 | else |
509 | 262 | { |
510 | 262 | val = Int64GetDatum(val64); |
511 | | |
512 | 262 | typeid = INT8OID; |
513 | 262 | typelen = sizeof(int64); |
514 | 262 | typebyval = FLOAT8PASSBYVAL; /* int8 and float8 alike */ |
515 | 262 | } |
516 | 291 | } |
517 | 4.36k | else |
518 | 4.36k | { |
519 | | /* arrange to report location if numeric_in() fails */ |
520 | 4.36k | setup_parser_errposition_callback(&pcbstate, pstate, location); |
521 | 4.36k | val = DirectFunctionCall3(numeric_in, |
522 | 4.36k | CStringGetDatum(strVal(value)), |
523 | 4.36k | ObjectIdGetDatum(InvalidOid), |
524 | 4.36k | Int32GetDatum(-1)); |
525 | 4.36k | cancel_parser_errposition_callback(&pcbstate); |
526 | | |
527 | 4.36k | typeid = NUMERICOID; |
528 | 4.36k | typelen = -1; /* variable len */ |
529 | 4.36k | typebyval = false; |
530 | 4.36k | } |
531 | 4.65k | break; |
532 | | |
533 | 278k | case T_String: |
534 | | |
535 | | /* |
536 | | * We assume here that UNKNOWN's internal representation is the |
537 | | * same as CSTRING |
538 | | */ |
539 | 278k | val = CStringGetDatum(strVal(value)); |
540 | | |
541 | 278k | typeid = UNKNOWNOID; /* will be coerced later */ |
542 | 278k | typelen = -2; /* cstring-style varwidth type */ |
543 | 278k | typebyval = false; |
544 | 278k | break; |
545 | | |
546 | 145 | case T_BitString: |
547 | | /* arrange to report location if bit_in() fails */ |
548 | 145 | setup_parser_errposition_callback(&pcbstate, pstate, location); |
549 | 145 | val = DirectFunctionCall3(bit_in, |
550 | 145 | CStringGetDatum(strVal(value)), |
551 | 145 | ObjectIdGetDatum(InvalidOid), |
552 | 145 | Int32GetDatum(-1)); |
553 | 145 | cancel_parser_errposition_callback(&pcbstate); |
554 | 145 | typeid = BITOID; |
555 | 145 | typelen = -1; |
556 | 145 | typebyval = false; |
557 | 145 | break; |
558 | | |
559 | 5.91k | case T_Null: |
560 | | /* return a null const */ |
561 | 5.91k | con = makeConst(UNKNOWNOID, |
562 | 5.91k | -1, |
563 | 5.91k | InvalidOid, |
564 | 5.91k | -2, |
565 | 5.91k | (Datum) 0, |
566 | 5.91k | true, |
567 | 5.91k | false); |
568 | 5.91k | con->location = location; |
569 | 5.91k | return con; |
570 | | |
571 | 0 | default: |
572 | 0 | elog(ERROR, "unrecognized node type: %d", (int) nodeTag(value)); |
573 | 0 | return NULL; /* keep compiler quiet */ |
574 | 2.90M | } |
575 | | |
576 | 2.89M | con = makeConst(typeid, |
577 | 2.89M | -1, /* typmod -1 is OK for all cases */ |
578 | 2.89M | InvalidOid, /* all cases are uncollatable types */ |
579 | 2.89M | typelen, |
580 | 2.89M | val, |
581 | 2.89M | false, |
582 | 2.89M | typebyval); |
583 | 2.89M | con->location = location; |
584 | | |
585 | 2.89M | return con; |
586 | 2.90M | } |