mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
Standard pgindent run for 8.1.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.165 2005/08/23 22:40:27 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.166 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -393,8 +393,8 @@ ScanKeywordLookup(const char *text)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Apply an ASCII-only downcasing. We must not use tolower() since it
|
||||
* may produce the wrong translation in some locales (eg, Turkish).
|
||||
* Apply an ASCII-only downcasing. We must not use tolower() since it may
|
||||
* produce the wrong translation in some locales (eg, Turkish).
|
||||
*/
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.69 2005/06/05 22:32:57 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.70 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -56,22 +56,22 @@ transformAggregateCall(ParseState *pstate, Aggref *agg)
|
||||
|
||||
/*
|
||||
* The aggregate's level is the same as the level of the lowest-level
|
||||
* variable or aggregate in its argument; or if it contains no
|
||||
* variables at all, we presume it to be local.
|
||||
* variable or aggregate in its argument; or if it contains no variables
|
||||
* at all, we presume it to be local.
|
||||
*/
|
||||
min_varlevel = find_minimum_var_level((Node *) agg->target);
|
||||
|
||||
/*
|
||||
* An aggregate can't directly contain another aggregate call of the
|
||||
* same level (though outer aggs are okay). We can skip this check if
|
||||
* we didn't find any local vars or aggs.
|
||||
* An aggregate can't directly contain another aggregate call of the same
|
||||
* level (though outer aggs are okay). We can skip this check if we
|
||||
* didn't find any local vars or aggs.
|
||||
*/
|
||||
if (min_varlevel == 0)
|
||||
{
|
||||
if (checkExprHasAggs((Node *) agg->target))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_GROUPING_ERROR),
|
||||
errmsg("aggregate function calls may not be nested")));
|
||||
errmsg("aggregate function calls may not be nested")));
|
||||
}
|
||||
|
||||
if (min_varlevel < 0)
|
||||
@@ -127,8 +127,8 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
|
||||
/*
|
||||
* No aggregates allowed in GROUP BY clauses, either.
|
||||
*
|
||||
* While we are at it, build a list of the acceptable GROUP BY
|
||||
* expressions for use by check_ungrouped_columns().
|
||||
* While we are at it, build a list of the acceptable GROUP BY expressions
|
||||
* for use by check_ungrouped_columns().
|
||||
*/
|
||||
foreach(l, qry->groupClause)
|
||||
{
|
||||
@@ -141,15 +141,15 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
|
||||
if (checkExprHasAggs(expr))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_GROUPING_ERROR),
|
||||
errmsg("aggregates not allowed in GROUP BY clause")));
|
||||
errmsg("aggregates not allowed in GROUP BY clause")));
|
||||
groupClauses = lcons(expr, groupClauses);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are join alias vars involved, we have to flatten them to
|
||||
* the underlying vars, so that aliased and unaliased vars will be
|
||||
* correctly taken as equal. We can skip the expense of doing this if
|
||||
* no rangetable entries are RTE_JOIN kind.
|
||||
* If there are join alias vars involved, we have to flatten them to the
|
||||
* underlying vars, so that aliased and unaliased vars will be correctly
|
||||
* taken as equal. We can skip the expense of doing this if no rangetable
|
||||
* entries are RTE_JOIN kind.
|
||||
*/
|
||||
hasJoinRTEs = false;
|
||||
foreach(l, pstate->p_rtable)
|
||||
@@ -165,8 +165,8 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
|
||||
|
||||
/*
|
||||
* We use the planner's flatten_join_alias_vars routine to do the
|
||||
* flattening; it wants a PlannerInfo root node, which fortunately
|
||||
* can be mostly dummy.
|
||||
* flattening; it wants a PlannerInfo root node, which fortunately can be
|
||||
* mostly dummy.
|
||||
*/
|
||||
if (hasJoinRTEs)
|
||||
{
|
||||
@@ -175,15 +175,15 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
|
||||
root->hasJoinRTEs = true;
|
||||
|
||||
groupClauses = (List *) flatten_join_alias_vars(root,
|
||||
(Node *) groupClauses);
|
||||
(Node *) groupClauses);
|
||||
}
|
||||
else
|
||||
root = NULL; /* keep compiler quiet */
|
||||
|
||||
/*
|
||||
* Detect whether any of the grouping expressions aren't simple Vars;
|
||||
* if they're all Vars then we don't have to work so hard in the
|
||||
* recursive scans. (Note we have to flatten aliases before this.)
|
||||
* Detect whether any of the grouping expressions aren't simple Vars; if
|
||||
* they're all Vars then we don't have to work so hard in the recursive
|
||||
* scans. (Note we have to flatten aliases before this.)
|
||||
*/
|
||||
have_non_var_grouping = false;
|
||||
foreach(l, groupClauses)
|
||||
@@ -259,23 +259,23 @@ check_ungrouped_columns_walker(Node *node,
|
||||
return false; /* constants are always acceptable */
|
||||
|
||||
/*
|
||||
* If we find an aggregate call of the original level, do not recurse
|
||||
* into its arguments; ungrouped vars in the arguments are not an
|
||||
* error. We can also skip looking at the arguments of aggregates of
|
||||
* higher levels, since they could not possibly contain Vars that are
|
||||
* of concern to us (see transformAggregateCall). We do need to look
|
||||
* into the arguments of aggregates of lower levels, however.
|
||||
* If we find an aggregate call of the original level, do not recurse into
|
||||
* its arguments; ungrouped vars in the arguments are not an error. We can
|
||||
* also skip looking at the arguments of aggregates of higher levels,
|
||||
* since they could not possibly contain Vars that are of concern to us
|
||||
* (see transformAggregateCall). We do need to look into the arguments of
|
||||
* aggregates of lower levels, however.
|
||||
*/
|
||||
if (IsA(node, Aggref) &&
|
||||
(int) ((Aggref *) node)->agglevelsup >= context->sublevels_up)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If we have any GROUP BY items that are not simple Vars, check to
|
||||
* see if subexpression as a whole matches any GROUP BY item. We need
|
||||
* to do this at every recursion level so that we recognize GROUPed-BY
|
||||
* expressions before reaching variables within them. But this only
|
||||
* works at the outer query level, as noted above.
|
||||
* If we have any GROUP BY items that are not simple Vars, check to see if
|
||||
* subexpression as a whole matches any GROUP BY item. We need to do this
|
||||
* at every recursion level so that we recognize GROUPed-BY expressions
|
||||
* before reaching variables within them. But this only works at the outer
|
||||
* query level, as noted above.
|
||||
*/
|
||||
if (context->have_non_var_grouping && context->sublevels_up == 0)
|
||||
{
|
||||
@@ -288,10 +288,9 @@ check_ungrouped_columns_walker(Node *node,
|
||||
|
||||
/*
|
||||
* If we have an ungrouped Var of the original query level, we have a
|
||||
* failure. Vars below the original query level are not a problem,
|
||||
* and neither are Vars from above it. (If such Vars are ungrouped as
|
||||
* far as their own query level is concerned, that's someone else's
|
||||
* problem...)
|
||||
* failure. Vars below the original query level are not a problem, and
|
||||
* neither are Vars from above it. (If such Vars are ungrouped as far as
|
||||
* their own query level is concerned, that's someone else's problem...)
|
||||
*/
|
||||
if (IsA(node, Var))
|
||||
{
|
||||
@@ -321,7 +320,7 @@ check_ungrouped_columns_walker(Node *node,
|
||||
|
||||
/* Found an ungrouped local variable; generate error message */
|
||||
Assert(var->varno > 0 &&
|
||||
(int) var->varno <= list_length(context->pstate->p_rtable));
|
||||
(int) var->varno <= list_length(context->pstate->p_rtable));
|
||||
rte = rt_fetch(var->varno, context->pstate->p_rtable);
|
||||
attname = get_rte_attribute_name(rte, var->varattno);
|
||||
if (context->sublevels_up == 0)
|
||||
@@ -390,10 +389,10 @@ build_aggregate_fnexprs(Oid agg_input_type,
|
||||
transfn_nargs = get_func_nargs(transfn_oid);
|
||||
|
||||
/*
|
||||
* Build arg list to use in the transfn FuncExpr node. We really only
|
||||
* care that transfn can discover the actual argument types at runtime
|
||||
* using get_fn_expr_argtype(), so it's okay to use Param nodes that
|
||||
* don't correspond to any real Param.
|
||||
* Build arg list to use in the transfn FuncExpr node. We really only care
|
||||
* that transfn can discover the actual argument types at runtime using
|
||||
* get_fn_expr_argtype(), so it's okay to use Param nodes that don't
|
||||
* correspond to any real Param.
|
||||
*/
|
||||
arg0 = makeNode(Param);
|
||||
arg0->paramkind = PARAM_EXEC;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.142 2005/06/05 00:38:09 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.143 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -87,10 +87,10 @@ transformFromClause(ParseState *pstate, List *frmList)
|
||||
ListCell *fl;
|
||||
|
||||
/*
|
||||
* The grammar will have produced a list of RangeVars,
|
||||
* RangeSubselects, RangeFunctions, and/or JoinExprs. Transform each
|
||||
* one (possibly adding entries to the rtable), check for duplicate
|
||||
* refnames, and then add it to the joinlist and namespaces.
|
||||
* The grammar will have produced a list of RangeVars, RangeSubselects,
|
||||
* RangeFunctions, and/or JoinExprs. Transform each one (possibly adding
|
||||
* entries to the rtable), check for duplicate refnames, and then add it
|
||||
* to the joinlist and namespaces.
|
||||
*/
|
||||
foreach(fl, frmList)
|
||||
{
|
||||
@@ -148,8 +148,8 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
|
||||
heap_close(pstate->p_target_relation, NoLock);
|
||||
|
||||
/*
|
||||
* Open target rel and grab suitable lock (which we will hold till end
|
||||
* of transaction).
|
||||
* Open target rel and grab suitable lock (which we will hold till end of
|
||||
* transaction).
|
||||
*
|
||||
* analyze.c will eventually do the corresponding heap_close(), but *not*
|
||||
* release the lock.
|
||||
@@ -168,14 +168,13 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
|
||||
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
|
||||
|
||||
/*
|
||||
* Override addRangeTableEntry's default ACL_SELECT permissions check,
|
||||
* and instead mark target table as requiring exactly the specified
|
||||
* Override addRangeTableEntry's default ACL_SELECT permissions check, and
|
||||
* instead mark target table as requiring exactly the specified
|
||||
* permissions.
|
||||
*
|
||||
* If we find an explicit reference to the rel later during parse
|
||||
* analysis, scanRTEForColumn will add the ACL_SELECT bit back again.
|
||||
* That can't happen for INSERT but it is possible for UPDATE and
|
||||
* DELETE.
|
||||
* If we find an explicit reference to the rel later during parse analysis,
|
||||
* scanRTEForColumn will add the ACL_SELECT bit back again. That can't
|
||||
* happen for INSERT but it is possible for UPDATE and DELETE.
|
||||
*/
|
||||
rte->requiredPerms = requiredPerms;
|
||||
|
||||
@@ -294,10 +293,9 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
|
||||
*rvars;
|
||||
|
||||
/*
|
||||
* We cheat a little bit here by building an untransformed operator
|
||||
* tree whose leaves are the already-transformed Vars. This is OK
|
||||
* because transformExpr() won't complain about already-transformed
|
||||
* subnodes.
|
||||
* We cheat a little bit here by building an untransformed operator tree
|
||||
* whose leaves are the already-transformed Vars. This is OK because
|
||||
* transformExpr() won't complain about already-transformed subnodes.
|
||||
*/
|
||||
forboth(lvars, leftVars, rvars, rightVars)
|
||||
{
|
||||
@@ -319,10 +317,10 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
|
||||
}
|
||||
|
||||
/*
|
||||
* Since the references are already Vars, and are certainly from the
|
||||
* input relations, we don't have to go through the same pushups that
|
||||
* transformJoinOnClause() does. Just invoke transformExpr() to fix
|
||||
* up the operators, and we're done.
|
||||
* Since the references are already Vars, and are certainly from the input
|
||||
* relations, we don't have to go through the same pushups that
|
||||
* transformJoinOnClause() does. Just invoke transformExpr() to fix up
|
||||
* the operators, and we're done.
|
||||
*/
|
||||
result = transformExpr(pstate, result);
|
||||
|
||||
@@ -349,14 +347,13 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
|
||||
int varno;
|
||||
|
||||
/*
|
||||
* This is a tad tricky, for two reasons. First, the namespace that
|
||||
* the join expression should see is just the two subtrees of the JOIN
|
||||
* plus any outer references from upper pstate levels. So,
|
||||
* temporarily set this pstate's namespace accordingly. (We need not
|
||||
* check for refname conflicts, because transformFromClauseItem()
|
||||
* already did.) NOTE: this code is OK only because the ON clause
|
||||
* can't legally alter the namespace by causing implicit relation refs
|
||||
* to be added.
|
||||
* This is a tad tricky, for two reasons. First, the namespace that the
|
||||
* join expression should see is just the two subtrees of the JOIN plus
|
||||
* any outer references from upper pstate levels. So, temporarily set
|
||||
* this pstate's namespace accordingly. (We need not check for refname
|
||||
* conflicts, because transformFromClauseItem() already did.) NOTE: this
|
||||
* code is OK only because the ON clause can't legally alter the namespace
|
||||
* by causing implicit relation refs to be added.
|
||||
*/
|
||||
save_relnamespace = pstate->p_relnamespace;
|
||||
save_varnamespace = pstate->p_varnamespace;
|
||||
@@ -371,11 +368,10 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
|
||||
|
||||
/*
|
||||
* Second, we need to check that the ON condition doesn't refer to any
|
||||
* rels outside the input subtrees of the JOIN. It could do that
|
||||
* despite our hack on the namespace if it uses fully-qualified names.
|
||||
* So, grovel through the transformed clause and make sure there are
|
||||
* no bogus references. (Outer references are OK, and are ignored
|
||||
* here.)
|
||||
* rels outside the input subtrees of the JOIN. It could do that despite
|
||||
* our hack on the namespace if it uses fully-qualified names. So, grovel
|
||||
* through the transformed clause and make sure there are no bogus
|
||||
* references. (Outer references are OK, and are ignored here.)
|
||||
*/
|
||||
clause_varnos = pull_varnos(result);
|
||||
clause_varnos = bms_del_members(clause_varnos, containedRels);
|
||||
@@ -383,8 +379,8 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("JOIN/ON clause refers to \"%s\", which is not part of JOIN",
|
||||
rt_fetch(varno, pstate->p_rtable)->eref->aliasname)));
|
||||
errmsg("JOIN/ON clause refers to \"%s\", which is not part of JOIN",
|
||||
rt_fetch(varno, pstate->p_rtable)->eref->aliasname)));
|
||||
}
|
||||
bms_free(clause_varnos);
|
||||
|
||||
@@ -400,9 +396,9 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
|
||||
RangeTblEntry *rte;
|
||||
|
||||
/*
|
||||
* mark this entry to indicate it comes from the FROM clause. In SQL,
|
||||
* the target list can only refer to range variables specified in the
|
||||
* from clause but we follow the more powerful POSTQUEL semantics and
|
||||
* mark this entry to indicate it comes from the FROM clause. In SQL, the
|
||||
* target list can only refer to range variables specified in the from
|
||||
* clause but we follow the more powerful POSTQUEL semantics and
|
||||
* automatically generate the range variable if not specified. However
|
||||
* there are times we need to know whether the entries are legitimate.
|
||||
*/
|
||||
@@ -424,9 +420,9 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
|
||||
RangeTblEntry *rte;
|
||||
|
||||
/*
|
||||
* We require user to supply an alias for a subselect, per SQL92. To
|
||||
* relax this, we'd have to be prepared to gin up a unique alias for
|
||||
* an unlabeled subselect.
|
||||
* We require user to supply an alias for a subselect, per SQL92. To relax
|
||||
* this, we'd have to be prepared to gin up a unique alias for an
|
||||
* unlabeled subselect.
|
||||
*/
|
||||
if (r->alias == NULL)
|
||||
ereport(ERROR,
|
||||
@@ -439,9 +435,9 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
|
||||
parsetrees = parse_sub_analyze(r->subquery, pstate);
|
||||
|
||||
/*
|
||||
* Check that we got something reasonable. Most of these conditions
|
||||
* are probably impossible given restrictions of the grammar, but
|
||||
* check 'em anyway.
|
||||
* Check that we got something reasonable. Most of these conditions are
|
||||
* probably impossible given restrictions of the grammar, but check 'em
|
||||
* anyway.
|
||||
*/
|
||||
if (list_length(parsetrees) != 1)
|
||||
elog(ERROR, "unexpected parse analysis result for subquery in FROM");
|
||||
@@ -457,19 +453,17 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
|
||||
errmsg("subquery in FROM may not have SELECT INTO")));
|
||||
|
||||
/*
|
||||
* The subquery cannot make use of any variables from FROM items
|
||||
* created earlier in the current query. Per SQL92, the scope of a
|
||||
* FROM item does not include other FROM items. Formerly we hacked
|
||||
* the namespace so that the other variables weren't even visible, but
|
||||
* it seems more useful to leave them visible and give a specific
|
||||
* error message.
|
||||
* The subquery cannot make use of any variables from FROM items created
|
||||
* earlier in the current query. Per SQL92, the scope of a FROM item does
|
||||
* not include other FROM items. Formerly we hacked the namespace so that
|
||||
* the other variables weren't even visible, but it seems more useful to
|
||||
* leave them visible and give a specific error message.
|
||||
*
|
||||
* XXX this will need further work to support SQL99's LATERAL() feature,
|
||||
* wherein such references would indeed be legal.
|
||||
*
|
||||
* We can skip groveling through the subquery if there's not anything
|
||||
* visible in the current query. Also note that outer references are
|
||||
* OK.
|
||||
* We can skip groveling through the subquery if there's not anything visible
|
||||
* in the current query. Also note that outer references are OK.
|
||||
*/
|
||||
if (pstate->p_relnamespace || pstate->p_varnamespace)
|
||||
{
|
||||
@@ -500,9 +494,9 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
|
||||
/*
|
||||
* Get function name for possible use as alias. We use the same
|
||||
* transformation rules as for a SELECT output expression. For a
|
||||
* FuncCall node, the result will be the function name, but it is
|
||||
* possible for the grammar to hand back other node types.
|
||||
* transformation rules as for a SELECT output expression. For a FuncCall
|
||||
* node, the result will be the function name, but it is possible for the
|
||||
* grammar to hand back other node types.
|
||||
*/
|
||||
funcname = FigureColname(r->funccallnode);
|
||||
|
||||
@@ -514,8 +508,8 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
/*
|
||||
* The function parameters cannot make use of any variables from other
|
||||
* FROM items. (Compare to transformRangeSubselect(); the coding is
|
||||
* different though because we didn't parse as a sub-select with its
|
||||
* own level of namespace.)
|
||||
* different though because we didn't parse as a sub-select with its own
|
||||
* level of namespace.)
|
||||
*
|
||||
* XXX this will need further work to support SQL99's LATERAL() feature,
|
||||
* wherein such references would indeed be legal.
|
||||
@@ -529,8 +523,8 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
}
|
||||
|
||||
/*
|
||||
* Disallow aggregate functions in the expression. (No reason to
|
||||
* postpone this check until parseCheckAggregates.)
|
||||
* Disallow aggregate functions in the expression. (No reason to postpone
|
||||
* this check until parseCheckAggregates.)
|
||||
*/
|
||||
if (pstate->p_hasAggs)
|
||||
{
|
||||
@@ -541,8 +535,8 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
}
|
||||
|
||||
/*
|
||||
* If a coldeflist is supplied, ensure it defines a legal set of names
|
||||
* (no duplicates) and datatypes (no pseudo-types, for instance).
|
||||
* If a coldeflist is supplied, ensure it defines a legal set of names (no
|
||||
* duplicates) and datatypes (no pseudo-types, for instance).
|
||||
*/
|
||||
if (r->coldeflist)
|
||||
{
|
||||
@@ -576,7 +570,7 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r)
|
||||
* (We could extract this from the function return node, but it saves cycles
|
||||
* to pass it back separately.)
|
||||
*
|
||||
* *top_rti: receives the rangetable index of top_rte. (Ditto.)
|
||||
* *top_rti: receives the rangetable index of top_rte. (Ditto.)
|
||||
*
|
||||
* *relnamespace: receives a List of the RTEs exposed as relation names
|
||||
* by this item.
|
||||
@@ -599,7 +593,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
/* Plain relation reference */
|
||||
RangeTblRef *rtr;
|
||||
RangeTblEntry *rte;
|
||||
int rtindex;
|
||||
int rtindex;
|
||||
|
||||
rte = transformTableEntry(pstate, (RangeVar *) n);
|
||||
/* assume new rte is at end */
|
||||
@@ -618,7 +612,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
/* sub-SELECT is like a plain relation */
|
||||
RangeTblRef *rtr;
|
||||
RangeTblEntry *rte;
|
||||
int rtindex;
|
||||
int rtindex;
|
||||
|
||||
rte = transformRangeSubselect(pstate, (RangeSubselect *) n);
|
||||
/* assume new rte is at end */
|
||||
@@ -637,7 +631,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
/* function is like a plain relation */
|
||||
RangeTblRef *rtr;
|
||||
RangeTblEntry *rte;
|
||||
int rtindex;
|
||||
int rtindex;
|
||||
|
||||
rte = transformRangeFunction(pstate, (RangeFunction *) n);
|
||||
/* assume new rte is at end */
|
||||
@@ -688,8 +682,8 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
&r_containedRels);
|
||||
|
||||
/*
|
||||
* Check for conflicting refnames in left and right subtrees. Must
|
||||
* do this because higher levels will assume I hand back a self-
|
||||
* Check for conflicting refnames in left and right subtrees. Must do
|
||||
* this because higher levels will assume I hand back a self-
|
||||
* consistent namespace subtree.
|
||||
*/
|
||||
checkNameSpaceConflicts(pstate, l_relnamespace, r_relnamespace);
|
||||
@@ -715,12 +709,12 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
|
||||
/*
|
||||
* Natural join does not explicitly specify columns; must generate
|
||||
* columns to join. Need to run through the list of columns from
|
||||
* each table or join result and match up the column names. Use
|
||||
* the first table, and check every column in the second table for
|
||||
* a match. (We'll check that the matches were unique later on.)
|
||||
* The result of this step is a list of column names just like an
|
||||
* explicitly-written USING list.
|
||||
* columns to join. Need to run through the list of columns from each
|
||||
* table or join result and match up the column names. Use the first
|
||||
* table, and check every column in the second table for a match.
|
||||
* (We'll check that the matches were unique later on.) The result of
|
||||
* this step is a list of column names just like an explicitly-written
|
||||
* USING list.
|
||||
*/
|
||||
if (j->isNatural)
|
||||
{
|
||||
@@ -763,9 +757,9 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
if (j->using)
|
||||
{
|
||||
/*
|
||||
* JOIN/USING (or NATURAL JOIN, as transformed above).
|
||||
* Transform the list into an explicit ON-condition, and
|
||||
* generate a list of merged result columns.
|
||||
* JOIN/USING (or NATURAL JOIN, as transformed above). Transform
|
||||
* the list into an explicit ON-condition, and generate a list of
|
||||
* merged result columns.
|
||||
*/
|
||||
List *ucols = j->using;
|
||||
List *l_usingvars = NIL;
|
||||
@@ -917,10 +911,10 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
*top_rti = j->rtindex;
|
||||
|
||||
/*
|
||||
* Prepare returned namespace list. If the JOIN has an alias
|
||||
* then it hides the contained RTEs as far as the relnamespace
|
||||
* goes; otherwise, put the contained RTEs and *not* the JOIN
|
||||
* into relnamespace.
|
||||
* Prepare returned namespace list. If the JOIN has an alias then it
|
||||
* hides the contained RTEs as far as the relnamespace goes;
|
||||
* otherwise, put the contained RTEs and *not* the JOIN into
|
||||
* relnamespace.
|
||||
*/
|
||||
if (j->alias)
|
||||
{
|
||||
@@ -975,10 +969,10 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert coercion functions if needed. Note that a difference in
|
||||
* typmod can only happen if input has typmod but outcoltypmod is -1.
|
||||
* In that case we insert a RelabelType to clearly mark that result's
|
||||
* typmod is not same as input. We never need coerce_type_typmod.
|
||||
* Insert coercion functions if needed. Note that a difference in typmod
|
||||
* can only happen if input has typmod but outcoltypmod is -1. In that
|
||||
* case we insert a RelabelType to clearly mark that result's typmod is
|
||||
* not same as input. We never need coerce_type_typmod.
|
||||
*/
|
||||
if (l_colvar->vartype != outcoltype)
|
||||
l_node = coerce_type(pstate, (Node *) l_colvar, l_colvar->vartype,
|
||||
@@ -1030,8 +1024,8 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
|
||||
case JOIN_FULL:
|
||||
{
|
||||
/*
|
||||
* Here we must build a COALESCE expression to ensure that
|
||||
* the join output is non-null if either input is.
|
||||
* Here we must build a COALESCE expression to ensure that the
|
||||
* join output is non-null if either input is.
|
||||
*/
|
||||
CoalesceExpr *c = makeNode(CoalesceExpr);
|
||||
|
||||
@@ -1095,9 +1089,9 @@ transformLimitClause(ParseState *pstate, Node *clause,
|
||||
qual = coerce_to_integer(pstate, qual, constructName);
|
||||
|
||||
/*
|
||||
* LIMIT can't refer to any vars or aggregates of the current query;
|
||||
* we don't allow subselects either (though that case would at least
|
||||
* be sensible)
|
||||
* LIMIT can't refer to any vars or aggregates of the current query; we
|
||||
* don't allow subselects either (though that case would at least be
|
||||
* sensible)
|
||||
*/
|
||||
if (contain_vars_of_level(qual, 0))
|
||||
{
|
||||
@@ -1193,20 +1187,19 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
|
||||
{
|
||||
/*
|
||||
* In GROUP BY, we must prefer a match against a FROM-clause
|
||||
* column to one against the targetlist. Look to see if there
|
||||
* is a matching column. If so, fall through to let
|
||||
* transformExpr() do the rest. NOTE: if name could refer
|
||||
* ambiguously to more than one column name exposed by FROM,
|
||||
* colNameToVar will ereport(ERROR). That's just what we want
|
||||
* here.
|
||||
* column to one against the targetlist. Look to see if there is
|
||||
* a matching column. If so, fall through to let transformExpr()
|
||||
* do the rest. NOTE: if name could refer ambiguously to more
|
||||
* than one column name exposed by FROM, colNameToVar will
|
||||
* ereport(ERROR). That's just what we want here.
|
||||
*
|
||||
* Small tweak for 7.4.3: ignore matches in upper query levels.
|
||||
* This effectively changes the search order for bare names to
|
||||
* (1) local FROM variables, (2) local targetlist aliases, (3)
|
||||
* outer FROM variables, whereas before it was (1) (3) (2).
|
||||
* SQL92 and SQL99 do not allow GROUPing BY an outer
|
||||
* reference, so this breaks no cases that are legal per spec,
|
||||
* and it seems a more self-consistent behavior.
|
||||
* Small tweak for 7.4.3: ignore matches in upper query levels. This
|
||||
* effectively changes the search order for bare names to (1)
|
||||
* local FROM variables, (2) local targetlist aliases, (3) outer
|
||||
* FROM variables, whereas before it was (1) (3) (2). SQL92 and
|
||||
* SQL99 do not allow GROUPing BY an outer reference, so this
|
||||
* breaks no cases that are legal per spec, and it seems a more
|
||||
* self-consistent behavior.
|
||||
*/
|
||||
if (colNameToVar(pstate, name, true) != NULL)
|
||||
name = NULL;
|
||||
@@ -1292,9 +1285,9 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
|
||||
}
|
||||
|
||||
/*
|
||||
* If no matches, construct a new target entry which is appended to
|
||||
* the end of the target list. This target is given resjunk = TRUE so
|
||||
* that it will not be projected into the final tuple.
|
||||
* If no matches, construct a new target entry which is appended to the
|
||||
* end of the target list. This target is given resjunk = TRUE so that it
|
||||
* will not be projected into the final tuple.
|
||||
*/
|
||||
target_result = transformTargetEntry(pstate, node, expr, NULL, true);
|
||||
|
||||
@@ -1349,11 +1342,11 @@ transformGroupClause(ParseState *pstate, List *grouplist,
|
||||
|
||||
/*
|
||||
* If the GROUP BY clause matches the ORDER BY clause, we want to
|
||||
* adopt the ordering operators from the latter rather than using
|
||||
* the default ops. This allows "GROUP BY foo ORDER BY foo DESC"
|
||||
* to be done with only one sort step. Note we are assuming that
|
||||
* any user-supplied ordering operator will bring equal values
|
||||
* together, which is all that GROUP BY needs.
|
||||
* adopt the ordering operators from the latter rather than using the
|
||||
* default ops. This allows "GROUP BY foo ORDER BY foo DESC" to be
|
||||
* done with only one sort step. Note we are assuming that any
|
||||
* user-supplied ordering operator will bring equal values together,
|
||||
* which is all that GROUP BY needs.
|
||||
*/
|
||||
if (sortItem &&
|
||||
((SortClause *) lfirst(sortItem))->tleSortGroupRef ==
|
||||
@@ -1435,11 +1428,11 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
/* We had SELECT DISTINCT */
|
||||
|
||||
/*
|
||||
* All non-resjunk elements from target list that are not already
|
||||
* in the sort list should be added to it. (We don't really care
|
||||
* what order the DISTINCT fields are checked in, so we can leave
|
||||
* the user's ORDER BY spec alone, and just add additional sort
|
||||
* keys to it to ensure that all targetlist items get sorted.)
|
||||
* All non-resjunk elements from target list that are not already in
|
||||
* the sort list should be added to it. (We don't really care what
|
||||
* order the DISTINCT fields are checked in, so we can leave the
|
||||
* user's ORDER BY spec alone, and just add additional sort keys to it
|
||||
* to ensure that all targetlist items get sorted.)
|
||||
*/
|
||||
*sortClause = addAllTargetsToSortList(pstate,
|
||||
*sortClause,
|
||||
@@ -1449,9 +1442,9 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
/*
|
||||
* Now, DISTINCT list consists of all non-resjunk sortlist items.
|
||||
* Actually, all the sortlist items had better be non-resjunk!
|
||||
* Otherwise, user wrote SELECT DISTINCT with an ORDER BY item
|
||||
* that does not appear anywhere in the SELECT targetlist, and we
|
||||
* can't implement that with only one sorting pass...
|
||||
* Otherwise, user wrote SELECT DISTINCT with an ORDER BY item that
|
||||
* does not appear anywhere in the SELECT targetlist, and we can't
|
||||
* implement that with only one sorting pass...
|
||||
*/
|
||||
foreach(slitem, *sortClause)
|
||||
{
|
||||
@@ -1474,16 +1467,16 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
* If the user writes both DISTINCT ON and ORDER BY, then the two
|
||||
* expression lists must match (until one or the other runs out).
|
||||
* Otherwise the ORDER BY requires a different sort order than the
|
||||
* DISTINCT does, and we can't implement that with only one sort
|
||||
* pass (and if we do two passes, the results will be rather
|
||||
* DISTINCT does, and we can't implement that with only one sort pass
|
||||
* (and if we do two passes, the results will be rather
|
||||
* unpredictable). However, it's OK to have more DISTINCT ON
|
||||
* expressions than ORDER BY expressions; we can just add the
|
||||
* extra DISTINCT values to the sort list, much as we did above
|
||||
* for ordinary DISTINCT fields.
|
||||
* expressions than ORDER BY expressions; we can just add the extra
|
||||
* DISTINCT values to the sort list, much as we did above for ordinary
|
||||
* DISTINCT fields.
|
||||
*
|
||||
* Actually, it'd be OK for the common prefixes of the two lists to
|
||||
* match in any order, but implementing that check seems like more
|
||||
* trouble than it's worth.
|
||||
* Actually, it'd be OK for the common prefixes of the two lists to match
|
||||
* in any order, but implementing that check seems like more trouble
|
||||
* than it's worth.
|
||||
*/
|
||||
ListCell *nextsortlist = list_head(*sortClause);
|
||||
|
||||
@@ -1508,12 +1501,12 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
else
|
||||
{
|
||||
*sortClause = addTargetToSortList(pstate, tle,
|
||||
*sortClause, *targetlist,
|
||||
*sortClause, *targetlist,
|
||||
SORTBY_ASC, NIL, true);
|
||||
|
||||
/*
|
||||
* Probably, the tle should always have been added at the
|
||||
* end of the sort list ... but search to be safe.
|
||||
* Probably, the tle should always have been added at the end
|
||||
* of the sort list ... but search to be safe.
|
||||
*/
|
||||
foreach(slitem, *sortClause)
|
||||
{
|
||||
@@ -1638,7 +1631,7 @@ assignSortGroupRef(TargetEntry *tle, List *tlist)
|
||||
Index maxRef;
|
||||
ListCell *l;
|
||||
|
||||
if (tle->ressortgroupref) /* already has one? */
|
||||
if (tle->ressortgroupref) /* already has one? */
|
||||
return tle->ressortgroupref;
|
||||
|
||||
/* easiest way to pick an unused refnumber: max used + 1 */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.131 2005/06/04 19:19:42 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.132 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -82,9 +82,9 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
|
||||
ccontext, cformat);
|
||||
|
||||
/*
|
||||
* If the target is a fixed-length type, it may need a length coercion
|
||||
* as well as a type coercion. If we find ourselves adding both,
|
||||
* force the inner coercion node to implicit display form.
|
||||
* If the target is a fixed-length type, it may need a length coercion as
|
||||
* well as a type coercion. If we find ourselves adding both, force the
|
||||
* inner coercion node to implicit display form.
|
||||
*/
|
||||
result = coerce_type_typmod(result,
|
||||
targettype, targettypmod,
|
||||
@@ -140,9 +140,9 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
if (inputTypeId == UNKNOWNOID && IsA(node, Const))
|
||||
{
|
||||
/*
|
||||
* Input is a string constant with previously undetermined type.
|
||||
* Apply the target type's typinput function to it to produce a
|
||||
* constant of the target type.
|
||||
* Input is a string constant with previously undetermined type. Apply
|
||||
* the target type's typinput function to it to produce a constant of
|
||||
* the target type.
|
||||
*
|
||||
* NOTE: this case cannot be folded together with the other
|
||||
* constant-input case, since the typinput function does not
|
||||
@@ -151,10 +151,10 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
* float-to-int type conversion will round to integer.
|
||||
*
|
||||
* XXX if the typinput function is not immutable, we really ought to
|
||||
* postpone evaluation of the function call until runtime. But
|
||||
* there is no way to represent a typinput function call as an
|
||||
* expression tree, because C-string values are not Datums. (XXX
|
||||
* This *is* possible as of 7.3, do we want to do it?)
|
||||
* postpone evaluation of the function call until runtime. But there
|
||||
* is no way to represent a typinput function call as an expression
|
||||
* tree, because C-string values are not Datums. (XXX This *is*
|
||||
* possible as of 7.3, do we want to do it?)
|
||||
*/
|
||||
Const *con = (Const *) node;
|
||||
Const *newcon = makeNode(Const);
|
||||
@@ -176,14 +176,13 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
|
||||
/*
|
||||
* We pass typmod -1 to the input routine, primarily because
|
||||
* existing input routines follow implicit-coercion semantics
|
||||
* for length checks, which is not always what we want here.
|
||||
* Any length constraint will be applied later by our caller.
|
||||
* existing input routines follow implicit-coercion semantics for
|
||||
* length checks, which is not always what we want here. Any
|
||||
* length constraint will be applied later by our caller.
|
||||
*
|
||||
* Note that we call stringTypeDatum using the domain's pg_type
|
||||
* row, if it's a domain. This works because the domain row
|
||||
* has the same typinput and typelem as the base type ---
|
||||
* ugly...
|
||||
* Note that we call stringTypeDatum using the domain's pg_type row,
|
||||
* if it's a domain. This works because the domain row has the
|
||||
* same typinput and typelem as the base type --- ugly...
|
||||
*/
|
||||
newcon->constvalue = stringTypeDatum(targetType, val, -1);
|
||||
}
|
||||
@@ -204,8 +203,8 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
pstate != NULL && pstate->p_variableparams)
|
||||
{
|
||||
/*
|
||||
* Input is a Param of previously undetermined type, and we want
|
||||
* to update our knowledge of the Param's type. Find the topmost
|
||||
* Input is a Param of previously undetermined type, and we want to
|
||||
* update our knowledge of the Param's type. Find the topmost
|
||||
* ParseState and update the state.
|
||||
*/
|
||||
Param *param = (Param *) node;
|
||||
@@ -236,10 +235,10 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
/* Ooops */
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_AMBIGUOUS_PARAMETER),
|
||||
errmsg("inconsistent types deduced for parameter $%d",
|
||||
paramno),
|
||||
errmsg("inconsistent types deduced for parameter $%d",
|
||||
paramno),
|
||||
errdetail("%s versus %s",
|
||||
format_type_be(toppstate->p_paramtypes[paramno - 1]),
|
||||
format_type_be(toppstate->p_paramtypes[paramno - 1]),
|
||||
format_type_be(targetTypeId))));
|
||||
}
|
||||
|
||||
@@ -252,11 +251,11 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
if (OidIsValid(funcId))
|
||||
{
|
||||
/*
|
||||
* Generate an expression tree representing run-time
|
||||
* application of the conversion function. If we are dealing
|
||||
* with a domain target type, the conversion function will
|
||||
* yield the base type, and we need to extract the correct
|
||||
* typmod to use from the domain's typtypmod.
|
||||
* Generate an expression tree representing run-time application
|
||||
* of the conversion function. If we are dealing with a domain
|
||||
* target type, the conversion function will yield the base type,
|
||||
* and we need to extract the correct typmod to use from the
|
||||
* domain's typtypmod.
|
||||
*/
|
||||
Oid baseTypeId = getBaseType(targetTypeId);
|
||||
int32 baseTypeMod;
|
||||
@@ -269,13 +268,12 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
result = build_coercion_expression(node, funcId,
|
||||
baseTypeId, baseTypeMod,
|
||||
cformat,
|
||||
(cformat != COERCE_IMPLICIT_CAST));
|
||||
(cformat != COERCE_IMPLICIT_CAST));
|
||||
|
||||
/*
|
||||
* If domain, coerce to the domain type and relabel with
|
||||
* domain type ID. We can skip the internal length-coercion
|
||||
* step if the selected coercion function was a type-and-length
|
||||
* coercion.
|
||||
* If domain, coerce to the domain type and relabel with domain
|
||||
* type ID. We can skip the internal length-coercion step if the
|
||||
* selected coercion function was a type-and-length coercion.
|
||||
*/
|
||||
if (targetTypeId != baseTypeId)
|
||||
result = coerce_to_domain(result, baseTypeId, targetTypeId,
|
||||
@@ -286,10 +284,9 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We don't need to do a physical conversion, but we do need
|
||||
* to attach a RelabelType node so that the expression will be
|
||||
* seen to have the intended type when inspected by
|
||||
* higher-level code.
|
||||
* We don't need to do a physical conversion, but we do need to
|
||||
* attach a RelabelType node so that the expression will be seen
|
||||
* to have the intended type when inspected by higher-level code.
|
||||
*
|
||||
* Also, domains may have value restrictions beyond the base type
|
||||
* that must be accounted for. If the destination is a domain
|
||||
@@ -300,11 +297,10 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
if (result == node)
|
||||
{
|
||||
/*
|
||||
* XXX could we label result with exprTypmod(node) instead
|
||||
* of default -1 typmod, to save a possible
|
||||
* length-coercion later? Would work if both types have
|
||||
* same interpretation of typmod, which is likely but not
|
||||
* certain.
|
||||
* XXX could we label result with exprTypmod(node) instead of
|
||||
* default -1 typmod, to save a possible length-coercion
|
||||
* later? Would work if both types have same interpretation of
|
||||
* typmod, which is likely but not certain.
|
||||
*/
|
||||
result = (Node *) makeRelabelType((Expr *) result,
|
||||
targetTypeId, -1,
|
||||
@@ -331,8 +327,8 @@ coerce_type(ParseState *pstate, Node *node,
|
||||
{
|
||||
/*
|
||||
* Input class type is a subclass of target, so generate an
|
||||
* appropriate runtime conversion (removing unneeded columns
|
||||
* and possibly rearranging the ones that are wanted).
|
||||
* appropriate runtime conversion (removing unneeded columns and
|
||||
* possibly rearranging the ones that are wanted).
|
||||
*/
|
||||
ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
|
||||
|
||||
@@ -386,23 +382,23 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
|
||||
}
|
||||
|
||||
/*
|
||||
* If input is an untyped string constant, assume we can convert
|
||||
* it to anything.
|
||||
* If input is an untyped string constant, assume we can convert it to
|
||||
* anything.
|
||||
*/
|
||||
if (inputTypeId == UNKNOWNOID)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If pg_cast shows that we can coerce, accept. This test now
|
||||
* covers both binary-compatible and coercion-function cases.
|
||||
* If pg_cast shows that we can coerce, accept. This test now covers
|
||||
* both binary-compatible and coercion-function cases.
|
||||
*/
|
||||
if (find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
|
||||
&funcId))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If input is RECORD and target is a composite type, assume we
|
||||
* can coerce (may need tighter checking here)
|
||||
* If input is RECORD and target is a composite type, assume we can
|
||||
* coerce (may need tighter checking here)
|
||||
*/
|
||||
if (inputTypeId == RECORDOID &&
|
||||
ISCOMPLEX(targetTypeId))
|
||||
@@ -472,22 +468,21 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
|
||||
hide_coercion_node(arg);
|
||||
|
||||
/*
|
||||
* If the domain applies a typmod to its base type, build the
|
||||
* appropriate coercion step. Mark it implicit for display purposes,
|
||||
* because we don't want it shown separately by ruleutils.c; but the
|
||||
* isExplicit flag passed to the conversion function depends on the
|
||||
* manner in which the domain coercion is invoked, so that the
|
||||
* semantics of implicit and explicit coercion differ. (Is that
|
||||
* really the behavior we want?)
|
||||
* If the domain applies a typmod to its base type, build the appropriate
|
||||
* coercion step. Mark it implicit for display purposes, because we don't
|
||||
* want it shown separately by ruleutils.c; but the isExplicit flag passed
|
||||
* to the conversion function depends on the manner in which the domain
|
||||
* coercion is invoked, so that the semantics of implicit and explicit
|
||||
* coercion differ. (Is that really the behavior we want?)
|
||||
*
|
||||
* NOTE: because we apply this as part of the fixed expression structure,
|
||||
* ALTER DOMAIN cannot alter the typtypmod. But it's unclear that
|
||||
* that would be safe to do anyway, without lots of knowledge about
|
||||
* what the base type thinks the typmod means.
|
||||
* ALTER DOMAIN cannot alter the typtypmod. But it's unclear that that
|
||||
* would be safe to do anyway, without lots of knowledge about what the
|
||||
* base type thinks the typmod means.
|
||||
*/
|
||||
if (!lengthCoercionDone)
|
||||
{
|
||||
int32 typmod = get_typtypmod(typeId);
|
||||
int32 typmod = get_typtypmod(typeId);
|
||||
|
||||
if (typmod >= 0)
|
||||
arg = coerce_type_typmod(arg, baseTypeId, typmod,
|
||||
@@ -497,10 +492,9 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
|
||||
}
|
||||
|
||||
/*
|
||||
* Now build the domain coercion node. This represents run-time
|
||||
* checking of any constraints currently attached to the domain. This
|
||||
* also ensures that the expression is properly labeled as to result
|
||||
* type.
|
||||
* Now build the domain coercion node. This represents run-time checking
|
||||
* of any constraints currently attached to the domain. This also ensures
|
||||
* that the expression is properly labeled as to result type.
|
||||
*/
|
||||
result = makeNode(CoerceToDomain);
|
||||
result->arg = (Expr *) arg;
|
||||
@@ -541,8 +535,8 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
|
||||
Oid funcId;
|
||||
|
||||
/*
|
||||
* A negative typmod is assumed to mean that no coercion is wanted.
|
||||
* Also, skip coercion if already done.
|
||||
* A negative typmod is assumed to mean that no coercion is wanted. Also,
|
||||
* skip coercion if already done.
|
||||
*/
|
||||
if (targetTypMod < 0 || targetTypMod == exprTypmod(node))
|
||||
return node;
|
||||
@@ -616,9 +610,9 @@ build_coercion_expression(Node *node, Oid funcId,
|
||||
procstruct = (Form_pg_proc) GETSTRUCT(tp);
|
||||
|
||||
/*
|
||||
* Asserts essentially check that function is a legal coercion
|
||||
* function. We can't make the seemingly obvious tests on prorettype
|
||||
* and proargtypes[0], because of various binary-compatibility cases.
|
||||
* Asserts essentially check that function is a legal coercion function.
|
||||
* We can't make the seemingly obvious tests on prorettype and
|
||||
* proargtypes[0], because of various binary-compatibility cases.
|
||||
*/
|
||||
/* Assert(targetTypeId == procstruct->prorettype); */
|
||||
Assert(!procstruct->proretset);
|
||||
@@ -685,8 +679,8 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
|
||||
if (node && IsA(node, RowExpr))
|
||||
{
|
||||
/*
|
||||
* Since the RowExpr must be of type RECORD, we needn't worry
|
||||
* about it containing any dropped columns.
|
||||
* Since the RowExpr must be of type RECORD, we needn't worry about it
|
||||
* containing any dropped columns.
|
||||
*/
|
||||
args = ((RowExpr *) node)->args;
|
||||
}
|
||||
@@ -721,8 +715,8 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
|
||||
if (tupdesc->attrs[i]->attisdropped)
|
||||
{
|
||||
/*
|
||||
* can't use atttypid here, but it doesn't really matter what
|
||||
* type the Const claims to be.
|
||||
* can't use atttypid here, but it doesn't really matter what type
|
||||
* the Const claims to be.
|
||||
*/
|
||||
newargs = lappend(newargs, makeNullConst(INT4OID));
|
||||
continue;
|
||||
@@ -752,7 +746,7 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
|
||||
format_type_be(targetTypeId)),
|
||||
errdetail("Cannot cast type %s to %s in column %d.",
|
||||
format_type_be(exprtype),
|
||||
format_type_be(tupdesc->attrs[i]->atttypid),
|
||||
format_type_be(tupdesc->attrs[i]->atttypid),
|
||||
ucolno)));
|
||||
newargs = lappend(newargs, expr);
|
||||
ucolno++;
|
||||
@@ -798,8 +792,8 @@ coerce_to_boolean(ParseState *pstate, Node *node,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
/* translator: first %s is name of a SQL construct, eg WHERE */
|
||||
errmsg("argument of %s must be type boolean, not type %s",
|
||||
constructName, format_type_be(inputTypeId))));
|
||||
errmsg("argument of %s must be type boolean, not type %s",
|
||||
constructName, format_type_be(inputTypeId))));
|
||||
}
|
||||
|
||||
if (expression_returns_set(node))
|
||||
@@ -837,8 +831,8 @@ coerce_to_integer(ParseState *pstate, Node *node,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
/* translator: first %s is name of a SQL construct, eg LIMIT */
|
||||
errmsg("argument of %s must be type integer, not type %s",
|
||||
constructName, format_type_be(inputTypeId))));
|
||||
errmsg("argument of %s must be type integer, not type %s",
|
||||
constructName, format_type_be(inputTypeId))));
|
||||
}
|
||||
|
||||
if (expression_returns_set(node))
|
||||
@@ -889,15 +883,13 @@ select_common_type(List *typeids, const char *context)
|
||||
else if (TypeCategory(ntype) != pcategory)
|
||||
{
|
||||
/*
|
||||
* both types in different categories? then not much
|
||||
* hope...
|
||||
* both types in different categories? then not much hope...
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
|
||||
/*
|
||||
* translator: first %s is name of a SQL construct, eg
|
||||
* CASE
|
||||
* translator: first %s is name of a SQL construct, eg CASE
|
||||
*/
|
||||
errmsg("%s types %s and %s cannot be matched",
|
||||
context,
|
||||
@@ -905,13 +897,12 @@ select_common_type(List *typeids, const char *context)
|
||||
format_type_be(ntype))));
|
||||
}
|
||||
else if (!IsPreferredType(pcategory, ptype) &&
|
||||
can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
|
||||
!can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
|
||||
can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
|
||||
!can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
|
||||
{
|
||||
/*
|
||||
* take new type if can coerce to it implicitly but not
|
||||
* the other way; but if we have a preferred type, stay on
|
||||
* it.
|
||||
* take new type if can coerce to it implicitly but not the
|
||||
* other way; but if we have a preferred type, stay on it.
|
||||
*/
|
||||
ptype = ntype;
|
||||
pcategory = TypeCategory(ptype);
|
||||
@@ -920,15 +911,15 @@ select_common_type(List *typeids, const char *context)
|
||||
}
|
||||
|
||||
/*
|
||||
* If all the inputs were UNKNOWN type --- ie, unknown-type literals
|
||||
* --- then resolve as type TEXT. This situation comes up with
|
||||
* constructs like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END);
|
||||
* SELECT 'foo' UNION SELECT 'bar'; It might seem desirable to leave
|
||||
* the construct's output type as UNKNOWN, but that really doesn't
|
||||
* work, because we'd probably end up needing a runtime coercion from
|
||||
* UNKNOWN to something else, and we usually won't have it. We need
|
||||
* to coerce the unknown literals while they are still literals, so a
|
||||
* decision has to be made now.
|
||||
* If all the inputs were UNKNOWN type --- ie, unknown-type literals ---
|
||||
* then resolve as type TEXT. This situation comes up with constructs
|
||||
* like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'
|
||||
* UNION SELECT 'bar'; It might seem desirable to leave the construct's
|
||||
* output type as UNKNOWN, but that really doesn't work, because we'd
|
||||
* probably end up needing a runtime coercion from UNKNOWN to something
|
||||
* else, and we usually won't have it. We need to coerce the unknown
|
||||
* literals while they are still literals, so a decision has to be made
|
||||
* now.
|
||||
*/
|
||||
if (ptype == UNKNOWNOID)
|
||||
ptype = TEXTOID;
|
||||
@@ -1005,9 +996,8 @@ check_generic_type_consistency(Oid *actual_arg_types,
|
||||
bool have_anyelement = false;
|
||||
|
||||
/*
|
||||
* Loop through the arguments to see if we have any that are ANYARRAY
|
||||
* or ANYELEMENT. If so, require the actual types to be
|
||||
* self-consistent
|
||||
* Loop through the arguments to see if we have any that are ANYARRAY or
|
||||
* ANYELEMENT. If so, require the actual types to be self-consistent
|
||||
*/
|
||||
for (j = 0; j < nargs; j++)
|
||||
{
|
||||
@@ -1050,8 +1040,7 @@ check_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (!OidIsValid(elem_typeid))
|
||||
{
|
||||
/*
|
||||
* if we don't have an element type yet, use the one we just
|
||||
* got
|
||||
* if we don't have an element type yet, use the one we just got
|
||||
*/
|
||||
elem_typeid = array_typelem;
|
||||
}
|
||||
@@ -1118,9 +1107,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
bool have_anyelement = (rettype == ANYELEMENTOID);
|
||||
|
||||
/*
|
||||
* Loop through the arguments to see if we have any that are ANYARRAY
|
||||
* or ANYELEMENT. If so, require the actual types to be
|
||||
* self-consistent
|
||||
* Loop through the arguments to see if we have any that are ANYARRAY or
|
||||
* ANYELEMENT. If so, require the actual types to be self-consistent
|
||||
*/
|
||||
for (j = 0; j < nargs; j++)
|
||||
{
|
||||
@@ -1137,7 +1125,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("arguments declared \"anyelement\" are not all alike"),
|
||||
errmsg("arguments declared \"anyelement\" are not all alike"),
|
||||
errdetail("%s versus %s",
|
||||
format_type_be(elem_typeid),
|
||||
format_type_be(actual_type))));
|
||||
@@ -1154,7 +1142,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (OidIsValid(array_typeid) && actual_type != array_typeid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("arguments declared \"anyarray\" are not all alike"),
|
||||
errmsg("arguments declared \"anyarray\" are not all alike"),
|
||||
errdetail("%s versus %s",
|
||||
format_type_be(array_typeid),
|
||||
format_type_be(actual_type))));
|
||||
@@ -1163,8 +1151,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast Track: if none of the arguments are ANYARRAY or ANYELEMENT,
|
||||
* return the unmodified rettype.
|
||||
* Fast Track: if none of the arguments are ANYARRAY or ANYELEMENT, return
|
||||
* the unmodified rettype.
|
||||
*/
|
||||
if (!have_generics)
|
||||
return rettype;
|
||||
@@ -1190,8 +1178,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (!OidIsValid(elem_typeid))
|
||||
{
|
||||
/*
|
||||
* if we don't have an element type yet, use the one we just
|
||||
* got
|
||||
* if we don't have an element type yet, use the one we just got
|
||||
*/
|
||||
elem_typeid = array_typelem;
|
||||
}
|
||||
@@ -1236,8 +1223,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (!OidIsValid(array_typeid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(elem_typeid))));
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(elem_typeid))));
|
||||
}
|
||||
declared_arg_types[j] = array_typeid;
|
||||
}
|
||||
@@ -1253,8 +1240,8 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
|
||||
if (!OidIsValid(array_typeid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(elem_typeid))));
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(elem_typeid))));
|
||||
}
|
||||
return array_typeid;
|
||||
}
|
||||
@@ -1307,8 +1294,8 @@ resolve_generic_type(Oid declared_type,
|
||||
if (!OidIsValid(array_typeid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(context_actual_type))));
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(context_actual_type))));
|
||||
return array_typeid;
|
||||
}
|
||||
}
|
||||
@@ -1471,8 +1458,8 @@ IsPreferredType(CATEGORY category, Oid type)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* This switch should agree with TypeCategory(), above. Note that at
|
||||
* this point, category certainly matches the type.
|
||||
* This switch should agree with TypeCategory(), above. Note that at this
|
||||
* point, category certainly matches the type.
|
||||
*/
|
||||
switch (category)
|
||||
{
|
||||
@@ -1679,17 +1666,16 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If there's no pg_cast entry, perhaps we are dealing with a pair
|
||||
* of array types. If so, and if the element types have a
|
||||
* suitable cast, use array_type_coerce() or
|
||||
* array_type_length_coerce().
|
||||
* If there's no pg_cast entry, perhaps we are dealing with a pair of
|
||||
* array types. If so, and if the element types have a suitable cast,
|
||||
* use array_type_coerce() or array_type_length_coerce().
|
||||
*
|
||||
* Hack: disallow coercions to oidvector and int2vector, which
|
||||
* otherwise tend to capture coercions that should go to "real" array
|
||||
* types. We want those types to be considered "real" arrays for many
|
||||
* purposes, but not this one. (Also, array_type_coerce isn't
|
||||
* guaranteed to produce an output that meets the restrictions of
|
||||
* these datatypes, such as being 1-dimensional.)
|
||||
* Hack: disallow coercions to oidvector and int2vector, which otherwise
|
||||
* tend to capture coercions that should go to "real" array types. We
|
||||
* want those types to be considered "real" arrays for many purposes,
|
||||
* but not this one. (Also, array_type_coerce isn't guaranteed to
|
||||
* produce an output that meets the restrictions of these datatypes,
|
||||
* such as being 1-dimensional.)
|
||||
*/
|
||||
Oid targetElemType;
|
||||
Oid sourceElemType;
|
||||
@@ -1699,7 +1685,7 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
|
||||
return false;
|
||||
|
||||
if ((targetElemType = get_element_type(targetTypeId)) != InvalidOid &&
|
||||
(sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
|
||||
(sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
|
||||
{
|
||||
if (find_coercion_pathway(targetElemType, sourceElemType,
|
||||
ccontext, &elemfuncid))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.184 2005/06/26 22:05:39 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.185 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -278,8 +278,8 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
|
||||
|
||||
/*
|
||||
* We have to split any field-selection operations apart from
|
||||
* subscripting. Adjacent A_Indices nodes have to be treated as a
|
||||
* single multidimensional subscript operation.
|
||||
* subscripting. Adjacent A_Indices nodes have to be treated as a single
|
||||
* multidimensional subscript operation.
|
||||
*/
|
||||
foreach(i, indirection)
|
||||
{
|
||||
@@ -295,7 +295,7 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
|
||||
if (subscripts)
|
||||
result = (Node *) transformArraySubscripts(pstate,
|
||||
result,
|
||||
exprType(result),
|
||||
exprType(result),
|
||||
InvalidOid,
|
||||
-1,
|
||||
subscripts,
|
||||
@@ -365,10 +365,10 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
/*
|
||||
* Not known as a column of any range-table entry.
|
||||
*
|
||||
* Consider the possibility that it's VALUE in a domain
|
||||
* check expression. (We handle VALUE as a name, not
|
||||
* a keyword, to avoid breaking a lot of applications
|
||||
* that have used VALUE as a column name in the past.)
|
||||
* Consider the possibility that it's VALUE in a domain check
|
||||
* expression. (We handle VALUE as a name, not a keyword,
|
||||
* to avoid breaking a lot of applications that have used
|
||||
* VALUE as a column name in the past.)
|
||||
*/
|
||||
if (pstate->p_value_substitute != NULL &&
|
||||
strcmp(name, "value") == 0)
|
||||
@@ -379,12 +379,12 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
|
||||
/*
|
||||
* Try to find the name as a relation. Note that only
|
||||
* relations already entered into the rangetable will
|
||||
* be recognized.
|
||||
* relations already entered into the rangetable will be
|
||||
* recognized.
|
||||
*
|
||||
* This is a hack for backwards compatibility with
|
||||
* PostQUEL-inspired syntax. The preferred form now
|
||||
* is "rel.*".
|
||||
* PostQUEL-inspired syntax. The preferred form now is
|
||||
* "rel.*".
|
||||
*/
|
||||
if (refnameRangeTblEntry(pstate, NULL, name,
|
||||
&levels_up) != NULL)
|
||||
@@ -414,13 +414,13 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
if (node == NULL)
|
||||
{
|
||||
/*
|
||||
* Not known as a column of any range-table entry, so
|
||||
* try it as a function call. Here, we will create an
|
||||
* Not known as a column of any range-table entry, so try
|
||||
* it as a function call. Here, we will create an
|
||||
* implicit RTE for tables not already entered.
|
||||
*/
|
||||
node = transformWholeRowRef(pstate, NULL, name1);
|
||||
node = ParseFuncOrColumn(pstate,
|
||||
list_make1(makeString(name2)),
|
||||
list_make1(makeString(name2)),
|
||||
list_make1(node),
|
||||
false, false, true);
|
||||
}
|
||||
@@ -446,7 +446,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
/* Try it as a function call */
|
||||
node = transformWholeRowRef(pstate, name1, name2);
|
||||
node = ParseFuncOrColumn(pstate,
|
||||
list_make1(makeString(name3)),
|
||||
list_make1(makeString(name3)),
|
||||
list_make1(node),
|
||||
false, false, true);
|
||||
}
|
||||
@@ -482,7 +482,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
/* Try it as a function call */
|
||||
node = transformWholeRowRef(pstate, name2, name3);
|
||||
node = ParseFuncOrColumn(pstate,
|
||||
list_make1(makeString(name4)),
|
||||
list_make1(makeString(name4)),
|
||||
list_make1(node),
|
||||
false, false, true);
|
||||
}
|
||||
@@ -491,8 +491,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("improper qualified name (too many dotted names): %s",
|
||||
NameListToString(cref->fields))));
|
||||
errmsg("improper qualified name (too many dotted names): %s",
|
||||
NameListToString(cref->fields))));
|
||||
node = NULL; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
@@ -515,7 +515,7 @@ transformParamRef(ParseState *pstate, ParamRef *pref)
|
||||
toppstate = toppstate->parentParseState;
|
||||
|
||||
/* Check parameter number is in range */
|
||||
if (paramno <= 0) /* probably can't happen? */
|
||||
if (paramno <= 0) /* probably can't happen? */
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_PARAMETER),
|
||||
errmsg("there is no parameter $%d", paramno)));
|
||||
@@ -563,9 +563,9 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
|
||||
Node *result;
|
||||
|
||||
/*
|
||||
* Special-case "foo = NULL" and "NULL = foo" for compatibility
|
||||
* with standards-broken products (like Microsoft's). Turn these
|
||||
* into IS NULL exprs.
|
||||
* Special-case "foo = NULL" and "NULL = foo" for compatibility with
|
||||
* standards-broken products (like Microsoft's). Turn these into IS NULL
|
||||
* exprs.
|
||||
*/
|
||||
if (Transform_null_equals &&
|
||||
list_length(a->name) == 1 &&
|
||||
@@ -588,10 +588,9 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
|
||||
((SubLink *) rexpr)->subLinkType == EXPR_SUBLINK)
|
||||
{
|
||||
/*
|
||||
* Convert "row op subselect" into a MULTIEXPR sublink.
|
||||
* Formerly the grammar did this, but now that a row construct
|
||||
* is allowed anywhere in expressions, it's easier to do it
|
||||
* here.
|
||||
* Convert "row op subselect" into a MULTIEXPR sublink. Formerly the
|
||||
* grammar did this, but now that a row construct is allowed anywhere
|
||||
* in expressions, it's easier to do it here.
|
||||
*/
|
||||
SubLink *s = (SubLink *) rexpr;
|
||||
|
||||
@@ -738,8 +737,8 @@ static Node *
|
||||
transformAExprOf(ParseState *pstate, A_Expr *a)
|
||||
{
|
||||
/*
|
||||
* Checking an expression for match to type. Will result in a
|
||||
* boolean constant node.
|
||||
* Checking an expression for match to type. Will result in a boolean
|
||||
* constant node.
|
||||
*/
|
||||
ListCell *telem;
|
||||
A_Const *n;
|
||||
@@ -758,8 +757,8 @@ transformAExprOf(ParseState *pstate, A_Expr *a)
|
||||
}
|
||||
|
||||
/*
|
||||
* Expect two forms: equals or not equals. Flip the sense of the
|
||||
* result for not equals.
|
||||
* Expect two forms: equals or not equals. Flip the sense of the result
|
||||
* for not equals.
|
||||
*/
|
||||
if (strcmp(strVal(linitial(a->name)), "!=") == 0)
|
||||
matched = (!matched);
|
||||
@@ -779,12 +778,11 @@ transformFuncCall(ParseState *pstate, FuncCall *fn)
|
||||
ListCell *args;
|
||||
|
||||
/*
|
||||
* Transform the list of arguments. We use a shallow list copy
|
||||
* and then transform-in-place to avoid O(N^2) behavior from
|
||||
* repeated lappend's.
|
||||
* Transform the list of arguments. We use a shallow list copy and then
|
||||
* transform-in-place to avoid O(N^2) behavior from repeated lappend's.
|
||||
*
|
||||
* XXX: repeated lappend() would no longer result in O(n^2)
|
||||
* behavior; worth reconsidering this design?
|
||||
* XXX: repeated lappend() would no longer result in O(n^2) behavior; worth
|
||||
* reconsidering this design?
|
||||
*/
|
||||
targs = list_copy(fn->args);
|
||||
foreach(args, targs)
|
||||
@@ -826,11 +824,11 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
|
||||
if (arg)
|
||||
{
|
||||
/*
|
||||
* If test expression is an untyped literal, force it to text.
|
||||
* We have to do something now because we won't be able to do
|
||||
* this coercion on the placeholder. This is not as flexible
|
||||
* as what was done in 7.4 and before, but it's good enough to
|
||||
* handle the sort of silly coding commonly seen.
|
||||
* If test expression is an untyped literal, force it to text. We have
|
||||
* to do something now because we won't be able to do this coercion on
|
||||
* the placeholder. This is not as flexible as what was done in 7.4
|
||||
* and before, but it's good enough to handle the sort of silly coding
|
||||
* commonly seen.
|
||||
*/
|
||||
if (exprType(arg) == UNKNOWNOID)
|
||||
arg = coerce_to_common_type(pstate, arg, TEXTOID, "CASE");
|
||||
@@ -891,9 +889,8 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
|
||||
|
||||
/*
|
||||
* Note: default result is considered the most significant type in
|
||||
* determining preferred type. This is how the code worked before,
|
||||
* but it seems a little bogus to me
|
||||
* --- tgl
|
||||
* determining preferred type. This is how the code worked before, but it
|
||||
* seems a little bogus to me --- tgl
|
||||
*/
|
||||
typeids = lcons_oid(exprType((Node *) newc->defresult), typeids);
|
||||
|
||||
@@ -947,8 +944,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
if (sublink->subLinkType == EXISTS_SUBLINK)
|
||||
{
|
||||
/*
|
||||
* EXISTS needs no lefthand or combining operator. These
|
||||
* fields should be NIL already, but make sure.
|
||||
* EXISTS needs no lefthand or combining operator. These fields
|
||||
* should be NIL already, but make sure.
|
||||
*/
|
||||
sublink->lefthand = NIL;
|
||||
sublink->operName = NIL;
|
||||
@@ -961,8 +958,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
ListCell *tlist_item = list_head(qtree->targetList);
|
||||
|
||||
/*
|
||||
* Make sure the subselect delivers a single column (ignoring
|
||||
* resjunk targets).
|
||||
* Make sure the subselect delivers a single column (ignoring resjunk
|
||||
* targets).
|
||||
*/
|
||||
if (tlist_item == NULL ||
|
||||
((TargetEntry *) lfirst(tlist_item))->resjunk)
|
||||
@@ -978,9 +975,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
}
|
||||
|
||||
/*
|
||||
* EXPR and ARRAY need no lefthand or combining
|
||||
* operator. These fields should be NIL already, but make
|
||||
* sure.
|
||||
* EXPR and ARRAY need no lefthand or combining operator. These fields
|
||||
* should be NIL already, but make sure.
|
||||
*/
|
||||
sublink->lefthand = NIL;
|
||||
sublink->operName = NIL;
|
||||
@@ -1004,9 +1000,9 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
lfirst(l) = transformExpr(pstate, lfirst(l));
|
||||
|
||||
/*
|
||||
* If the expression is "<> ALL" (with unqualified opname)
|
||||
* then convert it to "NOT IN". This is a hack to improve
|
||||
* efficiency of expressions output by pre-7.4 Postgres.
|
||||
* If the expression is "<> ALL" (with unqualified opname) then
|
||||
* convert it to "NOT IN". This is a hack to improve efficiency of
|
||||
* expressions output by pre-7.4 Postgres.
|
||||
*/
|
||||
if (sublink->subLinkType == ALL_SUBLINK &&
|
||||
list_length(op) == 1 && strcmp(opname, "<>") == 0)
|
||||
@@ -1035,10 +1031,10 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
|
||||
/*
|
||||
* To build the list of combining operator OIDs, we must scan
|
||||
* subquery's targetlist to find values that will be matched
|
||||
* against lefthand values. We need to ignore resjunk
|
||||
* targets, so doing the outer iteration over right_list is
|
||||
* easier than doing it over left_list.
|
||||
* subquery's targetlist to find values that will be matched against
|
||||
* lefthand values. We need to ignore resjunk targets, so doing the
|
||||
* outer iteration over right_list is easier than doing it over
|
||||
* left_list.
|
||||
*/
|
||||
sublink->operOids = NIL;
|
||||
|
||||
@@ -1061,9 +1057,8 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
ll_item = lnext(ll_item);
|
||||
|
||||
/*
|
||||
* It's OK to use oper() not compatible_oper() here,
|
||||
* because make_subplan() will insert type coercion calls
|
||||
* if needed.
|
||||
* It's OK to use oper() not compatible_oper() here, because
|
||||
* make_subplan() will insert type coercion calls if needed.
|
||||
*/
|
||||
optup = oper(op,
|
||||
exprType(lexpr),
|
||||
@@ -1074,9 +1069,9 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
if (opform->oprresult != BOOLOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("operator %s must return type boolean, not type %s",
|
||||
opname,
|
||||
format_type_be(opform->oprresult)),
|
||||
errmsg("operator %s must return type boolean, not type %s",
|
||||
opname,
|
||||
format_type_be(opform->oprresult)),
|
||||
errhint("The operator of a quantified predicate subquery must return type boolean.")));
|
||||
|
||||
if (get_func_retset(opform->oprcode))
|
||||
@@ -1300,7 +1295,7 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
|
||||
default:
|
||||
elog(ERROR, "unrecognized booltesttype: %d",
|
||||
(int) b->booltesttype);
|
||||
clausename = NULL; /* keep compiler quiet */
|
||||
clausename = NULL; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
b->arg = (Expr *) transformExpr(pstate, (Node *) b->arg);
|
||||
@@ -1385,10 +1380,10 @@ transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname)
|
||||
default:
|
||||
|
||||
/*
|
||||
* RTE is a join or subselect. We represent this as a
|
||||
* whole-row Var of RECORD type. (Note that in most cases the
|
||||
* Var will be expanded to a RowExpr during planning, but that
|
||||
* is not our concern here.)
|
||||
* RTE is a join or subselect. We represent this as a whole-row
|
||||
* Var of RECORD type. (Note that in most cases the Var will be
|
||||
* expanded to a RowExpr during planning, but that is not our
|
||||
* concern here.)
|
||||
*/
|
||||
result = (Node *) makeVar(vnum,
|
||||
InvalidAttrNumber,
|
||||
@@ -1469,7 +1464,7 @@ exprType(Node *expr)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(exprType((Node *) tent->expr)))));
|
||||
format_type_be(exprType((Node *) tent->expr)))));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1482,10 +1477,9 @@ exprType(Node *expr)
|
||||
case T_SubPlan:
|
||||
{
|
||||
/*
|
||||
* Although the parser does not ever deal with
|
||||
* already-planned expression trees, we support SubPlan
|
||||
* nodes in this routine for the convenience of
|
||||
* ruleutils.c.
|
||||
* Although the parser does not ever deal with already-planned
|
||||
* expression trees, we support SubPlan nodes in this routine
|
||||
* for the convenience of ruleutils.c.
|
||||
*/
|
||||
SubPlan *subplan = (SubPlan *) expr;
|
||||
|
||||
@@ -1506,7 +1500,7 @@ exprType(Node *expr)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(exprType((Node *) tent->expr)))));
|
||||
format_type_be(exprType((Node *) tent->expr)))));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1600,7 +1594,7 @@ exprTypmod(Node *expr)
|
||||
case BPCHAROID:
|
||||
if (!con->constisnull)
|
||||
{
|
||||
int32 len = VARSIZE(DatumGetPointer(con->constvalue)) - VARHDRSZ;
|
||||
int32 len = VARSIZE(DatumGetPointer(con->constvalue)) - VARHDRSZ;
|
||||
|
||||
/* if multi-byte, take len and find # characters */
|
||||
if (pg_database_encoding_max_length() > 1)
|
||||
@@ -1629,8 +1623,8 @@ exprTypmod(Node *expr)
|
||||
case T_CaseExpr:
|
||||
{
|
||||
/*
|
||||
* If all the alternatives agree on type/typmod, return
|
||||
* that typmod, else use -1
|
||||
* If all the alternatives agree on type/typmod, return that
|
||||
* typmod, else use -1
|
||||
*/
|
||||
CaseExpr *cexpr = (CaseExpr *) expr;
|
||||
Oid casetype = cexpr->casetype;
|
||||
@@ -1662,8 +1656,8 @@ exprTypmod(Node *expr)
|
||||
case T_CoalesceExpr:
|
||||
{
|
||||
/*
|
||||
* If all the alternatives agree on type/typmod, return
|
||||
* that typmod, else use -1
|
||||
* If all the alternatives agree on type/typmod, return that
|
||||
* typmod, else use -1
|
||||
*/
|
||||
CoalesceExpr *cexpr = (CoalesceExpr *) expr;
|
||||
Oid coalescetype = cexpr->coalescetype;
|
||||
@@ -1686,8 +1680,8 @@ exprTypmod(Node *expr)
|
||||
case T_MinMaxExpr:
|
||||
{
|
||||
/*
|
||||
* If all the alternatives agree on type/typmod, return
|
||||
* that typmod, else use -1
|
||||
* If all the alternatives agree on type/typmod, return that
|
||||
* typmod, else use -1
|
||||
*/
|
||||
MinMaxExpr *mexpr = (MinMaxExpr *) expr;
|
||||
Oid minmaxtype = mexpr->minmaxtype;
|
||||
@@ -1760,9 +1754,9 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If it's not a two-argument or three-argument function with the
|
||||
* second argument being an int4 constant, it can't have been created
|
||||
* from a length coercion (it must be a type coercion, instead).
|
||||
* If it's not a two-argument or three-argument function with the second
|
||||
* argument being an int4 constant, it can't have been created from a
|
||||
* length coercion (it must be a type coercion, instead).
|
||||
*/
|
||||
nargs = list_length(func->args);
|
||||
if (nargs < 2 || nargs > 3)
|
||||
@@ -1844,9 +1838,9 @@ make_row_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree)
|
||||
errmsg("unequal number of entries in row expression")));
|
||||
|
||||
/*
|
||||
* XXX it's really wrong to generate a simple AND combination for < <=
|
||||
* > >=. We probably need to invent a new runtime node type to handle
|
||||
* those correctly. For the moment, though, keep on doing this ...
|
||||
* XXX it's really wrong to generate a simple AND combination for < <= >
|
||||
* >=. We probably need to invent a new runtime node type to handle those
|
||||
* correctly. For the moment, though, keep on doing this ...
|
||||
*/
|
||||
oprname = strVal(llast(opname));
|
||||
|
||||
@@ -1862,8 +1856,8 @@ make_row_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("operator %s is not supported for row expressions",
|
||||
oprname)));
|
||||
errmsg("operator %s is not supported for row expressions",
|
||||
oprname)));
|
||||
boolop = 0; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
@@ -1957,7 +1951,7 @@ make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree)
|
||||
if (((OpExpr *) result)->opresulttype != BOOLOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("IS DISTINCT FROM requires = operator to yield boolean")));
|
||||
errmsg("IS DISTINCT FROM requires = operator to yield boolean")));
|
||||
|
||||
/*
|
||||
* We rely on DistinctExpr and OpExpr being same struct
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.181 2005/06/22 15:19:43 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.182 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -74,10 +74,10 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
FuncDetailCode fdresult;
|
||||
|
||||
/*
|
||||
* Most of the rest of the parser just assumes that functions do not
|
||||
* have more than FUNC_MAX_ARGS parameters. We have to test here to
|
||||
* protect against array overruns, etc. Of course, this may not be a
|
||||
* function, but the test doesn't hurt.
|
||||
* Most of the rest of the parser just assumes that functions do not have
|
||||
* more than FUNC_MAX_ARGS parameters. We have to test here to protect
|
||||
* against array overruns, etc. Of course, this may not be a function,
|
||||
* but the test doesn't hurt.
|
||||
*/
|
||||
if (list_length(fargs) > FUNC_MAX_ARGS)
|
||||
ereport(ERROR,
|
||||
@@ -88,11 +88,11 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
/*
|
||||
* Extract arg type info in preparation for function lookup.
|
||||
*
|
||||
* If any arguments are Param markers of type VOID, we discard them
|
||||
* from the parameter list. This is a hack to allow the JDBC driver
|
||||
* to not have to distinguish "input" and "output" parameter symbols
|
||||
* while parsing function-call constructs. We can't use foreach()
|
||||
* because we may modify the list ...
|
||||
* If any arguments are Param markers of type VOID, we discard them from the
|
||||
* parameter list. This is a hack to allow the JDBC driver to not have to
|
||||
* distinguish "input" and "output" parameter symbols while parsing
|
||||
* function-call constructs. We can't use foreach() because we may modify
|
||||
* the list ...
|
||||
*/
|
||||
nargs = 0;
|
||||
for (l = list_head(fargs); l != NULL; l = nextl)
|
||||
@@ -102,7 +102,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
|
||||
nextl = lnext(l);
|
||||
|
||||
if (argtype == VOIDOID && IsA(arg, Param) && !is_column)
|
||||
if (argtype == VOIDOID && IsA(arg, Param) &&!is_column)
|
||||
{
|
||||
fargs = list_delete_ptr(fargs, arg);
|
||||
continue;
|
||||
@@ -119,9 +119,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
|
||||
/*
|
||||
* Check for column projection: if function has one argument, and that
|
||||
* argument is of complex type, and function name is not qualified,
|
||||
* then the "function call" could be a projection. We also check that
|
||||
* there wasn't any aggregate decoration.
|
||||
* argument is of complex type, and function name is not qualified, then
|
||||
* the "function call" could be a projection. We also check that there
|
||||
* wasn't any aggregate decoration.
|
||||
*/
|
||||
if (nargs == 1 && !agg_star && !agg_distinct && list_length(funcname) == 1)
|
||||
{
|
||||
@@ -136,8 +136,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* If ParseComplexProjection doesn't recognize it as a
|
||||
* projection, just press on.
|
||||
* If ParseComplexProjection doesn't recognize it as a projection,
|
||||
* just press on.
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -147,8 +147,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
* func_get_detail looks up the function in the catalogs, does
|
||||
* disambiguation for polymorphic functions, handles inheritance, and
|
||||
* returns the funcid and type and set or singleton status of the
|
||||
* function's return value. it also returns the true argument types
|
||||
* to the function.
|
||||
* function's return value. it also returns the true argument types to
|
||||
* the function.
|
||||
*/
|
||||
fdresult = func_get_detail(funcname, fargs, nargs, actual_arg_types,
|
||||
&funcid, &rettype, &retset,
|
||||
@@ -156,8 +156,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
if (fdresult == FUNCDETAIL_COERCION)
|
||||
{
|
||||
/*
|
||||
* We can do it as a trivial coercion. coerce_type can handle
|
||||
* these cases, so why duplicate code...
|
||||
* We can do it as a trivial coercion. coerce_type can handle these
|
||||
* cases, so why duplicate code...
|
||||
*/
|
||||
return coerce_type(pstate, linitial(fargs),
|
||||
actual_arg_types[0], rettype, -1,
|
||||
@@ -166,28 +166,28 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
else if (fdresult == FUNCDETAIL_NORMAL)
|
||||
{
|
||||
/*
|
||||
* Normal function found; was there anything indicating it must be
|
||||
* an aggregate?
|
||||
* Normal function found; was there anything indicating it must be an
|
||||
* aggregate?
|
||||
*/
|
||||
if (agg_star)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("%s(*) specified, but %s is not an aggregate function",
|
||||
NameListToString(funcname),
|
||||
NameListToString(funcname))));
|
||||
errmsg("%s(*) specified, but %s is not an aggregate function",
|
||||
NameListToString(funcname),
|
||||
NameListToString(funcname))));
|
||||
if (agg_distinct)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("DISTINCT specified, but %s is not an aggregate function",
|
||||
NameListToString(funcname))));
|
||||
errmsg("DISTINCT specified, but %s is not an aggregate function",
|
||||
NameListToString(funcname))));
|
||||
}
|
||||
else if (fdresult != FUNCDETAIL_AGGREGATE)
|
||||
{
|
||||
/*
|
||||
* Oops. Time to die.
|
||||
*
|
||||
* If we are dealing with the attribute notation rel.function, give
|
||||
* an error message that is appropriate for that case.
|
||||
* If we are dealing with the attribute notation rel.function, give an
|
||||
* error message that is appropriate for that case.
|
||||
*/
|
||||
if (is_column)
|
||||
{
|
||||
@@ -205,22 +205,22 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
errmsg("function %s is not unique",
|
||||
func_signature_string(funcname, nargs,
|
||||
actual_arg_types)),
|
||||
errhint("Could not choose a best candidate function. "
|
||||
"You may need to add explicit type casts.")));
|
||||
errhint("Could not choose a best candidate function. "
|
||||
"You may need to add explicit type casts.")));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("function %s does not exist",
|
||||
func_signature_string(funcname, nargs,
|
||||
actual_arg_types)),
|
||||
errhint("No function matches the given name and argument types. "
|
||||
"You may need to add explicit type casts.")));
|
||||
errhint("No function matches the given name and argument types. "
|
||||
"You may need to add explicit type casts.")));
|
||||
}
|
||||
|
||||
/*
|
||||
* enforce consistency with ANYARRAY and ANYELEMENT argument and
|
||||
* return types, possibly adjusting return type or declared_arg_types
|
||||
* (which will be used as the cast destination by make_fn_arguments)
|
||||
* enforce consistency with ANYARRAY and ANYELEMENT argument and return
|
||||
* types, possibly adjusting return type or declared_arg_types (which will
|
||||
* be used as the cast destination by make_fn_arguments)
|
||||
*/
|
||||
rettype = enforce_generic_type_consistency(actual_arg_types,
|
||||
declared_arg_types,
|
||||
@@ -394,15 +394,14 @@ func_select_candidate(int nargs,
|
||||
FUNC_MAX_ARGS)));
|
||||
|
||||
/*
|
||||
* If any input types are domains, reduce them to their base types.
|
||||
* This ensures that we will consider functions on the base type to be
|
||||
* "exact matches" in the exact-match heuristic; it also makes it
|
||||
* possible to do something useful with the type-category heuristics.
|
||||
* Note that this makes it difficult, but not impossible, to use
|
||||
* functions declared to take a domain as an input datatype. Such a
|
||||
* function will be selected over the base-type function only if it is
|
||||
* an exact match at all argument positions, and so was already chosen
|
||||
* by our caller.
|
||||
* If any input types are domains, reduce them to their base types. This
|
||||
* ensures that we will consider functions on the base type to be "exact
|
||||
* matches" in the exact-match heuristic; it also makes it possible to do
|
||||
* something useful with the type-category heuristics. Note that this
|
||||
* makes it difficult, but not impossible, to use functions declared to
|
||||
* take a domain as an input datatype. Such a function will be selected
|
||||
* over the base-type function only if it is an exact match at all
|
||||
* argument positions, and so was already chosen by our caller.
|
||||
*/
|
||||
for (i = 0; i < nargs; i++)
|
||||
input_base_typeids[i] = getBaseType(input_typeids[i]);
|
||||
@@ -452,12 +451,11 @@ func_select_candidate(int nargs,
|
||||
return candidates;
|
||||
|
||||
/*
|
||||
* Still too many candidates? Now look for candidates which have
|
||||
* either exact matches or preferred types at the args that will
|
||||
* require coercion. (Restriction added in 7.4: preferred type must be
|
||||
* of same category as input type; give no preference to
|
||||
* cross-category conversions to preferred types.) Keep all
|
||||
* candidates if none match.
|
||||
* Still too many candidates? Now look for candidates which have either
|
||||
* exact matches or preferred types at the args that will require
|
||||
* coercion. (Restriction added in 7.4: preferred type must be of same
|
||||
* category as input type; give no preference to cross-category
|
||||
* conversions to preferred types.) Keep all candidates if none match.
|
||||
*/
|
||||
for (i = 0; i < nargs; i++) /* avoid multiple lookups */
|
||||
slot_category[i] = TypeCategory(input_base_typeids[i]);
|
||||
@@ -502,30 +500,28 @@ func_select_candidate(int nargs,
|
||||
return candidates;
|
||||
|
||||
/*
|
||||
* Still too many candidates? Try assigning types for the unknown
|
||||
* columns.
|
||||
* Still too many candidates? Try assigning types for the unknown columns.
|
||||
*
|
||||
* NOTE: for a binary operator with one unknown and one non-unknown
|
||||
* input, we already tried the heuristic of looking for a candidate
|
||||
* with the known input type on both sides (see binary_oper_exact()).
|
||||
* That's essentially a special case of the general algorithm we try
|
||||
* next.
|
||||
* NOTE: for a binary operator with one unknown and one non-unknown input, we
|
||||
* already tried the heuristic of looking for a candidate with the known
|
||||
* input type on both sides (see binary_oper_exact()). That's essentially
|
||||
* a special case of the general algorithm we try next.
|
||||
*
|
||||
* We do this by examining each unknown argument position to see if we
|
||||
* can determine a "type category" for it. If any candidate has an
|
||||
* input datatype of STRING category, use STRING category (this bias
|
||||
* towards STRING is appropriate since unknown-type literals look like
|
||||
* strings). Otherwise, if all the candidates agree on the type
|
||||
* category of this argument position, use that category. Otherwise,
|
||||
* fail because we cannot determine a category.
|
||||
* We do this by examining each unknown argument position to see if we can
|
||||
* determine a "type category" for it. If any candidate has an input
|
||||
* datatype of STRING category, use STRING category (this bias towards
|
||||
* STRING is appropriate since unknown-type literals look like strings).
|
||||
* Otherwise, if all the candidates agree on the type category of this
|
||||
* argument position, use that category. Otherwise, fail because we
|
||||
* cannot determine a category.
|
||||
*
|
||||
* If we are able to determine a type category, also notice whether any
|
||||
* of the candidates takes a preferred datatype within the category.
|
||||
* If we are able to determine a type category, also notice whether any of
|
||||
* the candidates takes a preferred datatype within the category.
|
||||
*
|
||||
* Having completed this examination, remove candidates that accept the
|
||||
* wrong category at any unknown position. Also, if at least one
|
||||
* candidate accepted a preferred type at a position, remove
|
||||
* candidates that accept non-preferred types.
|
||||
* Having completed this examination, remove candidates that accept the wrong
|
||||
* category at any unknown position. Also, if at least one candidate
|
||||
* accepted a preferred type at a position, remove candidates that accept
|
||||
* non-preferred types.
|
||||
*
|
||||
* If we are down to one candidate at the end, we win.
|
||||
*/
|
||||
@@ -573,8 +569,7 @@ func_select_candidate(int nargs,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Remember conflict, but keep going (might find
|
||||
* STRING)
|
||||
* Remember conflict, but keep going (might find STRING)
|
||||
*/
|
||||
have_conflict = true;
|
||||
}
|
||||
@@ -687,8 +682,8 @@ func_get_detail(List *funcname,
|
||||
raw_candidates = FuncnameGetCandidates(funcname, nargs);
|
||||
|
||||
/*
|
||||
* Quickly check if there is an exact match to the input datatypes
|
||||
* (there can be only one)
|
||||
* Quickly check if there is an exact match to the input datatypes (there
|
||||
* can be only one)
|
||||
*/
|
||||
for (best_candidate = raw_candidates;
|
||||
best_candidate != NULL;
|
||||
@@ -703,32 +698,30 @@ func_get_detail(List *funcname,
|
||||
/*
|
||||
* If we didn't find an exact match, next consider the possibility
|
||||
* that this is really a type-coercion request: a single-argument
|
||||
* function call where the function name is a type name. If so,
|
||||
* and if we can do the coercion trivially (no run-time function
|
||||
* call needed), then go ahead and treat the "function call" as a
|
||||
* coercion. This interpretation needs to be given higher
|
||||
* priority than interpretations involving a type coercion
|
||||
* followed by a function call, otherwise we can produce
|
||||
* surprising results. For example, we want "text(varchar)" to be
|
||||
* interpreted as a trivial coercion, not as "text(name(varchar))"
|
||||
* which the code below this point is entirely capable of
|
||||
* selecting.
|
||||
* function call where the function name is a type name. If so, and
|
||||
* if we can do the coercion trivially (no run-time function call
|
||||
* needed), then go ahead and treat the "function call" as a coercion.
|
||||
* This interpretation needs to be given higher priority than
|
||||
* interpretations involving a type coercion followed by a function
|
||||
* call, otherwise we can produce surprising results. For example, we
|
||||
* want "text(varchar)" to be interpreted as a trivial coercion, not
|
||||
* as "text(name(varchar))" which the code below this point is
|
||||
* entirely capable of selecting.
|
||||
*
|
||||
* "Trivial" coercions are ones that involve binary-compatible types
|
||||
* and ones that are coercing a previously-unknown-type literal
|
||||
* constant to a specific type.
|
||||
* "Trivial" coercions are ones that involve binary-compatible types and
|
||||
* ones that are coercing a previously-unknown-type literal constant
|
||||
* to a specific type.
|
||||
*
|
||||
* The reason we can restrict our check to binary-compatible
|
||||
* coercions here is that we expect non-binary-compatible
|
||||
* coercions to have an implementation function named after the
|
||||
* target type. That function will be found by normal lookup if
|
||||
* appropriate.
|
||||
* The reason we can restrict our check to binary-compatible coercions
|
||||
* here is that we expect non-binary-compatible coercions to have an
|
||||
* implementation function named after the target type. That function
|
||||
* will be found by normal lookup if appropriate.
|
||||
*
|
||||
* NB: it's important that this code stays in sync with what
|
||||
* coerce_type can do, because the caller will try to apply
|
||||
* coerce_type if we return FUNCDETAIL_COERCION. If we return
|
||||
* that result for something coerce_type can't handle, we'll cause
|
||||
* infinite recursion between this module and coerce_type!
|
||||
* NB: it's important that this code stays in sync with what coerce_type
|
||||
* can do, because the caller will try to apply coerce_type if we
|
||||
* return FUNCDETAIL_COERCION. If we return that result for something
|
||||
* coerce_type can't handle, we'll cause infinite recursion between
|
||||
* this module and coerce_type!
|
||||
*/
|
||||
if (nargs == 1 && fargs != NIL)
|
||||
{
|
||||
@@ -761,8 +754,7 @@ func_get_detail(List *funcname,
|
||||
}
|
||||
|
||||
/*
|
||||
* didn't find an exact match, so now try to match up
|
||||
* candidates...
|
||||
* didn't find an exact match, so now try to match up candidates...
|
||||
*/
|
||||
if (raw_candidates != NULL)
|
||||
{
|
||||
@@ -788,8 +780,8 @@ func_get_detail(List *funcname,
|
||||
current_candidates);
|
||||
|
||||
/*
|
||||
* If we were able to choose a best candidate, we're
|
||||
* done. Otherwise, ambiguous function call.
|
||||
* If we were able to choose a best candidate, we're done.
|
||||
* Otherwise, ambiguous function call.
|
||||
*/
|
||||
if (!best_candidate)
|
||||
return FUNCDETAIL_MULTIPLE;
|
||||
@@ -853,11 +845,10 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
|
||||
inhrel = heap_open(InheritsRelationId, AccessShareLock);
|
||||
|
||||
/*
|
||||
* Use queue to do a breadth-first traversal of the inheritance graph
|
||||
* from the relid supplied up to the root. Notice that we append to
|
||||
* the queue inside the loop --- this is okay because the foreach()
|
||||
* macro doesn't advance queue_item until the next loop iteration
|
||||
* begins.
|
||||
* Use queue to do a breadth-first traversal of the inheritance graph from
|
||||
* the relid supplied up to the root. Notice that we append to the queue
|
||||
* inside the loop --- this is okay because the foreach() macro doesn't
|
||||
* advance queue_item until the next loop iteration begins.
|
||||
*/
|
||||
foreach(queue_item, queue)
|
||||
{
|
||||
@@ -872,9 +863,9 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
|
||||
|
||||
/*
|
||||
* Okay, this is a not-yet-seen relid. Add it to the list of
|
||||
* already-visited OIDs, then find all the types this relid
|
||||
* inherits from and add them to the queue. The one exception is
|
||||
* we don't add the original relation to 'visited'.
|
||||
* already-visited OIDs, then find all the types this relid inherits
|
||||
* from and add them to the queue. The one exception is we don't add
|
||||
* the original relation to 'visited'.
|
||||
*/
|
||||
if (queue_item != list_head(queue))
|
||||
visited = lappend_oid(visited, this_relid);
|
||||
@@ -889,7 +880,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
|
||||
while ((inhtup = heap_getnext(inhscan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inhtup);
|
||||
Oid inhparent = inh->inhparent;
|
||||
Oid inhparent = inh->inhparent;
|
||||
|
||||
/* If this is the target superclass, we're done */
|
||||
if (get_rel_type_id(inhparent) == superclassTypeId)
|
||||
@@ -968,14 +959,14 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg)
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Special case for whole-row Vars so that we can resolve (foo.*).bar
|
||||
* even when foo is a reference to a subselect, join, or RECORD
|
||||
* function. A bonus is that we avoid generating an unnecessary
|
||||
* FieldSelect; our result can omit the whole-row Var and just be a
|
||||
* Var for the selected field.
|
||||
* Special case for whole-row Vars so that we can resolve (foo.*).bar even
|
||||
* when foo is a reference to a subselect, join, or RECORD function. A
|
||||
* bonus is that we avoid generating an unnecessary FieldSelect; our
|
||||
* result can omit the whole-row Var and just be a Var for the selected
|
||||
* field.
|
||||
*
|
||||
* This case could be handled by expandRecordVariable, but it's
|
||||
* more efficient to do it this way when possible.
|
||||
* This case could be handled by expandRecordVariable, but it's more
|
||||
* efficient to do it this way when possible.
|
||||
*/
|
||||
if (IsA(first_arg, Var) &&
|
||||
((Var *) first_arg)->varattno == InvalidAttrNumber)
|
||||
@@ -992,9 +983,9 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg)
|
||||
/*
|
||||
* Else do it the hard way with get_expr_result_type().
|
||||
*
|
||||
* If it's a Var of type RECORD, we have to work even harder: we have
|
||||
* to find what the Var refers to, and pass that to get_expr_result_type.
|
||||
* That task is handled by expandRecordVariable().
|
||||
* If it's a Var of type RECORD, we have to work even harder: we have to find
|
||||
* what the Var refers to, and pass that to get_expr_result_type. That
|
||||
* task is handled by expandRecordVariable().
|
||||
*/
|
||||
if (IsA(first_arg, Var) &&
|
||||
((Var *) first_arg)->vartype == RECORDOID)
|
||||
@@ -1057,8 +1048,8 @@ unknown_attribute(ParseState *pstate, Node *relref, char *attname)
|
||||
else if (relTypeId == RECORDOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("could not identify column \"%s\" in record data type",
|
||||
attname)));
|
||||
errmsg("could not identify column \"%s\" in record data type",
|
||||
attname)));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
@@ -1161,7 +1152,7 @@ find_aggregate_func(List *aggname, Oid basetype, bool noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("function %s(%s) is not an aggregate",
|
||||
NameListToString(aggname), format_type_be(basetype))));
|
||||
NameListToString(aggname), format_type_be(basetype))));
|
||||
}
|
||||
|
||||
ReleaseSysCache(ftup);
|
||||
@@ -1198,7 +1189,7 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("function %s does not exist",
|
||||
func_signature_string(funcname, nargs, argtypes))));
|
||||
func_signature_string(funcname, nargs, argtypes))));
|
||||
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.89 2005/05/30 01:20:49 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.90 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -92,8 +92,8 @@ transformArrayType(Oid arrayType)
|
||||
if (elementType == InvalidOid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("cannot subscript type %s because it is not an array",
|
||||
format_type_be(arrayType))));
|
||||
errmsg("cannot subscript type %s because it is not an array",
|
||||
format_type_be(arrayType))));
|
||||
|
||||
ReleaseSysCache(type_tuple_array);
|
||||
|
||||
@@ -145,11 +145,11 @@ transformArraySubscripts(ParseState *pstate,
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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)
|
||||
{
|
||||
@@ -163,9 +163,9 @@ transformArraySubscripts(ParseState *pstate,
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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;
|
||||
@@ -188,14 +188,14 @@ transformArraySubscripts(ParseState *pstate,
|
||||
subexpr = transformExpr(pstate, ai->lidx);
|
||||
/* If it's not int4 already, try to coerce */
|
||||
subexpr = coerce_to_target_type(pstate,
|
||||
subexpr, exprType(subexpr),
|
||||
subexpr, exprType(subexpr),
|
||||
INT4OID, -1,
|
||||
COERCION_ASSIGNMENT,
|
||||
COERCE_IMPLICIT_CAST);
|
||||
if (subexpr == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("array subscript must have type integer")));
|
||||
errmsg("array subscript must have type integer")));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -224,8 +224,7 @@ transformArraySubscripts(ParseState *pstate,
|
||||
|
||||
/*
|
||||
* If doing an array store, coerce the source value to the right type.
|
||||
* (This should agree with the coercion done by
|
||||
* updateTargetListEntry.)
|
||||
* (This should agree with the coercion done by updateTargetListEntry.)
|
||||
*/
|
||||
if (assignFrom != NULL)
|
||||
{
|
||||
@@ -244,7 +243,7 @@ transformArraySubscripts(ParseState *pstate,
|
||||
" but expression is of type %s",
|
||||
format_type_be(typeneeded),
|
||||
format_type_be(typesource)),
|
||||
errhint("You will need to rewrite or cast the expression.")));
|
||||
errhint("You will need to rewrite or cast the expression.")));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -308,7 +307,7 @@ make_const(Value *value)
|
||||
* 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;
|
||||
int32 val32 = (int32) val64;
|
||||
|
||||
if (val64 == (int64) val32)
|
||||
{
|
||||
@@ -324,7 +323,7 @@ make_const(Value *value)
|
||||
|
||||
typeid = INT8OID;
|
||||
typelen = sizeof(int64);
|
||||
typebyval = false; /* XXX might change someday */
|
||||
typebyval = false; /* XXX might change someday */
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -341,6 +340,7 @@ make_const(Value *value)
|
||||
break;
|
||||
|
||||
case T_String:
|
||||
|
||||
/*
|
||||
* We assume here that UNKNOWN's internal representation is the
|
||||
* same as CSTRING
|
||||
@@ -348,7 +348,7 @@ make_const(Value *value)
|
||||
val = CStringGetDatum(strVal(value));
|
||||
|
||||
typeid = UNKNOWNOID; /* will be coerced later */
|
||||
typelen = -2; /* cstring-style varwidth type */
|
||||
typelen = -2; /* cstring-style varwidth type */
|
||||
typebyval = false;
|
||||
break;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.81 2004/12/31 22:00:27 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.82 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -142,16 +142,16 @@ equality_oper(Oid argtype, bool noError)
|
||||
|
||||
/*
|
||||
* Look for an "=" operator for the datatype. We require it to be an
|
||||
* exact or binary-compatible match, since most callers are not
|
||||
* prepared to cope with adding any run-time type coercion steps.
|
||||
* exact or binary-compatible match, since most callers are not prepared
|
||||
* to cope with adding any run-time type coercion steps.
|
||||
*/
|
||||
typentry = lookup_type_cache(argtype, TYPECACHE_EQ_OPR);
|
||||
oproid = typentry->eq_opr;
|
||||
|
||||
/*
|
||||
* If the datatype is an array, then we can use array_eq ... but only
|
||||
* if there is a suitable equality operator for the element type.
|
||||
* (This check is not in the raw typcache.c code ... should it be?)
|
||||
* If the datatype is an array, then we can use array_eq ... but only if
|
||||
* there is a suitable equality operator for the element type. (This check
|
||||
* is not in the raw typcache.c code ... should it be?)
|
||||
*/
|
||||
if (oproid == ARRAY_EQ_OP)
|
||||
{
|
||||
@@ -182,8 +182,8 @@ equality_oper(Oid argtype, bool noError)
|
||||
if (!noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify an equality operator for type %s",
|
||||
format_type_be(argtype))));
|
||||
errmsg("could not identify an equality operator for type %s",
|
||||
format_type_be(argtype))));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -200,22 +200,22 @@ ordering_oper(Oid argtype, bool noError)
|
||||
Operator optup;
|
||||
|
||||
/*
|
||||
* Look for a "<" operator for the datatype. We require it to be an
|
||||
* exact or binary-compatible match, since most callers are not
|
||||
* prepared to cope with adding any run-time type coercion steps.
|
||||
* Look for a "<" operator for the datatype. We require it to be an exact
|
||||
* or binary-compatible match, since most callers are not prepared to cope
|
||||
* with adding any run-time type coercion steps.
|
||||
*
|
||||
* Note: the search algorithm used by typcache.c ensures that if a "<"
|
||||
* operator is returned, it will be consistent with the "=" operator
|
||||
* returned by equality_oper. This is critical for sorting and
|
||||
* grouping purposes.
|
||||
* returned by equality_oper. This is critical for sorting and grouping
|
||||
* purposes.
|
||||
*/
|
||||
typentry = lookup_type_cache(argtype, TYPECACHE_LT_OPR);
|
||||
oproid = typentry->lt_opr;
|
||||
|
||||
/*
|
||||
* If the datatype is an array, then we can use array_lt ... but only
|
||||
* if there is a suitable less-than operator for the element type.
|
||||
* (This check is not in the raw typcache.c code ... should it be?)
|
||||
* If the datatype is an array, then we can use array_lt ... but only if
|
||||
* there is a suitable less-than operator for the element type. (This
|
||||
* check is not in the raw typcache.c code ... should it be?)
|
||||
*/
|
||||
if (oproid == ARRAY_LT_OP)
|
||||
{
|
||||
@@ -246,9 +246,9 @@ ordering_oper(Oid argtype, bool noError)
|
||||
if (!noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify an ordering operator for type %s",
|
||||
format_type_be(argtype)),
|
||||
errhint("Use an explicit ordering operator or modify the query.")));
|
||||
errmsg("could not identify an ordering operator for type %s",
|
||||
format_type_be(argtype)),
|
||||
errhint("Use an explicit ordering operator or modify the query.")));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -265,22 +265,22 @@ reverse_ordering_oper(Oid argtype, bool noError)
|
||||
Operator optup;
|
||||
|
||||
/*
|
||||
* Look for a ">" operator for the datatype. We require it to be an
|
||||
* exact or binary-compatible match, since most callers are not
|
||||
* prepared to cope with adding any run-time type coercion steps.
|
||||
* Look for a ">" operator for the datatype. We require it to be an exact
|
||||
* or binary-compatible match, since most callers are not prepared to cope
|
||||
* with adding any run-time type coercion steps.
|
||||
*
|
||||
* Note: the search algorithm used by typcache.c ensures that if a ">"
|
||||
* operator is returned, it will be consistent with the "=" operator
|
||||
* returned by equality_oper. This is critical for sorting and
|
||||
* grouping purposes.
|
||||
* returned by equality_oper. This is critical for sorting and grouping
|
||||
* purposes.
|
||||
*/
|
||||
typentry = lookup_type_cache(argtype, TYPECACHE_GT_OPR);
|
||||
oproid = typentry->gt_opr;
|
||||
|
||||
/*
|
||||
* If the datatype is an array, then we can use array_gt ... but only
|
||||
* if there is a suitable greater-than operator for the element type.
|
||||
* (This check is not in the raw typcache.c code ... should it be?)
|
||||
* If the datatype is an array, then we can use array_gt ... but only if
|
||||
* there is a suitable greater-than operator for the element type. (This
|
||||
* check is not in the raw typcache.c code ... should it be?)
|
||||
*/
|
||||
if (oproid == ARRAY_GT_OP)
|
||||
{
|
||||
@@ -311,9 +311,9 @@ reverse_ordering_oper(Oid argtype, bool noError)
|
||||
if (!noError)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify an ordering operator for type %s",
|
||||
format_type_be(argtype)),
|
||||
errhint("Use an explicit ordering operator or modify the query.")));
|
||||
errmsg("could not identify an ordering operator for type %s",
|
||||
format_type_be(argtype)),
|
||||
errhint("Use an explicit ordering operator or modify the query.")));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -528,8 +528,8 @@ oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Unspecified type for one of the arguments? then use the
|
||||
* other (XXX this is probably dead code?)
|
||||
* Unspecified type for one of the arguments? then use the other
|
||||
* (XXX this is probably dead code?)
|
||||
*/
|
||||
if (rtypeId == InvalidOid)
|
||||
rtypeId = ltypeId;
|
||||
@@ -654,9 +654,8 @@ right_oper(List *op, Oid arg, bool noError)
|
||||
if (!OidIsValid(operOid))
|
||||
{
|
||||
/*
|
||||
* We must run oper_select_candidate even if only one
|
||||
* candidate, otherwise we may falsely return a
|
||||
* non-type-compatible operator.
|
||||
* We must run oper_select_candidate even if only one candidate,
|
||||
* otherwise we may falsely return a non-type-compatible operator.
|
||||
*/
|
||||
fdresult = oper_select_candidate(1, &arg, clist, &operOid);
|
||||
}
|
||||
@@ -703,9 +702,9 @@ left_oper(List *op, Oid arg, bool noError)
|
||||
* First, quickly check to see if there is an exactly matching
|
||||
* operator (there can be only one such entry in the list).
|
||||
*
|
||||
* The returned list has args in the form (0, oprright). Move the
|
||||
* useful data into args[0] to keep oper_select_candidate simple.
|
||||
* XXX we are assuming here that we may scribble on the list!
|
||||
* The returned list has args in the form (0, oprright). Move the useful
|
||||
* data into args[0] to keep oper_select_candidate simple. XXX we are
|
||||
* assuming here that we may scribble on the list!
|
||||
*/
|
||||
FuncCandidateList clisti;
|
||||
|
||||
@@ -722,9 +721,8 @@ left_oper(List *op, Oid arg, bool noError)
|
||||
if (!OidIsValid(operOid))
|
||||
{
|
||||
/*
|
||||
* We must run oper_select_candidate even if only one
|
||||
* candidate, otherwise we may falsely return a
|
||||
* non-type-compatible operator.
|
||||
* We must run oper_select_candidate even if only one candidate,
|
||||
* otherwise we may falsely return a non-type-compatible operator.
|
||||
*/
|
||||
fdresult = oper_select_candidate(1, &arg, clist, &operOid);
|
||||
}
|
||||
@@ -784,8 +782,8 @@ op_error(List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult)
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("operator does not exist: %s",
|
||||
op_signature_string(op, oprkind, arg1, arg2)),
|
||||
errhint("No operator matches the given name and argument type(s). "
|
||||
"You may need to add explicit type casts.")));
|
||||
errhint("No operator matches the given name and argument type(s). "
|
||||
"You may need to add explicit type casts.")));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -862,9 +860,9 @@ make_scalar_array_op(ParseState *pstate, List *opname,
|
||||
atypeId = exprType(rtree);
|
||||
|
||||
/*
|
||||
* The right-hand input of the operator will be the element type of
|
||||
* the array. However, if we currently have just an untyped literal
|
||||
* on the right, stay with that and hope we can resolve the operator.
|
||||
* The right-hand input of the operator will be the element type of the
|
||||
* array. However, if we currently have just an untyped literal on the
|
||||
* right, stay with that and hope we can resolve the operator.
|
||||
*/
|
||||
if (atypeId == UNKNOWNOID)
|
||||
rtypeId = UNKNOWNOID;
|
||||
@@ -874,7 +872,7 @@ make_scalar_array_op(ParseState *pstate, List *opname,
|
||||
if (!OidIsValid(rtypeId))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("op ANY/ALL (array) requires array on right side")));
|
||||
errmsg("op ANY/ALL (array) requires array on right side")));
|
||||
}
|
||||
|
||||
/* Now resolve the operator */
|
||||
@@ -888,9 +886,9 @@ make_scalar_array_op(ParseState *pstate, List *opname,
|
||||
declared_arg_types[1] = opform->oprright;
|
||||
|
||||
/*
|
||||
* enforce consistency with ANYARRAY and ANYELEMENT argument and
|
||||
* return types, possibly adjusting return type or declared_arg_types
|
||||
* (which will be used as the cast destination by make_fn_arguments)
|
||||
* enforce consistency with ANYARRAY and ANYELEMENT argument and return
|
||||
* types, possibly adjusting return type or declared_arg_types (which will
|
||||
* be used as the cast destination by make_fn_arguments)
|
||||
*/
|
||||
rettype = enforce_generic_type_consistency(actual_arg_types,
|
||||
declared_arg_types,
|
||||
@@ -903,11 +901,11 @@ make_scalar_array_op(ParseState *pstate, List *opname,
|
||||
if (rettype != BOOLOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("op ANY/ALL (array) requires operator to yield boolean")));
|
||||
errmsg("op ANY/ALL (array) requires operator to yield boolean")));
|
||||
if (get_func_retset(opform->oprcode))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("op ANY/ALL (array) requires operator not to return a set")));
|
||||
errmsg("op ANY/ALL (array) requires operator not to return a set")));
|
||||
|
||||
/*
|
||||
* Now switch back to the array type on the right, arranging for any
|
||||
@@ -985,9 +983,9 @@ make_op_expr(ParseState *pstate, Operator op,
|
||||
}
|
||||
|
||||
/*
|
||||
* enforce consistency with ANYARRAY and ANYELEMENT argument and
|
||||
* return types, possibly adjusting return type or declared_arg_types
|
||||
* (which will be used as the cast destination by make_fn_arguments)
|
||||
* enforce consistency with ANYARRAY and ANYELEMENT argument and return
|
||||
* types, possibly adjusting return type or declared_arg_types (which will
|
||||
* be used as the cast destination by make_fn_arguments)
|
||||
*/
|
||||
rettype = enforce_generic_type_consistency(actual_arg_types,
|
||||
declared_arg_types,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.114 2005/10/06 19:51:13 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.115 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -35,7 +35,7 @@
|
||||
bool add_missing_from;
|
||||
|
||||
static RangeTblEntry *scanNameSpaceForRefname(ParseState *pstate,
|
||||
const char *refname);
|
||||
const char *refname);
|
||||
static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid);
|
||||
static bool isLockedRel(ParseState *pstate, char *refname);
|
||||
static void expandRelation(Oid relid, Alias *eref,
|
||||
@@ -43,9 +43,9 @@ static void expandRelation(Oid relid, Alias *eref,
|
||||
bool include_dropped,
|
||||
List **colnames, List **colvars);
|
||||
static void expandTupleDesc(TupleDesc tupdesc, Alias *eref,
|
||||
int rtindex, int sublevels_up,
|
||||
bool include_dropped,
|
||||
List **colnames, List **colvars);
|
||||
int rtindex, int sublevels_up,
|
||||
bool include_dropped,
|
||||
List **colnames, List **colvars);
|
||||
static int specialAttNum(const char *attname);
|
||||
static void warnAutoRange(ParseState *pstate, RangeVar *relation);
|
||||
|
||||
@@ -297,15 +297,14 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
|
||||
* Scan the user column names (or aliases) for a match. Complain if
|
||||
* multiple matches.
|
||||
*
|
||||
* Note: eref->colnames may include entries for dropped columns, but
|
||||
* those will be empty strings that cannot match any legal SQL
|
||||
* identifier, so we don't bother to test for that case here.
|
||||
* Note: eref->colnames may include entries for dropped columns, but those
|
||||
* will be empty strings that cannot match any legal SQL identifier, so we
|
||||
* don't bother to test for that case here.
|
||||
*
|
||||
* Should this somehow go wrong and we try to access a dropped column,
|
||||
* we'll still catch it by virtue of the checks in
|
||||
* get_rte_attribute_type(), which is called by make_var(). That
|
||||
* routine has to do a cache lookup anyway, so the check there is
|
||||
* cheap.
|
||||
* Should this somehow go wrong and we try to access a dropped column, we'll
|
||||
* still catch it by virtue of the checks in get_rte_attribute_type(),
|
||||
* which is called by make_var(). That routine has to do a cache lookup
|
||||
* anyway, so the check there is cheap.
|
||||
*/
|
||||
foreach(c, rte->eref->colnames)
|
||||
{
|
||||
@@ -385,8 +384,8 @@ colNameToVar(ParseState *pstate, char *colname, bool localonly)
|
||||
if (result)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_AMBIGUOUS_COLUMN),
|
||||
errmsg("column reference \"%s\" is ambiguous",
|
||||
colname)));
|
||||
errmsg("column reference \"%s\" is ambiguous",
|
||||
colname)));
|
||||
result = newresult;
|
||||
}
|
||||
}
|
||||
@@ -502,7 +501,7 @@ buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("table \"%s\" has %d columns available but %d columns specified",
|
||||
eref->aliasname, maxattrs - numdropped, numaliases)));
|
||||
eref->aliasname, maxattrs - numdropped, numaliases)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -531,8 +530,8 @@ buildScalarFunctionAlias(Node *funcexpr, char *funcname,
|
||||
if (list_length(alias->colnames) != 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("too many column aliases specified for function %s",
|
||||
funcname)));
|
||||
errmsg("too many column aliases specified for function %s",
|
||||
funcname)));
|
||||
eref->colnames = copyObject(alias->colnames);
|
||||
return;
|
||||
}
|
||||
@@ -583,26 +582,26 @@ addRangeTableEntry(ParseState *pstate,
|
||||
rte->alias = alias;
|
||||
|
||||
/*
|
||||
* Get the rel's OID. This access also ensures that we have an
|
||||
* up-to-date relcache entry for the rel. Since this is typically the
|
||||
* first access to a rel in a statement, be careful to get the right
|
||||
* access level depending on whether we're doing SELECT FOR UPDATE/SHARE.
|
||||
* Get the rel's OID. This access also ensures that we have an up-to-date
|
||||
* relcache entry for the rel. Since this is typically the first access
|
||||
* to a rel in a statement, be careful to get the right access level
|
||||
* depending on whether we're doing SELECT FOR UPDATE/SHARE.
|
||||
*/
|
||||
lockmode = isLockedRel(pstate, refname) ? RowShareLock : AccessShareLock;
|
||||
rel = heap_openrv(relation, lockmode);
|
||||
rte->relid = RelationGetRelid(rel);
|
||||
|
||||
/*
|
||||
* Build the list of effective column names using user-supplied
|
||||
* aliases and/or actual column names.
|
||||
* Build the list of effective column names using user-supplied aliases
|
||||
* and/or actual column names.
|
||||
*/
|
||||
rte->eref = makeAlias(refname, NIL);
|
||||
buildRelationAliases(rel->rd_att, alias, rte->eref);
|
||||
|
||||
/*
|
||||
* Drop the rel refcount, but keep the access lock till end of
|
||||
* transaction so that the table can't be deleted or have its schema
|
||||
* modified underneath us.
|
||||
* Drop the rel refcount, but keep the access lock till end of transaction
|
||||
* so that the table can't be deleted or have its schema modified
|
||||
* underneath us.
|
||||
*/
|
||||
heap_close(rel, NoLock);
|
||||
|
||||
@@ -623,8 +622,8 @@ addRangeTableEntry(ParseState *pstate,
|
||||
rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
|
||||
|
||||
/*
|
||||
* Add completed RTE to pstate's range table list, but not to join
|
||||
* list nor namespace --- caller must do that if appropriate.
|
||||
* Add completed RTE to pstate's range table list, but not to join list
|
||||
* nor namespace --- caller must do that if appropriate.
|
||||
*/
|
||||
if (pstate != NULL)
|
||||
pstate->p_rtable = lappend(pstate->p_rtable, rte);
|
||||
@@ -653,8 +652,8 @@ addRangeTableEntryForRelation(ParseState *pstate,
|
||||
rte->relid = RelationGetRelid(rel);
|
||||
|
||||
/*
|
||||
* Build the list of effective column names using user-supplied
|
||||
* aliases and/or actual column names.
|
||||
* Build the list of effective column names using user-supplied aliases
|
||||
* and/or actual column names.
|
||||
*/
|
||||
rte->eref = makeAlias(refname, NIL);
|
||||
buildRelationAliases(rel->rd_att, alias, rte->eref);
|
||||
@@ -676,8 +675,8 @@ addRangeTableEntryForRelation(ParseState *pstate,
|
||||
rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
|
||||
|
||||
/*
|
||||
* Add completed RTE to pstate's range table list, but not to join
|
||||
* list nor namespace --- caller must do that if appropriate.
|
||||
* Add completed RTE to pstate's range table list, but not to join list
|
||||
* nor namespace --- caller must do that if appropriate.
|
||||
*/
|
||||
if (pstate != NULL)
|
||||
pstate->p_rtable = lappend(pstate->p_rtable, rte);
|
||||
@@ -754,8 +753,8 @@ addRangeTableEntryForSubquery(ParseState *pstate,
|
||||
rte->checkAsUser = InvalidOid;
|
||||
|
||||
/*
|
||||
* Add completed RTE to pstate's range table list, but not to join
|
||||
* list nor namespace --- caller must do that if appropriate.
|
||||
* Add completed RTE to pstate's range table list, but not to join list
|
||||
* nor namespace --- caller must do that if appropriate.
|
||||
*/
|
||||
if (pstate != NULL)
|
||||
pstate->p_rtable = lappend(pstate->p_rtable, rte);
|
||||
@@ -801,8 +800,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
||||
&tupdesc);
|
||||
|
||||
/*
|
||||
* A coldeflist is required if the function returns RECORD and hasn't
|
||||
* got a predetermined record type, and is prohibited otherwise.
|
||||
* A coldeflist is required if the function returns RECORD and hasn't got
|
||||
* a predetermined record type, and is prohibited otherwise.
|
||||
*/
|
||||
if (coldeflist != NIL)
|
||||
{
|
||||
@@ -848,8 +847,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("function \"%s\" in FROM has unsupported return type %s",
|
||||
funcname, format_type_be(funcrettype))));
|
||||
errmsg("function \"%s\" in FROM has unsupported return type %s",
|
||||
funcname, format_type_be(funcrettype))));
|
||||
|
||||
/*----------
|
||||
* Flags:
|
||||
@@ -868,8 +867,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
||||
rte->checkAsUser = InvalidOid;
|
||||
|
||||
/*
|
||||
* Add completed RTE to pstate's range table list, but not to join
|
||||
* list nor namespace --- caller must do that if appropriate.
|
||||
* Add completed RTE to pstate's range table list, but not to join list
|
||||
* nor namespace --- caller must do that if appropriate.
|
||||
*/
|
||||
if (pstate != NULL)
|
||||
pstate->p_rtable = lappend(pstate->p_rtable, rte);
|
||||
@@ -907,7 +906,7 @@ addRangeTableEntryForJoin(ParseState *pstate,
|
||||
/* fill in any unspecified alias columns */
|
||||
if (numaliases < list_length(colnames))
|
||||
eref->colnames = list_concat(eref->colnames,
|
||||
list_copy_tail(colnames, numaliases));
|
||||
list_copy_tail(colnames, numaliases));
|
||||
|
||||
rte->eref = eref;
|
||||
|
||||
@@ -927,8 +926,8 @@ addRangeTableEntryForJoin(ParseState *pstate,
|
||||
rte->checkAsUser = InvalidOid;
|
||||
|
||||
/*
|
||||
* Add completed RTE to pstate's range table list, but not to join
|
||||
* list nor namespace --- caller must do that if appropriate.
|
||||
* Add completed RTE to pstate's range table list, but not to join list
|
||||
* nor namespace --- caller must do that if appropriate.
|
||||
*/
|
||||
if (pstate != NULL)
|
||||
pstate->p_rtable = lappend(pstate->p_rtable, rte);
|
||||
@@ -983,7 +982,7 @@ addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
|
||||
{
|
||||
if (addToJoinList)
|
||||
{
|
||||
int rtindex = RTERangeTablePosn(pstate, rte, NULL);
|
||||
int rtindex = RTERangeTablePosn(pstate, rte, NULL);
|
||||
RangeTblRef *rtr = makeNode(RangeTblRef);
|
||||
|
||||
rtr->rtindex = rtindex;
|
||||
@@ -1111,7 +1110,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
|
||||
/* Base data type, i.e. scalar */
|
||||
if (colnames)
|
||||
*colnames = lappend(*colnames,
|
||||
linitial(rte->eref->colnames));
|
||||
linitial(rte->eref->colnames));
|
||||
|
||||
if (colvars)
|
||||
{
|
||||
@@ -1184,11 +1183,11 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
|
||||
|
||||
/*
|
||||
* During ordinary parsing, there will never be any
|
||||
* deleted columns in the join; but we have to check
|
||||
* since this routine is also used by the rewriter,
|
||||
* and joins found in stored rules might have join
|
||||
* columns for since-deleted columns. This will be
|
||||
* signaled by a NULL Const in the alias-vars list.
|
||||
* deleted columns in the join; but we have to check since
|
||||
* this routine is also used by the rewriter, and joins
|
||||
* found in stored rules might have join columns for
|
||||
* since-deleted columns. This will be signaled by a NULL
|
||||
* Const in the alias-vars list.
|
||||
*/
|
||||
if (IsA(avar, Const))
|
||||
{
|
||||
@@ -1274,8 +1273,8 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref,
|
||||
if (colvars)
|
||||
{
|
||||
/*
|
||||
* can't use atttypid here, but it doesn't really
|
||||
* matter what type the Const claims to be.
|
||||
* can't use atttypid here, but it doesn't really matter
|
||||
* what type the Const claims to be.
|
||||
*/
|
||||
*colvars = lappend(*colvars, makeNullConst(INT4OID));
|
||||
}
|
||||
@@ -1342,8 +1341,7 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte,
|
||||
te_list = lappend(te_list, te);
|
||||
}
|
||||
|
||||
Assert(name == NULL && var == NULL); /* lists not the same
|
||||
* length? */
|
||||
Assert(name == NULL && var == NULL); /* lists not the same length? */
|
||||
|
||||
return te_list;
|
||||
}
|
||||
@@ -1382,8 +1380,7 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
|
||||
return get_relid_attribute_name(rte->relid, attnum);
|
||||
|
||||
/*
|
||||
* Otherwise use the column name from eref. There should always be
|
||||
* one.
|
||||
* Otherwise use the column name from eref. There should always be one.
|
||||
*/
|
||||
if (attnum > 0 && attnum <= list_length(rte->eref->colnames))
|
||||
return strVal(list_nth(rte->eref->colnames, attnum - 1));
|
||||
@@ -1420,15 +1417,15 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
|
||||
|
||||
/*
|
||||
* If dropped column, pretend it ain't there. See notes
|
||||
* in scanRTEForColumn.
|
||||
* If dropped column, pretend it ain't there. See notes in
|
||||
* scanRTEForColumn.
|
||||
*/
|
||||
if (att_tup->attisdropped)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||
NameStr(att_tup->attname),
|
||||
get_rel_name(rte->relid))));
|
||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||
NameStr(att_tup->attname),
|
||||
get_rel_name(rte->relid))));
|
||||
*vartype = att_tup->atttypid;
|
||||
*vartypmod = att_tup->atttypmod;
|
||||
ReleaseSysCache(tp);
|
||||
@@ -1468,15 +1465,15 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
if (attnum < 1 || attnum > tupdesc->natts)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column %d of relation \"%s\" does not exist",
|
||||
attnum,
|
||||
rte->eref->aliasname)));
|
||||
errmsg("column %d of relation \"%s\" does not exist",
|
||||
attnum,
|
||||
rte->eref->aliasname)));
|
||||
|
||||
att_tup = tupdesc->attrs[attnum - 1];
|
||||
|
||||
/*
|
||||
* If dropped column, pretend it ain't there. See
|
||||
* notes in scanRTEForColumn.
|
||||
* If dropped column, pretend it ain't there. See notes
|
||||
* in scanRTEForColumn.
|
||||
*/
|
||||
if (att_tup->attisdropped)
|
||||
ereport(ERROR,
|
||||
@@ -1510,8 +1507,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
case RTE_JOIN:
|
||||
{
|
||||
/*
|
||||
* Join RTE --- get type info from join RTE's alias
|
||||
* variable
|
||||
* Join RTE --- get type info from join RTE's alias variable
|
||||
*/
|
||||
Node *aliasvar;
|
||||
|
||||
@@ -1540,8 +1536,7 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
|
||||
case RTE_RELATION:
|
||||
{
|
||||
/*
|
||||
* Plain relation RTE --- get the attribute's catalog
|
||||
* entry
|
||||
* Plain relation RTE --- get the attribute's catalog entry
|
||||
*/
|
||||
HeapTuple tp;
|
||||
Form_pg_attribute att_tup;
|
||||
@@ -1565,12 +1560,11 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
|
||||
case RTE_JOIN:
|
||||
{
|
||||
/*
|
||||
* A join RTE would not have dropped columns when
|
||||
* constructed, but one in a stored rule might contain
|
||||
* columns that were dropped from the underlying tables,
|
||||
* if said columns are nowhere explicitly referenced in
|
||||
* the rule. This will be signaled to us by a NULL Const
|
||||
* in the joinaliasvars list.
|
||||
* A join RTE would not have dropped columns when constructed,
|
||||
* but one in a stored rule might contain columns that were
|
||||
* dropped from the underlying tables, if said columns are
|
||||
* nowhere explicitly referenced in the rule. This will be
|
||||
* signaled to us by a NULL Const in the joinaliasvars list.
|
||||
*/
|
||||
Var *aliasvar;
|
||||
|
||||
@@ -1766,8 +1760,8 @@ warnAutoRange(ParseState *pstate, RangeVar *relation)
|
||||
if (pstate->parentParseState != NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_TABLE),
|
||||
errmsg("missing FROM-clause entry in subquery for table \"%s\"",
|
||||
relation->relname)));
|
||||
errmsg("missing FROM-clause entry in subquery for table \"%s\"",
|
||||
relation->relname)));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_TABLE),
|
||||
@@ -1785,7 +1779,7 @@ warnAutoRange(ParseState *pstate, RangeVar *relation)
|
||||
else
|
||||
ereport(NOTICE,
|
||||
(errcode(ERRCODE_UNDEFINED_TABLE),
|
||||
errmsg("adding missing FROM-clause entry for table \"%s\"",
|
||||
relation->relname)));
|
||||
errmsg("adding missing FROM-clause entry for table \"%s\"",
|
||||
relation->relname)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.137 2005/06/26 22:05:40 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.138 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
|
||||
static void markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
|
||||
Var *var, int levelsup);
|
||||
Var *var, int levelsup);
|
||||
static Node *transformAssignmentIndirection(ParseState *pstate,
|
||||
Node *basenode,
|
||||
const char *targetName,
|
||||
@@ -73,8 +73,8 @@ transformTargetEntry(ParseState *pstate,
|
||||
if (colname == NULL && !resjunk)
|
||||
{
|
||||
/*
|
||||
* Generate a suitable column name for a column without any
|
||||
* explicit 'AS ColumnName' clause.
|
||||
* Generate a suitable column name for a column without any explicit
|
||||
* 'AS ColumnName' clause.
|
||||
*/
|
||||
colname = FigureColname(node);
|
||||
}
|
||||
@@ -105,8 +105,8 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
|
||||
/*
|
||||
* Check for "something.*". Depending on the complexity of the
|
||||
* "something", the star could appear as the last name in
|
||||
* ColumnRef, or as the last indirection item in A_Indirection.
|
||||
* "something", the star could appear as the last name in ColumnRef,
|
||||
* or as the last indirection item in A_Indirection.
|
||||
*/
|
||||
if (IsA(res->val, ColumnRef))
|
||||
{
|
||||
@@ -130,7 +130,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
{
|
||||
/* It is something.*, expand into multiple items */
|
||||
p_target = list_concat(p_target,
|
||||
ExpandIndirectionStar(pstate, ind));
|
||||
ExpandIndirectionStar(pstate, ind));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -271,11 +271,11 @@ updateTargetListEntry(ParseState *pstate,
|
||||
|
||||
/*
|
||||
* If the expression is a DEFAULT placeholder, insert the attribute's
|
||||
* type/typmod into it so that exprType will report the right things.
|
||||
* (We expect that the eventually substituted default expression will
|
||||
* in fact have this type and typmod.) Also, reject trying to update
|
||||
* a subfield or array element with DEFAULT, since there can't be any
|
||||
* default for portions of a column.
|
||||
* type/typmod into it so that exprType will report the right things. (We
|
||||
* expect that the eventually substituted default expression will in fact
|
||||
* have this type and typmod.) Also, reject trying to update a subfield
|
||||
* or array element with DEFAULT, since there can't be any default for
|
||||
* portions of a column.
|
||||
*/
|
||||
if (tle->expr && IsA(tle->expr, SetToDefault))
|
||||
{
|
||||
@@ -288,7 +288,7 @@ updateTargetListEntry(ParseState *pstate,
|
||||
if (IsA(linitial(indirection), A_Indices))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot set an array element to DEFAULT")));
|
||||
errmsg("cannot set an array element to DEFAULT")));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
@@ -301,9 +301,9 @@ updateTargetListEntry(ParseState *pstate,
|
||||
|
||||
/*
|
||||
* If there is indirection on the target column, prepare an array or
|
||||
* subfield assignment expression. This will generate a new column
|
||||
* value that the source value has been inserted into, which can then
|
||||
* be placed in the new tuple constructed by INSERT or UPDATE.
|
||||
* subfield assignment expression. This will generate a new column value
|
||||
* that the source value has been inserted into, which can then be placed
|
||||
* in the new tuple constructed by INSERT or UPDATE.
|
||||
*/
|
||||
if (indirection)
|
||||
{
|
||||
@@ -312,9 +312,9 @@ updateTargetListEntry(ParseState *pstate,
|
||||
if (pstate->p_is_insert)
|
||||
{
|
||||
/*
|
||||
* The command is INSERT INTO table (col.something) ... so
|
||||
* there is not really a source value to work with. Insert a
|
||||
* NULL constant as the source value.
|
||||
* The command is INSERT INTO table (col.something) ... so there
|
||||
* is not really a source value to work with. Insert a NULL
|
||||
* constant as the source value.
|
||||
*/
|
||||
colVar = (Node *) makeNullConst(attrtype);
|
||||
}
|
||||
@@ -358,15 +358,14 @@ updateTargetListEntry(ParseState *pstate,
|
||||
colname,
|
||||
format_type_be(attrtype),
|
||||
format_type_be(type_id)),
|
||||
errhint("You will need to rewrite or cast the expression.")));
|
||||
errhint("You will need to rewrite or cast the expression.")));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the resno to identify the target column --- the rewriter and
|
||||
* planner depend on this. We also set the resname to identify the
|
||||
* target column, but this is only for debugging purposes; it should
|
||||
* not be relied on. (In particular, it might be out of date in a
|
||||
* stored rule.)
|
||||
* planner depend on this. We also set the resname to identify the target
|
||||
* column, but this is only for debugging purposes; it should not be
|
||||
* relied on. (In particular, it might be out of date in a stored rule.)
|
||||
*/
|
||||
tle->resno = (AttrNumber) attrno;
|
||||
tle->resname = colname;
|
||||
@@ -424,8 +423,8 @@ transformAssignmentIndirection(ParseState *pstate,
|
||||
|
||||
/*
|
||||
* We have to split any field-selection operations apart from
|
||||
* subscripting. Adjacent A_Indices nodes have to be treated as a
|
||||
* single multidimensional subscript operation.
|
||||
* subscripting. Adjacent A_Indices nodes have to be treated as a single
|
||||
* multidimensional subscript operation.
|
||||
*/
|
||||
for_each_cell(i, indirection)
|
||||
{
|
||||
@@ -561,7 +560,7 @@ transformAssignmentIndirection(ParseState *pstate,
|
||||
targetName,
|
||||
format_type_be(targetTypeId),
|
||||
format_type_be(exprType(rhs))),
|
||||
errhint("You will need to rewrite or cast the expression.")));
|
||||
errhint("You will need to rewrite or cast the expression.")));
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
@@ -570,7 +569,7 @@ transformAssignmentIndirection(ParseState *pstate,
|
||||
targetName,
|
||||
format_type_be(targetTypeId),
|
||||
format_type_be(exprType(rhs))),
|
||||
errhint("You will need to rewrite or cast the expression.")));
|
||||
errhint("You will need to rewrite or cast the expression.")));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -631,8 +630,8 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
attrno = attnameAttNum(pstate->p_target_relation, name, false);
|
||||
|
||||
/*
|
||||
* Check for duplicates, but only of whole columns --- we
|
||||
* allow INSERT INTO foo (col.subcol1, col.subcol2)
|
||||
* Check for duplicates, but only of whole columns --- we allow
|
||||
* INSERT INTO foo (col.subcol1, col.subcol2)
|
||||
*/
|
||||
if (col->indirection == NIL)
|
||||
{
|
||||
@@ -641,8 +640,8 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
bms_is_member(attrno, partialcols))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_COLUMN),
|
||||
errmsg("column \"%s\" specified more than once",
|
||||
name)));
|
||||
errmsg("column \"%s\" specified more than once",
|
||||
name)));
|
||||
wholecols = bms_add_member(wholecols, attrno);
|
||||
}
|
||||
else
|
||||
@@ -651,8 +650,8 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
|
||||
if (bms_is_member(attrno, wholecols))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_COLUMN),
|
||||
errmsg("column \"%s\" specified more than once",
|
||||
name)));
|
||||
errmsg("column \"%s\" specified more than once",
|
||||
name)));
|
||||
partialcols = bms_add_member(partialcols, attrno);
|
||||
}
|
||||
|
||||
@@ -727,8 +726,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref)
|
||||
default:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("improper qualified name (too many dotted names): %s",
|
||||
NameListToString(fields))));
|
||||
errmsg("improper qualified name (too many dotted names): %s",
|
||||
NameListToString(fields))));
|
||||
schemaname = NULL; /* keep compiler quiet */
|
||||
relname = NULL;
|
||||
break;
|
||||
@@ -765,12 +764,12 @@ ExpandAllTables(ParseState *pstate)
|
||||
if (!pstate->p_varnamespace)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("SELECT * with no tables specified is not valid")));
|
||||
errmsg("SELECT * with no tables specified is not valid")));
|
||||
|
||||
foreach(l, pstate->p_varnamespace)
|
||||
{
|
||||
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
|
||||
int rtindex = RTERangeTablePosn(pstate, rte, NULL);
|
||||
int rtindex = RTERangeTablePosn(pstate, rte, NULL);
|
||||
|
||||
target = list_concat(target,
|
||||
expandRelAttrs(pstate, rte, rtindex, 0));
|
||||
@@ -804,14 +803,14 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
|
||||
|
||||
/*
|
||||
* Verify it's a composite type, and get the tupdesc. We use
|
||||
* get_expr_result_type() because that can handle references to
|
||||
* functions returning anonymous record types. If that fails,
|
||||
* use lookup_rowtype_tupdesc(), which will almost certainly fail
|
||||
* as well, but it will give an appropriate error message.
|
||||
* get_expr_result_type() because that can handle references to functions
|
||||
* returning anonymous record types. If that fails, use
|
||||
* lookup_rowtype_tupdesc(), which will almost certainly fail as well, but
|
||||
* it will give an appropriate error message.
|
||||
*
|
||||
* If it's a Var of type RECORD, we have to work even harder: we have
|
||||
* to find what the Var refers to, and pass that to get_expr_result_type.
|
||||
* That task is handled by expandRecordVariable().
|
||||
* If it's a Var of type RECORD, we have to work even harder: we have to find
|
||||
* what the Var refers to, and pass that to get_expr_result_type. That
|
||||
* task is handled by expandRecordVariable().
|
||||
*/
|
||||
if (IsA(expr, Var) &&
|
||||
((Var *) expr)->vartype == RECORDOID)
|
||||
@@ -832,9 +831,9 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we got a whole-row Var from the rowtype reference, we can
|
||||
* expand the fields as simple Vars. Otherwise we must generate
|
||||
* multiple copies of the rowtype reference and do FieldSelects.
|
||||
* If we got a whole-row Var from the rowtype reference, we can expand
|
||||
* the fields as simple Vars. Otherwise we must generate multiple
|
||||
* copies of the rowtype reference and do FieldSelects.
|
||||
*/
|
||||
if (IsA(expr, Var) &&
|
||||
((Var *) expr)->varattno == InvalidAttrNumber)
|
||||
@@ -874,7 +873,7 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
|
||||
* Get the tuple descriptor for a Var of type RECORD, if possible.
|
||||
*
|
||||
* Since no actual table or view column is allowed to have type RECORD, such
|
||||
* a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
|
||||
* a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
|
||||
* drill down to find the ultimate defining expression and attempt to infer
|
||||
* the tupdesc from it. We ereport if we can't determine the tupdesc.
|
||||
*
|
||||
@@ -934,6 +933,7 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
|
||||
{
|
||||
case RTE_RELATION:
|
||||
case RTE_SPECIAL:
|
||||
|
||||
/*
|
||||
* This case should not occur: a column of a table shouldn't have
|
||||
* type RECORD. Fall through and fail (most likely) at the
|
||||
@@ -954,7 +954,7 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
|
||||
{
|
||||
/*
|
||||
* Recurse into the sub-select to see what its Var refers
|
||||
* to. We have to build an additional level of ParseState
|
||||
* to. We have to build an additional level of ParseState
|
||||
* to keep in step with varlevelsup in the subselect.
|
||||
*/
|
||||
ParseState mypstate;
|
||||
@@ -978,18 +978,19 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
|
||||
/* else fall through to inspect the expression */
|
||||
break;
|
||||
case RTE_FUNCTION:
|
||||
|
||||
/*
|
||||
* We couldn't get here unless a function is declared with one
|
||||
* of its result columns as RECORD, which is not allowed.
|
||||
* We couldn't get here unless a function is declared with one of
|
||||
* its result columns as RECORD, which is not allowed.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have an expression we can't expand any more, so see if
|
||||
* get_expr_result_type() can do anything with it. If not, pass
|
||||
* to lookup_rowtype_tupdesc() which will probably fail, but will
|
||||
* give an appropriate error message while failing.
|
||||
* get_expr_result_type() can do anything with it. If not, pass to
|
||||
* lookup_rowtype_tupdesc() which will probably fail, but will give an
|
||||
* appropriate error message while failing.
|
||||
*/
|
||||
if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
|
||||
tupleDesc = lookup_rowtype_tupdesc(exprType(expr), exprTypmod(expr));
|
||||
@@ -1125,7 +1126,7 @@ FigureColnameInternal(Node *node, char **name)
|
||||
return 2;
|
||||
case T_MinMaxExpr:
|
||||
/* make greatest/least act like a regular function */
|
||||
switch (((MinMaxExpr*) node)->op)
|
||||
switch (((MinMaxExpr *) node)->op)
|
||||
{
|
||||
case IS_GREATEST:
|
||||
*name = "greatest";
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.76 2005/08/01 20:31:10 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.77 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -59,8 +59,8 @@ LookupTypeName(const TypeName *typename)
|
||||
case 1:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("improper %%TYPE reference (too few dotted names): %s",
|
||||
NameListToString(typename->names))));
|
||||
errmsg("improper %%TYPE reference (too few dotted names): %s",
|
||||
NameListToString(typename->names))));
|
||||
break;
|
||||
case 2:
|
||||
rel->relname = strVal(linitial(typename->names));
|
||||
@@ -91,8 +91,8 @@ LookupTypeName(const TypeName *typename)
|
||||
if (attnum == InvalidAttrNumber)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||
field, rel->relname)));
|
||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||
field, rel->relname)));
|
||||
restype = get_atttype(relid, attnum);
|
||||
|
||||
/* this construct should never have an array indicator */
|
||||
@@ -364,8 +364,8 @@ pts_error_callback(void *arg)
|
||||
|
||||
/*
|
||||
* Currently we just suppress any syntax error position report, rather
|
||||
* than transforming to an "internal query" error. It's unlikely that
|
||||
* a type name is complex enough to need positioning.
|
||||
* than transforming to an "internal query" error. It's unlikely that a
|
||||
* type name is complex enough to need positioning.
|
||||
*/
|
||||
errposition(0);
|
||||
}
|
||||
@@ -406,8 +406,8 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
|
||||
error_context_stack = ptserrcontext.previous;
|
||||
|
||||
/*
|
||||
* Make sure we got back exactly what we expected and no more;
|
||||
* paranoia is justified since the string might contain anything.
|
||||
* Make sure we got back exactly what we expected and no more; paranoia is
|
||||
* justified since the string might contain anything.
|
||||
*/
|
||||
if (list_length(raw_parsetree_list) != 1)
|
||||
goto fail;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/scansup.c,v 1.29 2004/12/31 22:00:27 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/scansup.c,v 1.30 2005/10/15 02:49:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -53,8 +53,8 @@ scanstr(const char *s)
|
||||
if (s[i] == '\'')
|
||||
{
|
||||
/*
|
||||
* Note: if scanner is working right, unescaped quotes can
|
||||
* only appear in pairs, so there should be another character.
|
||||
* Note: if scanner is working right, unescaped quotes can only
|
||||
* appear in pairs, so there should be another character.
|
||||
*/
|
||||
i++;
|
||||
newStr[j] = s[i];
|
||||
@@ -135,13 +135,13 @@ downcase_truncate_identifier(const char *ident, int len, bool warn)
|
||||
result = palloc(len + 1);
|
||||
|
||||
/*
|
||||
* SQL99 specifies Unicode-aware case normalization, which we don't
|
||||
* yet have the infrastructure for. Instead we use tolower() to
|
||||
* provide a locale-aware translation. However, there are some
|
||||
* locales where this is not right either (eg, Turkish may do strange
|
||||
* things with 'i' and 'I'). Our current compromise is to use
|
||||
* tolower() for characters with the high bit set, and use an
|
||||
* ASCII-only downcasing for 7-bit characters.
|
||||
* SQL99 specifies Unicode-aware case normalization, which we don't yet
|
||||
* have the infrastructure for. Instead we use tolower() to provide a
|
||||
* locale-aware translation. However, there are some locales where this
|
||||
* is not right either (eg, Turkish may do strange things with 'i' and
|
||||
* 'I'). Our current compromise is to use tolower() for characters with
|
||||
* the high bit set, and use an ASCII-only downcasing for 7-bit
|
||||
* characters.
|
||||
*/
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
@@ -179,8 +179,8 @@ truncate_identifier(char *ident, int len, bool warn)
|
||||
if (warn)
|
||||
ereport(NOTICE,
|
||||
(errcode(ERRCODE_NAME_TOO_LONG),
|
||||
errmsg("identifier \"%s\" will be truncated to \"%.*s\"",
|
||||
ident, len, ident)));
|
||||
errmsg("identifier \"%s\" will be truncated to \"%.*s\"",
|
||||
ident, len, ident)));
|
||||
ident[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user