Re: [HACKERS] psql's help (the LIMIT stuff)
I hope the QUERY_LIMIT too.
I still have that cnfify() possible fix to review for KQSO. Are you
still thinking limit for 6.4 final, or a minor release after that?I posted the part that is the minimum applied to 6.4 to make
adding LIMIT later non-initdb earlier. Anyway, here it's
again.
Already applied. I assume it is the same as the one I applied.
My LIMIT implementation that does it like the SET in the
toplevel executor (but via parsetree values) is ready for
production. I only held it back because it's feature, not
bugfix.Do you want it in 6.4 final?
We are close to final, and can easily put it in 6.4.1, which I am sure
we will need, and if we split CVS trees, you'll have lots of minor
versions to pick from. :-)
Seems like it would be a nice minor release item, but the problem is
that minor releases aren't tested as much as major ones. How confident
are you in the code? What do others thing?
--
Bruce Momjian | http://www.op.net/~candle
maillist@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
Import Notes
Reply to msg id not found: m0zWLoE-000EBPC@orion.SAPserv.Hamburg.dsh.de
I hope the QUERY_LIMIT too.
I still have that cnfify() possible fix to review for KQSO. Are you
still thinking limit for 6.4 final, or a minor release after that?I posted the part that is the minimum applied to 6.4 to make
adding LIMIT later non-initdb earlier. Anyway, here it's
again.Already applied. I assume it is the same as the one I applied.
Seen, thanks. Your 'Applied' just arrived after I packed it
again. It's the same.
We are close to final, and can easily put it in 6.4.1, which I am sure
we will need, and if we split CVS trees, you'll have lots of minor
versions to pick from. :-)Seems like it would be a nice minor release item, but the problem is
that minor releases aren't tested as much as major ones. How confident
are you in the code? What do others thing?
I regression tested it, and did additional tests in the
SPI/PL area. It works. It only touches the parser and the
executor. Rules, planner/optimizer just bypass the values in
the parsetree. The parser and the executor are parts of
Postgres I feel very familiar with (not so in the optimizer).
I trust in the code and would use it in a production
environment.
It's below.
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#======================================== jwieck@debis.com (Jan Wieck) #
diff -cr src.orig/backend/commands/command.c src/backend/commands/command.c
*** src.orig/backend/commands/command.c Fri Oct 16 11:53:38 1998
--- src/backend/commands/command.c Fri Oct 16 12:56:44 1998
***************
*** 39,44 ****
--- 39,45 ----
#include "utils/mcxt.h"
#include "utils/portal.h"
#include "utils/syscache.h"
+ #include "string.h"
/* ----------------
* PortalExecutorHeapMemory stuff
***************
*** 101,106 ****
--- 102,108 ----
int feature;
QueryDesc *queryDesc;
MemoryContext context;
+ Const limcount;
/* ----------------
* sanity checks
***************
*** 113,118 ****
--- 115,134 ----
}
/* ----------------
+ * Create a const node from the given count value
+ * ----------------
+ */
+ memset(&limcount, 0, sizeof(limcount));
+ limcount.type = T_Const;
+ limcount.consttype = INT4OID;
+ limcount.constlen = sizeof(int4);
+ limcount.constvalue = (Datum)count;
+ limcount.constisnull = FALSE;
+ limcount.constbyval = TRUE;
+ limcount.constisset = FALSE;
+ limcount.constiscast = FALSE;
+
+ /* ----------------
* get the portal from the portal name
* ----------------
*/
***************
*** 176,182 ****
PortalExecutorHeapMemory = (MemoryContext)
PortalGetHeapMemory(portal);
! ExecutorRun(queryDesc, PortalGetState(portal), feature, count);
if (dest == None) /* MOVE */
pfree(queryDesc);
--- 192,198 ----
PortalExecutorHeapMemory = (MemoryContext)
PortalGetHeapMemory(portal);
! ExecutorRun(queryDesc, PortalGetState(portal), feature, (Node *)NULL, (Node *)&limcount);
if (dest == None) /* MOVE */
pfree(queryDesc);
diff -cr src.orig/backend/executor/execMain.c src/backend/executor/execMain.c
*** src.orig/backend/executor/execMain.c Fri Oct 16 11:53:38 1998
--- src/backend/executor/execMain.c Fri Oct 16 20:05:19 1998
***************
*** 64,69 ****
--- 64,70 ----
static void EndPlan(Plan *plan, EState *estate);
static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
Query *parseTree, CmdType operation,
+ int offsetTuples,
int numberTuples, ScanDirection direction,
void (*printfunc) ());
static void ExecRetrieve(TupleTableSlot *slot, void (*printfunc) (),
***************
*** 163,169 ****
* ----------------------------------------------------------------
*/
TupleTableSlot *
! ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
{
CmdType operation;
Query *parseTree;
--- 164,170 ----
* ----------------------------------------------------------------
*/
TupleTableSlot *
! ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, Node *limoffset, Node *limcount)
{
CmdType operation;
Query *parseTree;
***************
*** 171,176 ****
--- 172,179 ----
TupleTableSlot *result;
CommandDest dest;
void (*destination) ();
+ int offset = 0;
+ int count = 0;
/******************
* sanity checks
***************
*** 191,196 ****
--- 194,289 ----
estate->es_processed = 0;
estate->es_lastoid = InvalidOid;
+ /******************
+ * if given get the offset of the LIMIT clause
+ ******************
+ */
+ if (limoffset != NULL)
+ {
+ Const *coffset;
+ Param *poffset;
+ ParamListInfo paramLI;
+ int i;
+
+ switch (nodeTag(limoffset))
+ {
+ case T_Const:
+ coffset = (Const *)limoffset;
+ offset = (int)(coffset->constvalue);
+ break;
+
+ case T_Param:
+ poffset = (Param *)limoffset;
+ paramLI = estate->es_param_list_info;
+
+ if (paramLI == NULL)
+ elog(ERROR, "parameter for limit offset not in executor state");
+ for (i = 0; paramLI[i].kind != PARAM_INVALID; i++)
+ {
+ if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == poffset->paramid)
+ break;
+ }
+ if (paramLI[i].kind == PARAM_INVALID)
+ elog(ERROR, "parameter for limit offset not in executor state");
+ if (paramLI[i].isnull)
+ elog(ERROR, "limit offset cannot be NULL value");
+ offset = (int)(paramLI[i].value);
+
+ break;
+
+ default:
+ elog(ERROR, "unexpected node type %d as limit offset", nodeTag(limoffset));
+ }
+
+ if (offset < 0)
+ elog(ERROR, "limit offset cannot be negative");
+ }
+
+ /******************
+ * if given get the count of the LIMIT clause
+ ******************
+ */
+ if (limcount != NULL)
+ {
+ Const *ccount;
+ Param *pcount;
+ ParamListInfo paramLI;
+ int i;
+
+ switch (nodeTag(limcount))
+ {
+ case T_Const:
+ ccount = (Const *)limcount;
+ count = (int)(ccount->constvalue);
+ break;
+
+ case T_Param:
+ pcount = (Param *)limcount;
+ paramLI = estate->es_param_list_info;
+
+ if (paramLI == NULL)
+ elog(ERROR, "parameter for limit count not in executor state");
+ for (i = 0; paramLI[i].kind != PARAM_INVALID; i++)
+ {
+ if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == pcount->paramid)
+ break;
+ }
+ if (paramLI[i].kind == PARAM_INVALID)
+ elog(ERROR, "parameter for limit count not in executor state");
+ if (paramLI[i].isnull)
+ elog(ERROR, "limit count cannot be NULL value");
+ count = (int)(paramLI[i].value);
+
+ break;
+
+ default:
+ elog(ERROR, "unexpected node type %d as limit count", nodeTag(limcount));
+ }
+
+ if (count < 0)
+ elog(ERROR, "limit count cannot be negative");
+ }
+
switch (feature)
{
***************
*** 199,205 ****
plan,
parseTree,
operation,
! ALL_TUPLES,
ForwardScanDirection,
destination);
break;
--- 292,299 ----
plan,
parseTree,
operation,
! offset,
! count,
ForwardScanDirection,
destination);
break;
***************
*** 208,213 ****
--- 302,308 ----
plan,
parseTree,
operation,
+ offset,
count,
ForwardScanDirection,
destination);
***************
*** 222,227 ****
--- 317,323 ----
plan,
parseTree,
operation,
+ offset,
count,
BackwardScanDirection,
destination);
***************
*** 237,242 ****
--- 333,339 ----
plan,
parseTree,
operation,
+ 0,
ONE_TUPLE,
ForwardScanDirection,
destination);
***************
*** 691,696 ****
--- 788,794 ----
Plan *plan,
Query *parseTree,
CmdType operation,
+ int offsetTuples,
int numberTuples,
ScanDirection direction,
void (*printfunc) ())
***************
*** 742,747 ****
--- 840,859 ----
{
result = NULL;
break;
+ }
+
+ /******************
+ * For now we completely execute the plan and skip
+ * result tuples if requested by LIMIT offset.
+ * Finally we should try to do it in deeper levels
+ * if possible (during index scan)
+ * - Jan
+ ******************
+ */
+ if (offsetTuples > 0)
+ {
+ --offsetTuples;
+ continue;
}
/******************
diff -cr src.orig/backend/executor/functions.c src/backend/executor/functions.c
*** src.orig/backend/executor/functions.c Fri Oct 16 11:53:38 1998
--- src/backend/executor/functions.c Fri Oct 16 19:01:02 1998
***************
*** 130,135 ****
--- 130,138 ----
None);
estate = CreateExecutorState();
+ if (queryTree->limitOffset != NULL || queryTree->limitCount != NULL)
+ elog(ERROR, "LIMIT clause from SQL functions not yet implemented");
+
if (nargs > 0)
{
int i;
***************
*** 200,206 ****
feature = (LAST_POSTQUEL_COMMAND(es)) ? EXEC_RETONE : EXEC_RUN;
! return ExecutorRun(es->qd, es->estate, feature, 0);
}
static void
--- 203,209 ----
feature = (LAST_POSTQUEL_COMMAND(es)) ? EXEC_RETONE : EXEC_RUN;
! return ExecutorRun(es->qd, es->estate, feature, (Node *)NULL, (Node *)NULL);
}
static void
diff -cr src.orig/backend/executor/spi.c src/backend/executor/spi.c
*** src.orig/backend/executor/spi.c Fri Oct 16 11:53:39 1998
--- src/backend/executor/spi.c Fri Oct 16 19:25:33 1998
***************
*** 791,796 ****
--- 791,798 ----
bool isRetrieveIntoRelation = false;
char *intoName = NULL;
int res;
+ Const tcount_const;
+ Node *count = NULL;
switch (operation)
{
***************
*** 825,830 ****
--- 827,865 ----
return SPI_ERROR_OPUNKNOWN;
}
+ /* ----------------
+ * Get the query LIMIT tuple count
+ * ----------------
+ */
+ if (parseTree->limitCount != NULL)
+ {
+ /* ----------------
+ * A limit clause in the parsetree overrides the
+ * tcount parameter
+ * ----------------
+ */
+ count = parseTree->limitCount;
+ }
+ else
+ {
+ /* ----------------
+ * No LIMIT clause in parsetree. Use a local Const node
+ * to put tcount into it
+ * ----------------
+ */
+ memset(&tcount_const, 0, sizeof(tcount_const));
+ tcount_const.type = T_Const;
+ tcount_const.consttype = INT4OID;
+ tcount_const.constlen = sizeof(int4);
+ tcount_const.constvalue = (Datum)tcount;
+ tcount_const.constisnull = FALSE;
+ tcount_const.constbyval = TRUE;
+ tcount_const.constisset = FALSE;
+ tcount_const.constiscast = FALSE;
+
+ count = (Node *)&tcount_const;
+ }
+
if (state == NULL) /* plan preparation */
return res;
#ifdef SPI_EXECUTOR_STATS
***************
*** 845,851 ****
return SPI_OK_CURSOR;
}
! ExecutorRun(queryDesc, state, EXEC_FOR, tcount);
_SPI_current->processed = state->es_processed;
if (operation == CMD_SELECT && queryDesc->dest == SPI)
--- 880,886 ----
return SPI_OK_CURSOR;
}
! ExecutorRun(queryDesc, state, EXEC_FOR, parseTree->limitOffset, count);
_SPI_current->processed = state->es_processed;
if (operation == CMD_SELECT && queryDesc->dest == SPI)
diff -cr src.orig/backend/parser/analyze.c src/backend/parser/analyze.c
*** src.orig/backend/parser/analyze.c Fri Oct 16 11:53:41 1998
--- src/backend/parser/analyze.c Fri Oct 16 13:29:27 1998
***************
*** 180,186 ****
--- 180,190 ----
case T_SelectStmt:
if (!((SelectStmt *) parseTree)->portalname)
+ {
result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
+ result->limitOffset = ((SelectStmt *)parseTree)->limitOffset;
+ result->limitCount = ((SelectStmt *)parseTree)->limitCount;
+ }
else
result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
break;
diff -cr src.orig/backend/parser/gram.y src/backend/parser/gram.y
*** src.orig/backend/parser/gram.y Fri Oct 16 11:53:42 1998
--- src/backend/parser/gram.y Sun Oct 18 22:20:36 1998
***************
*** 45,50 ****
--- 45,51 ----
#include "catalog/catname.h"
#include "utils/elog.h"
#include "access/xact.h"
+ #include "catalog/pg_type.h"
#ifdef MULTIBYTE
#include "mb/pg_wchar.h"
***************
*** 163,169 ****
sort_clause, sortby_list, index_params, index_list, name_list,
from_clause, from_list, opt_array_bounds, nest_array_bounds,
expr_list, attrs, res_target_list, res_target_list2,
! def_list, opt_indirection, group_clause, TriggerFuncArgs
%type <node> func_return
%type <boolean> set_opt
--- 164,171 ----
sort_clause, sortby_list, index_params, index_list, name_list,
from_clause, from_list, opt_array_bounds, nest_array_bounds,
expr_list, attrs, res_target_list, res_target_list2,
! def_list, opt_indirection, group_clause, TriggerFuncArgs,
! opt_select_limit
%type <node> func_return
%type <boolean> set_opt
***************
*** 192,197 ****
--- 194,201 ----
%type <ival> fetch_how_many
+ %type <node> select_limit_value select_offset_value
+
%type <list> OptSeqList
%type <defelt> OptSeqElem
***************
*** 267,273 ****
FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
GRANT, GROUP, HAVING, HOUR_P,
IN, INNER_P, INSENSITIVE, INSERT, INTERVAL, INTO, IS,
! JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
MATCH, MINUTE_P, MONTH_P, NAMES,
NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULL_P, NUMERIC,
OF, ON, ONLY, OPTION, OR, ORDER, OUTER_P,
--- 271,277 ----
FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
GRANT, GROUP, HAVING, HOUR_P,
IN, INNER_P, INSENSITIVE, INSERT, INTERVAL, INTO, IS,
! JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LIMIT, LOCAL,
MATCH, MINUTE_P, MONTH_P, NAMES,
NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULL_P, NUMERIC,
OF, ON, ONLY, OPTION, OR, ORDER, OUTER_P,
***************
*** 299,305 ****
INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
LANCOMPILER, LISTEN, LOAD, LOCATION, LOCK_P, MAXVALUE, MINVALUE, MOVE,
NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
! OIDS, OPERATOR, PASSWORD, PROCEDURAL,
RECIPE, RENAME, RESET, RETURNS, ROW, RULE,
SEQUENCE, SERIAL, SETOF, SHOW, START, STATEMENT, STDIN, STDOUT, TRUSTED,
UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
--- 303,309 ----
INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
LANCOMPILER, LISTEN, LOAD, LOCATION, LOCK_P, MAXVALUE, MINVALUE, MOVE,
NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
! OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL,
RECIPE, RENAME, RESET, RETURNS, ROW, RULE,
SEQUENCE, SERIAL, SETOF, SHOW, START, STATEMENT, STDIN, STDOUT, TRUSTED,
UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
***************
*** 2591,2596 ****
--- 2595,2601 ----
result from_clause where_clause
group_clause having_clause
union_clause sort_clause
+ opt_select_limit
{
SelectStmt *n = makeNode(SelectStmt);
n->unique = $2;
***************
*** 2602,2607 ****
--- 2607,2622 ----
n->havingClause = $8;
n->unionClause = $9;
n->sortClause = $10;
+ if ($11 != NIL)
+ {
+ n->limitOffset = nth(0, $11);
+ n->limitCount = nth(1, $11);
+ }
+ else
+ {
+ n->limitOffset = NULL;
+ n->limitCount = NULL;
+ }
$$ = (Node *)n;
}
;
***************
*** 2699,2704 ****
--- 2714,2794 ----
| ASC { $$ = "<"; }
| DESC { $$ = ">"; }
| /*EMPTY*/ { $$ = "<"; /*default*/ }
+ ;
+
+ opt_select_limit: LIMIT select_offset_value ',' select_limit_value
+ { $$ = lappend(lappend(NIL, $2), $4); }
+ | LIMIT select_limit_value OFFSET select_offset_value
+ { $$ = lappend(lappend(NIL, $4), $2); }
+ | LIMIT select_limit_value
+ { $$ = lappend(lappend(NIL, NULL), $2); }
+ | OFFSET select_offset_value LIMIT select_limit_value
+ { $$ = lappend(lappend(NIL, $2), $4); }
+ | OFFSET select_offset_value
+ { $$ = lappend(lappend(NIL, $2), NULL); }
+ | /* EMPTY */
+ { $$ = NIL; }
+ ;
+
+ select_limit_value: Iconst
+ {
+ Const *n = makeNode(Const);
+
+ if ($1 < 1)
+ elog(ERROR, "selection limit must be ALL or a positive integer value > 0");
+
+ n->consttype = INT4OID;
+ n->constlen = sizeof(int4);
+ n->constvalue = (Datum)$1;
+ n->constisnull = FALSE;
+ n->constbyval = TRUE;
+ n->constisset = FALSE;
+ n->constiscast = FALSE;
+ $$ = (Node *)n;
+ }
+ | ALL
+ {
+ Const *n = makeNode(Const);
+ n->consttype = INT4OID;
+ n->constlen = sizeof(int4);
+ n->constvalue = (Datum)0;
+ n->constisnull = FALSE;
+ n->constbyval = TRUE;
+ n->constisset = FALSE;
+ n->constiscast = FALSE;
+ $$ = (Node *)n;
+ }
+ | PARAM
+ {
+ Param *n = makeNode(Param);
+ n->paramkind = PARAM_NUM;
+ n->paramid = $1;
+ n->paramtype = INT4OID;
+ $$ = (Node *)n;
+ }
+ ;
+
+ select_offset_value: Iconst
+ {
+ Const *n = makeNode(Const);
+
+ n->consttype = INT4OID;
+ n->constlen = sizeof(int4);
+ n->constvalue = (Datum)$1;
+ n->constisnull = FALSE;
+ n->constbyval = TRUE;
+ n->constisset = FALSE;
+ n->constiscast = FALSE;
+ $$ = (Node *)n;
+ }
+ | PARAM
+ {
+ Param *n = makeNode(Param);
+ n->paramkind = PARAM_NUM;
+ n->paramid = $1;
+ n->paramtype = INT4OID;
+ $$ = (Node *)n;
+ }
;
/*
diff -cr src.orig/backend/parser/keywords.c src/backend/parser/keywords.c
*** src.orig/backend/parser/keywords.c Fri Oct 16 11:53:42 1998
--- src/backend/parser/keywords.c Sun Oct 18 22:13:29 1998
***************
*** 128,133 ****
--- 128,134 ----
{"leading", LEADING},
{"left", LEFT},
{"like", LIKE},
+ {"limit", LIMIT},
{"listen", LISTEN},
{"load", LOAD},
{"local", LOCAL},
***************
*** 156,161 ****
--- 157,163 ----
{"null", NULL_P},
{"numeric", NUMERIC},
{"of", OF},
+ {"offset", OFFSET},
{"oids", OIDS},
{"old", CURRENT},
{"on", ON},
diff -cr src.orig/backend/rewrite/rewriteDefine.c src/backend/rewrite/rewriteDefine.c
*** src.orig/backend/rewrite/rewriteDefine.c Fri Oct 16 11:53:46 1998
--- src/backend/rewrite/rewriteDefine.c Fri Oct 16 13:48:55 1998
***************
*** 312,317 ****
--- 312,323 ----
heap_close(event_relation);
/*
+ * LIMIT in view is not supported
+ */
+ if (query->limitOffset != NULL || query->limitCount != NULL)
+ elog(ERROR, "LIMIT clause not supported in views");
+
+ /*
* ... and finally the rule must be named _RETviewname.
*/
sprintf(expected_name, "_RET%s", event_obj->relname);
diff -cr src.orig/backend/tcop/pquery.c src/backend/tcop/pquery.c
*** src.orig/backend/tcop/pquery.c Fri Oct 16 11:53:47 1998
--- src/backend/tcop/pquery.c Fri Oct 16 14:02:36 1998
***************
*** 40,46 ****
#include "commands/command.h"
static char *CreateOperationTag(int operationType);
! static void ProcessQueryDesc(QueryDesc *queryDesc);
/* ----------------------------------------------------------------
--- 40,46 ----
#include "commands/command.h"
static char *CreateOperationTag(int operationType);
! static void ProcessQueryDesc(QueryDesc *queryDesc, Node *limoffset, Node *limcount);
/* ----------------------------------------------------------------
***************
*** 205,211 ****
* ----------------------------------------------------------------
*/
static void
! ProcessQueryDesc(QueryDesc *queryDesc)
{
Query *parseTree;
Plan *plan;
--- 205,211 ----
* ----------------------------------------------------------------
*/
static void
! ProcessQueryDesc(QueryDesc *queryDesc, Node *limoffset, Node *limcount)
{
Query *parseTree;
Plan *plan;
***************
*** 330,336 ****
* actually run the plan..
* ----------------
*/
! ExecutorRun(queryDesc, state, EXEC_RUN, 0);
/* save infos for EndCommand */
UpdateCommandInfo(operation, state->es_lastoid, state->es_processed);
--- 330,336 ----
* actually run the plan..
* ----------------
*/
! ExecutorRun(queryDesc, state, EXEC_RUN, limoffset, limcount);
/* save infos for EndCommand */
UpdateCommandInfo(operation, state->es_lastoid, state->es_processed);
***************
*** 373,377 ****
print_plan(plan, parsetree);
}
else
! ProcessQueryDesc(queryDesc);
}
--- 373,377 ----
print_plan(plan, parsetree);
}
else
! ProcessQueryDesc(queryDesc, parsetree->limitOffset, parsetree->limitCount);
}
diff -cr src.orig/include/executor/executor.h src/include/executor/executor.h
*** src.orig/include/executor/executor.h Fri Oct 16 11:53:56 1998
--- src/include/executor/executor.h Fri Oct 16 12:04:17 1998
***************
*** 83,89 ****
* prototypes from functions in execMain.c
*/
extern TupleDesc ExecutorStart(QueryDesc *queryDesc, EState *estate);
! extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count);
extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate);
extern HeapTuple ExecConstraints(char *caller, Relation rel, HeapTuple tuple);
#ifdef QUERY_LIMIT
--- 83,89 ----
* prototypes from functions in execMain.c
*/
extern TupleDesc ExecutorStart(QueryDesc *queryDesc, EState *estate);
! extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, Node *limoffset, Node *limcount);
extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate);
extern HeapTuple ExecConstraints(char *caller, Relation rel, HeapTuple tuple);
#ifdef QUERY_LIMIT
I also would like to use Web-optimized postgresql in production.
Patched postgres (second trial) passed all regression test on my
Linux box and seems nothing was broken. How about
--enable-limit option to configure so people could make a choice ?
Regards,
Oleg
On Thu, 22 Oct 1998, Jan Wieck wrote:
We are close to final, and can easily put it in 6.4.1, which I am sure
we will need, and if we split CVS trees, you'll have lots of minor
versions to pick from. :-)Seems like it would be a nice minor release item, but the problem is
that minor releases aren't tested as much as major ones. How confident
are you in the code? What do others thing?I regression tested it, and did additional tests in the
SPI/PL area. It works. It only touches the parser and the
executor. Rules, planner/optimizer just bypass the values in
the parsetree. The parser and the executor are parts of
Postgres I feel very familiar with (not so in the optimizer).
I trust in the code and would use it in a production
environment.It's below.
Jan
_____________________________________________________________
Oleg Bartunov, sci.researcher, hostmaster of AstroNet,
Sternberg Astronomical Institute, Moscow University (Russia)
Internet: oleg@sai.msu.su, http://www.sai.msu.su/~megera/
phone: +007(095)939-16-83, +007(095)939-23-83
I also would like to use Web-optimized postgresql in production.
Patched postgres (second trial) passed all regression test on my
Linux box and seems nothing was broken. How about
--enable-limit option to configure so people could make a choice ?Regards,
It will be in 6.4, or in a minor release soon after 6.4.
--
Bruce Momjian | http://www.op.net/~candle
maillist@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
Seems like it would be a nice minor release item, but the problem is
that minor releases aren't tested as much as major ones. How confident
are you in the code? What do others thing?I regression tested it, and did additional tests in the
SPI/PL area. It works. It only touches the parser and the
executor. Rules, planner/optimizer just bypass the values in
the parsetree. The parser and the executor are parts of
Postgres I feel very familiar with (not so in the optimizer).
I trust in the code and would use it in a production
environment.It's below.
Haven't forgotten about this. Planned for the first minor release after
6.4. Hopefully I will have a cnf'ify/OR/palloc fix by then too.
--
Bruce Momjian | http://www.op.net/~candle
maillist@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026