| /*------------------------------------------------------------------------- |
| * |
| * parse_node.c |
| * various routines that make nodes for querytrees |
| * |
| * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group |
| * Portions Copyright (c) 1994, Regents of the University of California |
| * |
| * |
| * IDENTIFICATION |
| * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.95 2006/10/04 00:29:56 momjian Exp $ |
| * |
| *------------------------------------------------------------------------- |
| */ |
| #include "postgres.h" |
| |
| #include "catalog/catquery.h" |
| #include "catalog/pg_type.h" |
| #include "mb/pg_wchar.h" |
| #include "nodes/makefuncs.h" |
| #include "parser/parsetree.h" |
| #include "parser/parse_coerce.h" |
| #include "parser/parse_expr.h" |
| #include "parser/parse_relation.h" |
| #include "utils/builtins.h" |
| #include "utils/int8.h" |
| #include "utils/hsearch.h" |
| #include "utils/syscache.h" |
| #include "utils/varbit.h" |
| |
| /* |
| * make_parsestate() |
| * |
| * Allocate and initialize a new ParseState. |
| * The CALLER is responsible for freeing the ParseState* returned. |
| */ |
| ParseState * |
| make_parsestate(ParseState *parentParseState) |
| { |
| ParseState *pstate; |
| |
| pstate = palloc0(sizeof(ParseState)); |
| |
| pstate->parentParseState = parentParseState; |
| |
| /* Fill in fields that don't start at null/false/zero */ |
| pstate->p_next_resno = 1; |
| |
| if (parentParseState) |
| { |
| pstate->p_sourcetext = parentParseState->p_sourcetext; |
| pstate->p_variableparams = parentParseState->p_variableparams; |
| pstate->p_setopTypes = parentParseState->p_setopTypes; |
| pstate->p_setopTypmods = parentParseState->p_setopTypmods; |
| } |
| |
| return pstate; |
| } |
| |
| /* |
| * free_parsestate() |
| * |
| * Releases memory associated with a given parsestate. |
| */ |
| void |
| free_parsestate(ParseState **pstate) |
| { |
| if (pstate == NULL || *pstate == NULL) |
| return; /* already freed? */ |
| |
| if ((*pstate)->p_namecache) |
| hash_destroy((*pstate)->p_namecache); |
| |
| pfree(*pstate); |
| *pstate = NULL; |
| return; |
| } |
| |
| /* |
| * parser_get_namecache() |
| * |
| * Returns the allocated object name hash table associated with the given parse |
| * state. This cache is used by parse routines that need to allocate multiple |
| * ChooseRelationName() values that need to be distinct from each other. |
| * |
| * The cache is allocated by the first caller of this function. |
| */ |
| struct HTAB * |
| parser_get_namecache(ParseState *pstate) |
| { |
| /* |
| * The cache is always stored in the TOP level parse state, so if this is |
| * a substate start by walking up the pstate tree. |
| */ |
| while (pstate->parentParseState != NULL) |
| pstate = pstate->parentParseState; |
| |
| /* The first caller allocates the cache */ |
| if (!pstate->p_namecache) |
| { |
| HASHCTL cacheInfo; |
| int cacheFlags; |
| |
| memset(&cacheInfo, 0, sizeof(cacheInfo)); |
| cacheInfo.keysize = NAMEDATALEN; |
| cacheInfo.entrysize = NAMEDATALEN; |
| cacheInfo.hcxt = CurrentMemoryContext; |
| cacheFlags = HASH_ELEM | HASH_CONTEXT; |
| |
| pstate->p_namecache = hash_create("parse state object name cache", |
| 256, &cacheInfo, cacheFlags); |
| } |
| |
| /* Return the cache */ |
| return pstate->p_namecache; |
| } |
| |
| /* |
| * parser_errposition |
| * Report a parse-analysis-time cursor position, if possible. |
| * |
| * This is expected to be used within an ereport() call. The return value |
| * is a dummy (always 0, in fact). |
| * |
| * The locations stored in raw parsetrees are byte offsets into the source |
| * string. We have to convert them to 1-based character indexes for reporting |
| * to clients. (We do things this way to avoid unnecessary overhead in the |
| * normal non-error case: computing character indexes would be much more |
| * expensive than storing token offsets.) |
| */ |
| int |
| parser_errposition(ParseState *pstate, int location) |
| { |
| int pos; |
| |
| /* No-op if location was not provided */ |
| if (location < 0) |
| return 0; |
| /* Can't do anything if source text is not available */ |
| if (pstate == NULL || pstate->p_sourcetext == NULL) |
| return 0; |
| /* Convert offset to character number */ |
| pos = pg_mbstrlen_with_len(pstate->p_sourcetext, location) + 1; |
| /* And pass it to the ereport mechanism */ |
| return errposition(pos); |
| } |
| |
| |
| /* |
| * make_var |
| * Build a Var node for an attribute identified by RTE and attrno |
| */ |
| Var * |
| make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location) |
| { |
| int vnum, |
| sublevels_up; |
| Oid vartypeid; |
| int32 type_mod; |
| |
| vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); |
| get_rte_attribute_type(rte, attrno, &vartypeid, &type_mod); |
| return makeVar(vnum, attrno, vartypeid, type_mod, sublevels_up); |
| } |
| |
| /* |
| * transformArrayType() |
| * Get the element type of an array type in preparation for subscripting |
| */ |
| Oid |
| transformArrayType(Oid arrayType) |
| { |
| Oid elementType; |
| int fetchCount; |
| |
| |
| /* Get the type tuple for the array */ |
| elementType = caql_getoid_plus( |
| NULL, |
| &fetchCount, |
| NULL, |
| cql("SELECT typelem FROM pg_type " |
| " WHERE oid = :1 ", |
| ObjectIdGetDatum(arrayType))); |
| |
| if (!fetchCount) |
| elog(ERROR, "cache lookup failed for type %u", arrayType); |
| |
| /* needn't check typisdefined since this will fail anyway */ |
| |
| if (!OidIsValid(elementType)) |
| ereport(ERROR, |
| (errcode(ERRCODE_DATATYPE_MISMATCH), |
| errmsg("cannot subscript type %s because it is not an array", |
| format_type_be(arrayType)))); |
| |
| return elementType; |
| } |
| |
| /* |
| * transformArraySubscripts() |
| * Transform array subscripting. This is used for both |
| * array fetch and array assignment. |
| * |
| * In an array fetch, we are given a source array value and we produce an |
| * expression that represents the result of extracting a single array element |
| * or an array slice. |
| * |
| * In an array assignment, we are given a destination array value plus a |
| * source value that is to be assigned to a single element or a slice of |
| * that array. We produce an expression that represents the new array value |
| * with the source data inserted into the right part of the array. |
| * |
| * pstate Parse state |
| * arrayBase Already-transformed expression for the array as a whole |
| * arrayType OID of array's datatype (should match type of arrayBase) |
| * elementType OID of array's element type (fetch with transformArrayType, |
| * or pass InvalidOid to do it here) |
| * elementTypMod typmod to be applied to array elements (if storing) |
| * indirection Untransformed list of subscripts (must not be NIL) |
| * assignFrom NULL for array fetch, else transformed expression for source. |
| */ |
| ArrayRef * |
| transformArraySubscripts(ParseState *pstate, |
| Node *arrayBase, |
| Oid arrayType, |
| Oid elementType, |
| int32 elementTypMod, |
| List *indirection, |
| Node *assignFrom) |
| { |
| Oid resultType; |
| bool isSlice = false; |
| List *upperIndexpr = NIL; |
| List *lowerIndexpr = NIL; |
| ListCell *idx; |
| ArrayRef *aref; |
| |
| /* Caller may or may not have bothered to determine elementType */ |
| if (!OidIsValid(elementType)) |
| elementType = transformArrayType(arrayType); |
| |
| /* |
| * A list containing only single subscripts refers to a single array |
| * element. If any of the items are double subscripts (lower:upper), then |
| * the subscript expression means an array slice operation. In this case, |
| * we supply a default lower bound of 1 for any items that contain only a |
| * single subscript. We have to prescan the indirection list to see if |
| * there are any double subscripts. |
| */ |
| foreach(idx, indirection) |
| { |
| A_Indices *ai = (A_Indices *) lfirst(idx); |
| |
| if (ai->lidx != NULL) |
| { |
| isSlice = true; |
| break; |
| } |
| } |
| |
| /* |
| * The type represented by the subscript expression is the element type if |
| * we are fetching a single element, but it is the same as the array type |
| * if we are fetching a slice or storing. |
| */ |
| if (isSlice || assignFrom != NULL) |
| resultType = arrayType; |
| else |
| resultType = elementType; |
| |
| /* |
| * Transform the subscript expressions. |
| */ |
| foreach(idx, indirection) |
| { |
| A_Indices *ai = (A_Indices *) lfirst(idx); |
| Node *subexpr; |
| |
| Assert(IsA(ai, A_Indices)); |
| if (isSlice) |
| { |
| if (ai->lidx) |
| { |
| subexpr = transformExpr(pstate, ai->lidx); |
| /* If it's not int4 already, try to coerce */ |
| subexpr = coerce_to_target_type(pstate, |
| subexpr, exprType(subexpr), |
| INT4OID, -1, |
| COERCION_ASSIGNMENT, |
| COERCE_IMPLICIT_CAST, |
| -1); |
| if (subexpr == NULL) |
| ereport(ERROR, |
| (errcode(ERRCODE_DATATYPE_MISMATCH), |
| errmsg("array subscript must have type integer"))); |
| } |
| else |
| { |
| /* Make a constant 1 */ |
| subexpr = (Node *) makeConst(INT4OID, |
| -1, |
| sizeof(int32), |
| Int32GetDatum(1), |
| false, |
| true); /* pass by value */ |
| } |
| lowerIndexpr = lappend(lowerIndexpr, subexpr); |
| } |
| subexpr = transformExpr(pstate, ai->uidx); |
| /* If it's not int4 already, try to coerce */ |
| subexpr = coerce_to_target_type(pstate, |
| subexpr, exprType(subexpr), |
| INT4OID, -1, |
| COERCION_ASSIGNMENT, |
| COERCE_IMPLICIT_CAST, |
| -1); |
| if (subexpr == NULL) |
| ereport(ERROR, |
| (errcode(ERRCODE_DATATYPE_MISMATCH), |
| errmsg("array subscript must have type integer"))); |
| upperIndexpr = lappend(upperIndexpr, subexpr); |
| } |
| |
| /* |
| * If doing an array store, coerce the source value to the right type. |
| * (This should agree with the coercion done by transformAssignedExpr.) |
| */ |
| if (assignFrom != NULL) |
| { |
| Oid typesource = exprType(assignFrom); |
| Oid typeneeded = isSlice ? arrayType : elementType; |
| |
| assignFrom = coerce_to_target_type(pstate, |
| assignFrom, typesource, |
| typeneeded, elementTypMod, |
| COERCION_ASSIGNMENT, |
| COERCE_IMPLICIT_CAST, |
| -1); |
| if (assignFrom == NULL) |
| ereport(ERROR, |
| (errcode(ERRCODE_DATATYPE_MISMATCH), |
| errmsg("array assignment requires type %s" |
| " but expression is of type %s", |
| format_type_be(typeneeded), |
| format_type_be(typesource)), |
| errhint("You will need to rewrite or cast the expression."))); |
| } |
| |
| /* |
| * Ready to build the ArrayRef node. |
| */ |
| aref = makeNode(ArrayRef); |
| aref->refrestype = resultType; |
| aref->refarraytype = arrayType; |
| aref->refelemtype = elementType; |
| aref->refupperindexpr = upperIndexpr; |
| aref->reflowerindexpr = lowerIndexpr; |
| aref->refexpr = (Expr *) arrayBase; |
| aref->refassgnexpr = (Expr *) assignFrom; |
| |
| return aref; |
| } |
| |
| /* |
| * make_const |
| * |
| * Convert a Value node (as returned by the grammar) to a Const node |
| * of the "natural" type for the constant. Note that this routine is |
| * only used when there is no explicit cast for the constant, so we |
| * have to guess what type is wanted. |
| * |
| * For string literals we produce a constant of type UNKNOWN ---- whose |
| * representation is the same as cstring, but it indicates to later type |
| * resolution that we're not sure yet what type it should be considered. |
| * Explicit "NULL" constants are also typed as UNKNOWN. |
| * |
| * For integers and floats we produce int4, int8, or numeric depending |
| * on the value of the number. XXX We should produce int2 as well, |
| * but additional cleanup is needed before we can do that; there are |
| * too many examples that fail if we try. |
| */ |
| Const * |
| make_const(ParseState *pstate, Value *value, int location) |
| { |
| Datum val; |
| int64 val64; |
| Oid typeid; |
| int typelen; |
| bool typebyval; |
| Const *con; |
| |
| switch (nodeTag(value)) |
| { |
| case T_Integer: |
| val = Int32GetDatum(intVal(value)); |
| |
| typeid = INT4OID; |
| typelen = sizeof(int32); |
| typebyval = true; |
| break; |
| |
| case T_Float: |
| /* could be an oversize integer as well as a float ... */ |
| if (scanint8(strVal(value), true, &val64)) |
| { |
| /* |
| * It might actually fit in int32. Probably only INT_MIN can |
| * occur, but we'll code the test generally just to be sure. |
| */ |
| int32 val32 = (int32) val64; |
| |
| if (val64 == (int64) val32) |
| { |
| val = Int32GetDatum(val32); |
| |
| typeid = INT4OID; |
| typelen = sizeof(int32); |
| typebyval = true; |
| } |
| else |
| { |
| val = Int64GetDatum(val64); |
| |
| typeid = INT8OID; |
| typelen = sizeof(int64); |
| typebyval = true; /* XXX might change someday */ |
| } |
| } |
| else |
| { |
| val = DirectFunctionCall3(numeric_in, |
| CStringGetDatum(strVal(value)), |
| ObjectIdGetDatum(InvalidOid), |
| Int32GetDatum(-1)); |
| |
| typeid = NUMERICOID; |
| typelen = -1; /* variable len */ |
| typebyval = false; |
| } |
| break; |
| |
| case T_String: |
| |
| /* |
| * We assume here that UNKNOWN's internal representation is the |
| * same as CSTRING |
| */ |
| val = CStringGetDatum(strVal(value)); |
| |
| typeid = UNKNOWNOID; /* will be coerced later */ |
| typelen = -2; /* cstring-style varwidth type */ |
| typebyval = false; |
| break; |
| |
| case T_BitString: |
| val = DirectFunctionCall3(bit_in, |
| CStringGetDatum(strVal(value)), |
| ObjectIdGetDatum(InvalidOid), |
| Int32GetDatum(-1)); |
| typeid = BITOID; |
| typelen = -1; |
| typebyval = false; |
| break; |
| |
| case T_Null: |
| /* return a null const */ |
| con = makeConst(UNKNOWNOID, |
| -1, |
| -2, |
| (Datum) 0, |
| true, |
| false); |
| return con; |
| |
| default: |
| elog(ERROR, "unrecognized node type: %d", (int) nodeTag(value)); |
| return NULL; /* keep compiler quiet */ |
| } |
| |
| con = makeConst(typeid, |
| -1, |
| typelen, |
| val, |
| false, |
| typebyval); |
| |
| return con; |
| } |