mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Do honest transformation and preprocessing of LIMIT/OFFSET clauses,
instead of the former kluge whereby gram.y emitted already-transformed expressions. This is needed so that Params appearing in these clauses actually work correctly. I suppose some might claim that the side effect of 'SELECT ... LIMIT 2+2' working is a new feature, but I say this is a bug fix.
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.155 2003/06/16 02:03:37 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.156 2003/07/03 19:07:20 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -47,7 +47,8 @@
|
|||||||
#define EXPRKIND_QUAL 0
|
#define EXPRKIND_QUAL 0
|
||||||
#define EXPRKIND_TARGET 1
|
#define EXPRKIND_TARGET 1
|
||||||
#define EXPRKIND_RTFUNC 2
|
#define EXPRKIND_RTFUNC 2
|
||||||
#define EXPRKIND_ININFO 3
|
#define EXPRKIND_LIMIT 3
|
||||||
|
#define EXPRKIND_ININFO 4
|
||||||
|
|
||||||
|
|
||||||
static Node *preprocess_expression(Query *parse, Node *expr, int kind);
|
static Node *preprocess_expression(Query *parse, Node *expr, int kind);
|
||||||
@ -232,6 +233,11 @@ subquery_planner(Query *parse, double tuple_fraction)
|
|||||||
parse->havingQual = preprocess_expression(parse, parse->havingQual,
|
parse->havingQual = preprocess_expression(parse, parse->havingQual,
|
||||||
EXPRKIND_QUAL);
|
EXPRKIND_QUAL);
|
||||||
|
|
||||||
|
parse->limitOffset = preprocess_expression(parse, parse->limitOffset,
|
||||||
|
EXPRKIND_LIMIT);
|
||||||
|
parse->limitCount = preprocess_expression(parse, parse->limitCount,
|
||||||
|
EXPRKIND_LIMIT);
|
||||||
|
|
||||||
parse->in_info_list = (List *)
|
parse->in_info_list = (List *)
|
||||||
preprocess_expression(parse, (Node *) parse->in_info_list,
|
preprocess_expression(parse, (Node *) parse->in_info_list,
|
||||||
EXPRKIND_ININFO);
|
EXPRKIND_ININFO);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.145 2003/07/03 16:33:07 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.146 2003/07/03 19:07:25 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -2390,6 +2390,10 @@ query_tree_walker(Query *query,
|
|||||||
return true;
|
return true;
|
||||||
if (walker(query->havingQual, context))
|
if (walker(query->havingQual, context))
|
||||||
return true;
|
return true;
|
||||||
|
if (walker(query->limitOffset, context))
|
||||||
|
return true;
|
||||||
|
if (walker(query->limitCount, context))
|
||||||
|
return true;
|
||||||
if (walker(query->in_info_list, context))
|
if (walker(query->in_info_list, context))
|
||||||
return true;
|
return true;
|
||||||
foreach(rt, query->rtable)
|
foreach(rt, query->rtable)
|
||||||
@ -2863,6 +2867,8 @@ query_tree_mutator(Query *query,
|
|||||||
MUTATE(query->jointree, query->jointree, FromExpr *);
|
MUTATE(query->jointree, query->jointree, FromExpr *);
|
||||||
MUTATE(query->setOperations, query->setOperations, Node *);
|
MUTATE(query->setOperations, query->setOperations, Node *);
|
||||||
MUTATE(query->havingQual, query->havingQual, Node *);
|
MUTATE(query->havingQual, query->havingQual, Node *);
|
||||||
|
MUTATE(query->limitOffset, query->limitOffset, Node *);
|
||||||
|
MUTATE(query->limitCount, query->limitCount, Node *);
|
||||||
MUTATE(query->in_info_list, query->in_info_list, List *);
|
MUTATE(query->in_info_list, query->in_info_list, List *);
|
||||||
FastListInit(&newrt);
|
FastListInit(&newrt);
|
||||||
foreach(rt, query->rtable)
|
foreach(rt, query->rtable)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.277 2003/06/25 04:19:24 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.278 2003/07/03 19:07:30 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -459,7 +459,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
|
|||||||
qry->distinctClause = NIL;
|
qry->distinctClause = NIL;
|
||||||
|
|
||||||
/* fix where clause */
|
/* fix where clause */
|
||||||
qual = transformWhereClause(pstate, stmt->whereClause);
|
qual = transformWhereClause(pstate, stmt->whereClause, "WHERE");
|
||||||
|
|
||||||
/* done building the range table and jointree */
|
/* done building the range table and jointree */
|
||||||
qry->rtable = pstate->p_rtable;
|
qry->rtable = pstate->p_rtable;
|
||||||
@ -1588,7 +1588,8 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
|
|||||||
/* no to join list, yes to namespace */
|
/* no to join list, yes to namespace */
|
||||||
addRTEtoQuery(pstate, rte, false, true);
|
addRTEtoQuery(pstate, rte, false, true);
|
||||||
|
|
||||||
stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
|
stmt->whereClause = transformWhereClause(pstate, stmt->whereClause,
|
||||||
|
"WHERE");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* take care of any index expressions */
|
/* take care of any index expressions */
|
||||||
@ -1699,7 +1700,8 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* take care of the where clause */
|
/* take care of the where clause */
|
||||||
stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
|
stmt->whereClause = transformWhereClause(pstate, stmt->whereClause,
|
||||||
|
"WHERE");
|
||||||
|
|
||||||
if (length(pstate->p_rtable) != 2) /* naughty, naughty... */
|
if (length(pstate->p_rtable) != 2) /* naughty, naughty... */
|
||||||
elog(ERROR, "Rule WHERE condition may not contain references to other relations");
|
elog(ERROR, "Rule WHERE condition may not contain references to other relations");
|
||||||
@ -1891,13 +1893,14 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
|||||||
markTargetListOrigins(pstate, qry->targetList);
|
markTargetListOrigins(pstate, qry->targetList);
|
||||||
|
|
||||||
/* transform WHERE */
|
/* transform WHERE */
|
||||||
qual = transformWhereClause(pstate, stmt->whereClause);
|
qual = transformWhereClause(pstate, stmt->whereClause, "WHERE");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initial processing of HAVING clause is just like WHERE clause.
|
* Initial processing of HAVING clause is just like WHERE clause.
|
||||||
* Additional work will be done in optimizer/plan/planner.c.
|
* Additional work will be done in optimizer/plan/planner.c.
|
||||||
*/
|
*/
|
||||||
qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
|
qry->havingQual = transformWhereClause(pstate, stmt->havingClause,
|
||||||
|
"HAVING");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transform sorting/grouping stuff. Do ORDER BY first because both
|
* Transform sorting/grouping stuff. Do ORDER BY first because both
|
||||||
@ -1918,8 +1921,10 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
|||||||
qry->targetList,
|
qry->targetList,
|
||||||
&qry->sortClause);
|
&qry->sortClause);
|
||||||
|
|
||||||
qry->limitOffset = stmt->limitOffset;
|
qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
|
||||||
qry->limitCount = stmt->limitCount;
|
"OFFSET");
|
||||||
|
qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
|
||||||
|
"LIMIT");
|
||||||
|
|
||||||
qry->rtable = pstate->p_rtable;
|
qry->rtable = pstate->p_rtable;
|
||||||
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
|
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
|
||||||
@ -2124,8 +2129,10 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
|||||||
if (tllen != length(qry->targetList))
|
if (tllen != length(qry->targetList))
|
||||||
elog(ERROR, "ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns");
|
elog(ERROR, "ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns");
|
||||||
|
|
||||||
qry->limitOffset = limitOffset;
|
qry->limitOffset = transformLimitClause(pstate, limitOffset,
|
||||||
qry->limitCount = limitCount;
|
"OFFSET");
|
||||||
|
qry->limitCount = transformLimitClause(pstate, limitCount,
|
||||||
|
"LIMIT");
|
||||||
|
|
||||||
qry->rtable = pstate->p_rtable;
|
qry->rtable = pstate->p_rtable;
|
||||||
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
|
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
|
||||||
@ -2376,7 +2383,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
|||||||
|
|
||||||
qry->targetList = transformTargetList(pstate, stmt->targetList);
|
qry->targetList = transformTargetList(pstate, stmt->targetList);
|
||||||
|
|
||||||
qual = transformWhereClause(pstate, stmt->whereClause);
|
qual = transformWhereClause(pstate, stmt->whereClause, "WHERE");
|
||||||
|
|
||||||
qry->rtable = pstate->p_rtable;
|
qry->rtable = pstate->p_rtable;
|
||||||
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
|
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.425 2003/07/03 16:33:37 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.426 2003/07/03 19:07:36 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -4585,12 +4585,13 @@ select_limit:
|
|||||||
| OFFSET select_offset_value
|
| OFFSET select_offset_value
|
||||||
{ $$ = makeList2($2, NULL); }
|
{ $$ = makeList2($2, NULL); }
|
||||||
| LIMIT select_limit_value ',' select_offset_value
|
| LIMIT select_limit_value ',' select_offset_value
|
||||||
/* Disabled because it was too confusing, bjm 2002-02-18 */
|
{
|
||||||
{ elog(ERROR,
|
/* Disabled because it was too confusing, bjm 2002-02-18 */
|
||||||
"LIMIT #,# syntax not supported.\n\tUse separate LIMIT and OFFSET clauses."); }
|
elog(ERROR,
|
||||||
|
"LIMIT #,# syntax not supported.\n\tUse separate LIMIT and OFFSET clauses.");
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
opt_select_limit:
|
opt_select_limit:
|
||||||
select_limit { $$ = $1; }
|
select_limit { $$ = $1; }
|
||||||
| /* EMPTY */
|
| /* EMPTY */
|
||||||
@ -4598,67 +4599,18 @@ opt_select_limit:
|
|||||||
;
|
;
|
||||||
|
|
||||||
select_limit_value:
|
select_limit_value:
|
||||||
Iconst
|
a_expr { $$ = $1; }
|
||||||
{
|
|
||||||
Const *n = makeNode(Const);
|
|
||||||
|
|
||||||
if ($1 < 0)
|
|
||||||
elog(ERROR, "LIMIT must not be negative");
|
|
||||||
|
|
||||||
n->consttype = INT4OID;
|
|
||||||
n->constlen = sizeof(int4);
|
|
||||||
n->constvalue = Int32GetDatum($1);
|
|
||||||
n->constisnull = FALSE;
|
|
||||||
n->constbyval = TRUE;
|
|
||||||
$$ = (Node *)n;
|
|
||||||
}
|
|
||||||
| ALL
|
| ALL
|
||||||
{
|
{
|
||||||
/* LIMIT ALL is represented as a NULL constant */
|
/* LIMIT ALL is represented as a NULL constant */
|
||||||
Const *n = makeNode(Const);
|
A_Const *n = makeNode(A_Const);
|
||||||
|
n->val.type = T_Null;
|
||||||
n->consttype = INT4OID;
|
|
||||||
n->constlen = sizeof(int4);
|
|
||||||
n->constvalue = (Datum) 0;
|
|
||||||
n->constisnull = TRUE;
|
|
||||||
n->constbyval = TRUE;
|
|
||||||
$$ = (Node *)n;
|
|
||||||
}
|
|
||||||
| PARAM
|
|
||||||
{
|
|
||||||
Param *n = makeNode(Param);
|
|
||||||
|
|
||||||
n->paramkind = PARAM_NUM;
|
|
||||||
n->paramid = $1;
|
|
||||||
n->paramtype = INT4OID;
|
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
select_offset_value:
|
select_offset_value:
|
||||||
Iconst
|
a_expr { $$ = $1; }
|
||||||
{
|
|
||||||
Const *n = makeNode(Const);
|
|
||||||
|
|
||||||
if ($1 < 0)
|
|
||||||
elog(ERROR, "OFFSET must not be negative");
|
|
||||||
|
|
||||||
n->consttype = INT4OID;
|
|
||||||
n->constlen = sizeof(int4);
|
|
||||||
n->constvalue = Int32GetDatum($1);
|
|
||||||
n->constisnull = FALSE;
|
|
||||||
n->constbyval = TRUE;
|
|
||||||
$$ = (Node *)n;
|
|
||||||
}
|
|
||||||
| PARAM
|
|
||||||
{
|
|
||||||
Param *n = makeNode(Param);
|
|
||||||
|
|
||||||
n->paramkind = PARAM_NUM;
|
|
||||||
n->paramid = $1;
|
|
||||||
n->paramtype = INT4OID;
|
|
||||||
$$ = (Node *)n;
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.116 2003/06/16 02:03:37 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.117 2003/07/03 19:07:45 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -317,10 +317,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
|
|||||||
save_namespace = pstate->p_namespace;
|
save_namespace = pstate->p_namespace;
|
||||||
pstate->p_namespace = makeList2(j->larg, j->rarg);
|
pstate->p_namespace = makeList2(j->larg, j->rarg);
|
||||||
|
|
||||||
/* This part is just like transformWhereClause() */
|
result = transformWhereClause(pstate, j->quals, "JOIN/ON");
|
||||||
result = transformExpr(pstate, j->quals);
|
|
||||||
|
|
||||||
result = coerce_to_boolean(pstate, result, "JOIN/ON");
|
|
||||||
|
|
||||||
pstate->p_namespace = save_namespace;
|
pstate->p_namespace = save_namespace;
|
||||||
|
|
||||||
@ -945,10 +942,14 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* transformWhereClause -
|
* transformWhereClause -
|
||||||
* transforms the qualification and make sure it is of type Boolean
|
* Transform the qualification and make sure it is of type boolean.
|
||||||
|
* Used for WHERE and allied clauses.
|
||||||
|
*
|
||||||
|
* constructName does not affect the semantics, but is used in error messages
|
||||||
*/
|
*/
|
||||||
Node *
|
Node *
|
||||||
transformWhereClause(ParseState *pstate, Node *clause)
|
transformWhereClause(ParseState *pstate, Node *clause,
|
||||||
|
const char *constructName)
|
||||||
{
|
{
|
||||||
Node *qual;
|
Node *qual;
|
||||||
|
|
||||||
@ -957,7 +958,55 @@ transformWhereClause(ParseState *pstate, Node *clause)
|
|||||||
|
|
||||||
qual = transformExpr(pstate, clause);
|
qual = transformExpr(pstate, clause);
|
||||||
|
|
||||||
qual = coerce_to_boolean(pstate, qual, "WHERE");
|
qual = coerce_to_boolean(pstate, qual, constructName);
|
||||||
|
|
||||||
|
return qual;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* transformLimitClause -
|
||||||
|
* Transform the expression and make sure it is of type integer.
|
||||||
|
* Used for LIMIT and allied clauses.
|
||||||
|
*
|
||||||
|
* constructName does not affect the semantics, but is used in error messages
|
||||||
|
*/
|
||||||
|
Node *
|
||||||
|
transformLimitClause(ParseState *pstate, Node *clause,
|
||||||
|
const char *constructName)
|
||||||
|
{
|
||||||
|
Node *qual;
|
||||||
|
|
||||||
|
if (clause == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
qual = transformExpr(pstate, 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)
|
||||||
|
*/
|
||||||
|
if (contain_vars_of_level(qual, 0))
|
||||||
|
{
|
||||||
|
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||||
|
elog(ERROR, "argument of %s must not contain variables",
|
||||||
|
constructName);
|
||||||
|
}
|
||||||
|
if (checkExprHasAggs(qual))
|
||||||
|
{
|
||||||
|
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||||
|
elog(ERROR, "argument of %s must not contain aggregates",
|
||||||
|
constructName);
|
||||||
|
}
|
||||||
|
if (contain_subplans(qual))
|
||||||
|
{
|
||||||
|
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||||
|
elog(ERROR, "argument of %s must not contain subselects",
|
||||||
|
constructName);
|
||||||
|
}
|
||||||
|
|
||||||
return qual;
|
return qual;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.102 2003/07/01 19:10:53 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.103 2003/07/03 19:07:48 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -564,7 +564,7 @@ coerce_to_boolean(ParseState *pstate, Node *node,
|
|||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
{
|
{
|
||||||
/* translator: first %s is name of a SQL construct, eg WHERE */
|
/* translator: first %s is name of a SQL construct, eg WHERE */
|
||||||
elog(ERROR, "Argument of %s must be type boolean, not type %s",
|
elog(ERROR, "argument of %s must be type boolean, not type %s",
|
||||||
constructName, format_type_be(inputTypeId));
|
constructName, format_type_be(inputTypeId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -572,7 +572,46 @@ coerce_to_boolean(ParseState *pstate, Node *node,
|
|||||||
if (expression_returns_set(node))
|
if (expression_returns_set(node))
|
||||||
{
|
{
|
||||||
/* translator: %s is name of a SQL construct, eg WHERE */
|
/* translator: %s is name of a SQL construct, eg WHERE */
|
||||||
elog(ERROR, "Argument of %s must not be a set function",
|
elog(ERROR, "argument of %s must not be a set function",
|
||||||
|
constructName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* coerce_to_integer()
|
||||||
|
* Coerce an argument of a construct that requires integer input
|
||||||
|
* (LIMIT, OFFSET, etc). Also check that input is not a set.
|
||||||
|
*
|
||||||
|
* Returns the possibly-transformed node tree.
|
||||||
|
*
|
||||||
|
* As with coerce_type, pstate may be NULL if no special unknown-Param
|
||||||
|
* processing is wanted.
|
||||||
|
*/
|
||||||
|
Node *
|
||||||
|
coerce_to_integer(ParseState *pstate, Node *node,
|
||||||
|
const char *constructName)
|
||||||
|
{
|
||||||
|
Oid inputTypeId = exprType(node);
|
||||||
|
|
||||||
|
if (inputTypeId != INT4OID)
|
||||||
|
{
|
||||||
|
node = coerce_to_target_type(pstate, node, inputTypeId,
|
||||||
|
INT4OID, -1,
|
||||||
|
COERCION_ASSIGNMENT,
|
||||||
|
COERCE_IMPLICIT_CAST);
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
/* translator: first %s is name of a SQL construct, eg LIMIT */
|
||||||
|
elog(ERROR, "argument of %s must be type integer, not type %s",
|
||||||
|
constructName, format_type_be(inputTypeId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expression_returns_set(node))
|
||||||
|
{
|
||||||
|
/* translator: %s is name of a SQL construct, eg LIMIT */
|
||||||
|
elog(ERROR, "argument of %s must not be a set function",
|
||||||
constructName);
|
constructName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_clause.h,v 1.32 2003/06/16 02:03:38 tgl Exp $
|
* $Id: parse_clause.h,v 1.33 2003/07/03 19:07:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -21,7 +21,10 @@ extern int setTargetTable(ParseState *pstate, RangeVar *relation,
|
|||||||
bool inh, bool alsoSource);
|
bool inh, bool alsoSource);
|
||||||
extern bool interpretInhOption(InhOption inhOpt);
|
extern bool interpretInhOption(InhOption inhOpt);
|
||||||
|
|
||||||
extern Node *transformWhereClause(ParseState *pstate, Node *where);
|
extern Node *transformWhereClause(ParseState *pstate, Node *clause,
|
||||||
|
const char *constructName);
|
||||||
|
extern Node *transformLimitClause(ParseState *pstate, Node *clause,
|
||||||
|
const char *constructName);
|
||||||
extern List *transformGroupClause(ParseState *pstate, List *grouplist,
|
extern List *transformGroupClause(ParseState *pstate, List *grouplist,
|
||||||
List *targetlist, List *sortClause);
|
List *targetlist, List *sortClause);
|
||||||
extern List *transformSortClause(ParseState *pstate, List *orderlist,
|
extern List *transformSortClause(ParseState *pstate, List *orderlist,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_coerce.h,v 1.52 2003/07/01 19:10:53 tgl Exp $
|
* $Id: parse_coerce.h,v 1.53 2003/07/03 19:07:54 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -54,6 +54,8 @@ extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
|
|||||||
|
|
||||||
extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
|
extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
|
||||||
const char *constructName);
|
const char *constructName);
|
||||||
|
extern Node *coerce_to_integer(ParseState *pstate, Node *node,
|
||||||
|
const char *constructName);
|
||||||
|
|
||||||
extern Oid select_common_type(List *typeids, const char *context);
|
extern Oid select_common_type(List *typeids, const char *context);
|
||||||
extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
|
extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
|
||||||
|
Reference in New Issue
Block a user