From 085e5596541bd894328b08f0e71a6eae3bf22034 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Wed, 26 Jul 2006 00:34:48 +0000 Subject: [PATCH] Change LIMIT/OFFSET to use int8 Dhanaraj M --- src/backend/executor/nodeLimit.c | 33 +++++++++++++++---- src/backend/optimizer/plan/createplan.c | 4 +-- src/backend/optimizer/plan/planner.c | 15 ++++----- src/backend/parser/parse_clause.c | 4 +-- src/backend/parser/parse_coerce.c | 42 +++++++++++++++++++++++-- src/include/nodes/execnodes.h | 8 ++--- src/include/optimizer/planmain.h | 4 +-- src/include/parser/parse_coerce.h | 6 ++-- 8 files changed, 89 insertions(+), 27 deletions(-) diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index 01db14c7d1..99c474b161 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeLimit.c,v 1.25 2006/03/05 15:58:26 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeLimit.c,v 1.26 2006/07/26 00:34:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -23,6 +23,7 @@ #include "executor/executor.h" #include "executor/nodeLimit.h" +#include "catalog/pg_type.h" static void recompute_limits(LimitState *node); @@ -226,14 +227,24 @@ recompute_limits(LimitState *node) { ExprContext *econtext = node->ps.ps_ExprContext; bool isNull; - + Oid type; + if (node->limitOffset) { - node->offset = - DatumGetInt32(ExecEvalExprSwitchContext(node->limitOffset, + type = ((Const *) node->limitOffset->expr)->consttype; + + if (type == INT8OID) + node->offset = + DatumGetInt64(ExecEvalExprSwitchContext(node->limitOffset, econtext, &isNull, NULL)); + else + node->offset = DatumGetInt32(ExecEvalExprSwitchContext(node->limitOffset, + econtext, + &isNull, + NULL)); + /* Interpret NULL offset as no offset */ if (isNull) node->offset = 0; @@ -249,11 +260,21 @@ recompute_limits(LimitState *node) if (node->limitCount) { node->noCount = false; - node->count = - DatumGetInt32(ExecEvalExprSwitchContext(node->limitCount, + type = ((Const *) node->limitCount->expr)->consttype; + + if (type == INT8OID) + node->count = + DatumGetInt64(ExecEvalExprSwitchContext(node->limitCount, econtext, &isNull, NULL)); + else + node->count = DatumGetInt32(ExecEvalExprSwitchContext(node->limitCount, + econtext, + &isNull, + NULL)); + + /* Interpret NULL count as no count (LIMIT ALL) */ if (isNull) node->noCount = true; diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 2a774798c5..7ed718f0b3 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.214 2006/07/14 14:52:20 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.215 2006/07/26 00:34:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2863,7 +2863,7 @@ make_setop(SetOpCmd cmd, Plan *lefttree, */ Limit * make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, - int offset_est, int count_est) + int64 offset_est, int64 count_est) { Limit *node = makeNode(Limit); Plan *plan = &node->plan; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index a16ede1d7c..5545da4978 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.203 2006/07/14 14:52:20 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.204 2006/07/26 00:34:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -59,7 +59,7 @@ static Plan *inheritance_planner(PlannerInfo *root); static Plan *grouping_planner(PlannerInfo *root, double tuple_fraction); static double preprocess_limit(PlannerInfo *root, double tuple_fraction, - int *offset_est, int *count_est); + int64 *offset_est, int64 *count_est); static bool choose_hashed_grouping(PlannerInfo *root, double tuple_fraction, Path *cheapest_path, Path *sorted_path, double dNumGroups, AggClauseCounts *agg_counts); @@ -631,8 +631,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) { Query *parse = root->parse; List *tlist = parse->targetList; - int offset_est = 0; - int count_est = 0; + int64 offset_est = 0; + int64 count_est = 0; Plan *result_plan; List *current_pathkeys; List *sort_pathkeys; @@ -1080,7 +1080,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) */ static double preprocess_limit(PlannerInfo *root, double tuple_fraction, - int *offset_est, int *count_est) + int64 *offset_est, int64 *count_est) { Query *parse = root->parse; Node *est; @@ -1105,7 +1105,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction, } else { - *count_est = DatumGetInt32(((Const *) est)->constvalue); + *count_est = DatumGetInt64(((Const *) est)->constvalue); if (*count_est <= 0) *count_est = 1; /* force to at least 1 */ } @@ -1128,7 +1128,8 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction, } else { - *offset_est = DatumGetInt32(((Const *) est)->constvalue); + *offset_est = DatumGetInt64(((Const *) est)->constvalue); + if (*offset_est < 0) *offset_est = 0; /* less than 0 is same as 0 */ } diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index edd4e83bf8..2b95722530 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.153 2006/07/14 14:52:21 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.154 2006/07/26 00:34:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1090,7 +1090,7 @@ transformLimitClause(ParseState *pstate, Node *clause, qual = transformExpr(pstate, clause); - qual = coerce_to_integer(pstate, qual, constructName); + qual = coerce_to_integer64(pstate, qual, constructName); /* * LIMIT can't refer to any vars or aggregates of the current query; we diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 1e56c63d71..6aa04b7b82 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.141 2006/07/14 14:52:22 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.142 2006/07/26 00:34:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -821,7 +821,7 @@ coerce_to_boolean(ParseState *pstate, Node *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. + * Also check that input is not a set. * * Returns the possibly-transformed node tree. * @@ -857,7 +857,45 @@ coerce_to_integer(ParseState *pstate, Node *node, return node; } + +/* coerce_to_integer64() + * Coerce an argument of a construct that requires integer input + * (LIMIT, OFFSET). 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_integer64(ParseState *pstate, Node *node, + const char *constructName) +{ + Oid inputTypeId = exprType(node); + if (inputTypeId != INT8OID) + { + node = coerce_to_target_type(pstate, node, inputTypeId, + INT8OID, -1, COERCION_ASSIGNMENT, + COERCE_IMPLICIT_CAST); + if (node == NULL) + 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)))); + } + + if (expression_returns_set(node)) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + /* translator: %s is name of a SQL construct, eg LIMIT */ + errmsg("argument of %s must not return a set", + constructName))); + + return node; +} + /* select_common_type() * Determine the common supertype of a list of input expression types. diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 12b52434e7..e03daed8e7 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.153 2006/07/13 16:49:19 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.154 2006/07/26 00:34:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1325,11 +1325,11 @@ typedef struct LimitState PlanState ps; /* its first field is NodeTag */ ExprState *limitOffset; /* OFFSET parameter, or NULL if none */ ExprState *limitCount; /* COUNT parameter, or NULL if none */ - long offset; /* current OFFSET value */ - long count; /* current COUNT, if any */ + int64 offset; /* current OFFSET value */ + int64 count; /* current COUNT, if any */ bool noCount; /* if true, ignore count */ LimitStateCond lstate; /* state machine status, as above */ - long position; /* 1-based index of last tuple returned */ + int64 position; /* 1-based index of last tuple returned */ TupleTableSlot *subSlot; /* tuple last obtained from subplan */ } LimitState; diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 30b89d0974..b21ade9f9a 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.93 2006/07/01 18:38:33 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.94 2006/07/26 00:34:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -55,7 +55,7 @@ extern Material *make_material(Plan *lefttree); extern Plan *materialize_finished_plan(Plan *subplan); extern Unique *make_unique(Plan *lefttree, List *distinctList); extern Limit *make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, - int offset_est, int count_est); + int64 offset_est, int64 count_est); extern SetOp *make_setop(SetOpCmd cmd, Plan *lefttree, List *distinctList, AttrNumber flagColIdx); extern Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan); diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h index 0c46b32e05..a5afff496c 100644 --- a/src/include/parser/parse_coerce.h +++ b/src/include/parser/parse_coerce.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.63 2006/07/13 16:49:19 momjian Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.64 2006/07/26 00:34:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -57,7 +57,9 @@ extern Node *coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName); extern Node *coerce_to_integer(ParseState *pstate, Node *node, const char *constructName); - +extern Node *coerce_to_integer64(ParseState *pstate, Node *node, + const char *constructName); + extern Oid select_common_type(List *typeids, const char *context); extern Node *coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId,