diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-12-28 18:54:01 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-12-28 18:54:01 +0000 |
commit | 95b07bc7f5010233f52f9d11da74e2e5b653b0a7 (patch) | |
tree | 48f5858bf4eca1bfb316ef02bb959ca85f568e0a /src/include | |
parent | 38e9348282e9d078487147ba8a85aebec54e3a08 (diff) | |
download | postgresql-95b07bc7f5010233f52f9d11da74e2e5b653b0a7.tar.gz postgresql-95b07bc7f5010233f52f9d11da74e2e5b653b0a7.zip |
Support window functions a la SQL:2008.
Hitoshi Harada, with some kibitzing from Heikki and Tom.
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/catalog/catversion.h | 4 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.h | 34 | ||||
-rw-r--r-- | src/include/executor/nodeWindowAgg.h | 25 | ||||
-rw-r--r-- | src/include/fmgr.h | 4 | ||||
-rw-r--r-- | src/include/nodes/execnodes.h | 69 | ||||
-rw-r--r-- | src/include/nodes/nodes.h | 9 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 51 | ||||
-rw-r--r-- | src/include/nodes/plannodes.h | 17 | ||||
-rw-r--r-- | src/include/nodes/primnodes.h | 17 | ||||
-rw-r--r-- | src/include/nodes/relation.h | 3 | ||||
-rw-r--r-- | src/include/optimizer/clauses.h | 13 | ||||
-rw-r--r-- | src/include/optimizer/cost.h | 6 | ||||
-rw-r--r-- | src/include/optimizer/planmain.h | 7 | ||||
-rw-r--r-- | src/include/optimizer/tlist.h | 4 | ||||
-rw-r--r-- | src/include/parser/parse_agg.h | 7 | ||||
-rw-r--r-- | src/include/parser/parse_clause.h | 10 | ||||
-rw-r--r-- | src/include/parser/parse_func.h | 5 | ||||
-rw-r--r-- | src/include/parser/parse_node.h | 10 | ||||
-rw-r--r-- | src/include/rewrite/rewriteManip.h | 4 | ||||
-rw-r--r-- | src/include/utils/array.h | 4 | ||||
-rw-r--r-- | src/include/utils/builtins.h | 19 | ||||
-rw-r--r-- | src/include/utils/errcodes.h | 5 | ||||
-rw-r--r-- | src/include/utils/tuplestore.h | 4 | ||||
-rw-r--r-- | src/include/windowapi.h | 64 |
24 files changed, 362 insertions, 33 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 2f5ae35ef9f..21bbd429ae8 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.513 2008/12/19 18:25:19 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.514 2008/12/28 18:53:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200812192 +#define CATALOG_VERSION_NO 200812281 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index be632befc92..3082c58a582 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.533 2008/12/19 18:25:19 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.534 2008/12/28 18:53:59 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -4635,6 +4635,38 @@ DESCR("record greater than or equal"); DATA(insert OID = 2987 ( btrecordcmp PGNSP PGUID 12 1 0 0 f f f t f i 2 0 23 "2249 2249" _null_ _null_ _null_ _null_ btrecordcmp _null_ _null_ _null_ )); DESCR("btree less-equal-greater"); +/* SQL-spec window functions */ +DATA(insert OID = 3100 ( row_number PGNSP PGUID 12 1 0 0 f t f f f i 0 0 20 "" _null_ _null_ _null_ _null_ window_row_number _null_ _null_ _null_ )); +DESCR("row number within partition"); +DATA(insert OID = 3101 ( rank PGNSP PGUID 12 1 0 0 f t f f f i 0 0 20 "" _null_ _null_ _null_ _null_ window_rank _null_ _null_ _null_ )); +DESCR("integer rank with gaps"); +DATA(insert OID = 3102 ( dense_rank PGNSP PGUID 12 1 0 0 f t f f f i 0 0 20 "" _null_ _null_ _null_ _null_ window_dense_rank _null_ _null_ _null_ )); +DESCR("integer rank without gaps"); +DATA(insert OID = 3103 ( percent_rank PGNSP PGUID 12 1 0 0 f t f f f i 0 0 701 "" _null_ _null_ _null_ _null_ window_percent_rank _null_ _null_ _null_ )); +DESCR("fractional rank within partition"); +DATA(insert OID = 3104 ( cume_dist PGNSP PGUID 12 1 0 0 f t f f f i 0 0 701 "" _null_ _null_ _null_ _null_ window_cume_dist _null_ _null_ _null_ )); +DESCR("fractional row number within partition"); +DATA(insert OID = 3105 ( ntile PGNSP PGUID 12 1 0 0 f t f t f i 1 0 23 "23" _null_ _null_ _null_ _null_ window_ntile _null_ _null_ _null_ )); +DESCR("split rows into N groups"); +DATA(insert OID = 3106 ( lag PGNSP PGUID 12 1 0 0 f t f t f i 1 0 2283 "2283" _null_ _null_ _null_ _null_ window_lag _null_ _null_ _null_ )); +DESCR("fetch the preceding row value"); +DATA(insert OID = 3107 ( lag PGNSP PGUID 12 1 0 0 f t f t f i 2 0 2283 "2283 23" _null_ _null_ _null_ _null_ window_lag_with_offset _null_ _null_ _null_ )); +DESCR("fetch the Nth preceding row value"); +DATA(insert OID = 3108 ( lag PGNSP PGUID 12 1 0 0 f t f t f i 3 0 2283 "2283 23 2283" _null_ _null_ _null_ _null_ window_lag_with_offset_and_default _null_ _null_ _null_ )); +DESCR("fetch the Nth preceding row value with default"); +DATA(insert OID = 3109 ( lead PGNSP PGUID 12 1 0 0 f t f t f i 1 0 2283 "2283" _null_ _null_ _null_ _null_ window_lead _null_ _null_ _null_ )); +DESCR("fetch the following row value"); +DATA(insert OID = 3110 ( lead PGNSP PGUID 12 1 0 0 f t f t f i 2 0 2283 "2283 23" _null_ _null_ _null_ _null_ window_lead_with_offset _null_ _null_ _null_ )); +DESCR("fetch the Nth following row value"); +DATA(insert OID = 3111 ( lead PGNSP PGUID 12 1 0 0 f t f t f i 3 0 2283 "2283 23 2283" _null_ _null_ _null_ _null_ window_lead_with_offset_and_default _null_ _null_ _null_ )); +DESCR("fetch the Nth following row value with default"); +DATA(insert OID = 3112 ( first_value PGNSP PGUID 12 1 0 0 f t f t f i 1 0 2283 "2283" _null_ _null_ _null_ _null_ window_first_value _null_ _null_ _null_ )); +DESCR("fetch the first row value"); +DATA(insert OID = 3113 ( last_value PGNSP PGUID 12 1 0 0 f t f t f i 1 0 2283 "2283" _null_ _null_ _null_ _null_ window_last_value _null_ _null_ _null_ )); +DESCR("fetch the last row value"); +DATA(insert OID = 3114 ( nth_value PGNSP PGUID 12 1 0 0 f t f t f i 2 0 2283 "2283 23" _null_ _null_ _null_ _null_ window_nth_value _null_ _null_ _null_ )); +DESCR("fetch the Nth row value"); + /* * Symbolic values for provolatile column: these indicate whether the result diff --git a/src/include/executor/nodeWindowAgg.h b/src/include/executor/nodeWindowAgg.h new file mode 100644 index 00000000000..e8531037c07 --- /dev/null +++ b/src/include/executor/nodeWindowAgg.h @@ -0,0 +1,25 @@ +/*------------------------------------------------------------------------- + * + * nodeWindowAgg.h + * prototypes for nodeWindowAgg.c + * + * + * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL: pgsql/src/include/executor/nodeWindowAgg.h,v 1.1 2008/12/28 18:54:00 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef NODEWINDOWAGG_H +#define NODEWINDOWAGG_H + +#include "nodes/execnodes.h" + +extern int ExecCountSlotsWindowAgg(WindowAgg *node); +extern WindowAggState *ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags); +extern TupleTableSlot *ExecWindowAgg(WindowAggState *node); +extern void ExecEndWindowAgg(WindowAggState *node); +extern void ExecReScanWindowAgg(WindowAggState *node, ExprContext *exprCtxt); + +#endif /* NODEWINDOWAGG_H */ diff --git a/src/include/fmgr.h b/src/include/fmgr.h index c348086fbc8..ee95676fe24 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/fmgr.h,v 1.60 2008/09/03 22:34:50 tgl Exp $ + * $PostgreSQL: pgsql/src/include/fmgr.h,v 1.61 2008/12/28 18:54:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -516,6 +516,8 @@ extern Oid fmgr_internal_function(const char *proname); extern Oid get_fn_expr_rettype(FmgrInfo *flinfo); extern Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum); extern Oid get_call_expr_argtype(fmNodePtr expr, int argnum); +extern bool get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum); +extern bool get_call_expr_arg_stable(fmNodePtr expr, int argnum); /* * Routines in dfmgr.c diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 9aae040019b..258abdee6aa 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.196 2008/11/16 17:34:28 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.197 2008/12/28 18:54:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -119,9 +119,12 @@ typedef struct ExprContext ParamExecData *ecxt_param_exec_vals; /* for PARAM_EXEC params */ ParamListInfo ecxt_param_list_info; /* for other param types */ - /* Values to substitute for Aggref nodes in expression */ - Datum *ecxt_aggvalues; /* precomputed values for Aggref nodes */ - bool *ecxt_aggnulls; /* null flags for Aggref nodes */ + /* + * Values to substitute for Aggref nodes in the expressions of an Agg node, + * or for WindowFunc nodes within a WindowAgg node. + */ + Datum *ecxt_aggvalues; /* precomputed values for aggs/windowfuncs */ + bool *ecxt_aggnulls; /* null flags for aggs/windowfuncs */ /* Value to substitute for CaseTestExpr nodes in expression */ Datum caseValue_datum; @@ -512,6 +515,17 @@ typedef struct AggrefExprState } AggrefExprState; /* ---------------- + * WindowFuncExprState node + * ---------------- + */ +typedef struct WindowFuncExprState +{ + ExprState xprstate; + List *args; /* states of argument expressions */ + int wfuncno; /* ID number for wfunc within its plan node */ +} WindowFuncExprState; + +/* ---------------- * ArrayRefExprState node * * Note: array types can be fixed-length (typlen > 0), but only when the @@ -1483,6 +1497,53 @@ typedef struct AggState } AggState; /* ---------------- + * WindowAggState information + * ---------------- + */ +/* these structs are private in nodeWindowAgg.c: */ +typedef struct WindowStatePerFuncData *WindowStatePerFunc; +typedef struct WindowStatePerAggData *WindowStatePerAgg; + +typedef struct WindowAggState +{ + ScanState ss; /* its first field is NodeTag */ + + /* these fields are filled in by ExecInitExpr: */ + List *funcs; /* all WindowFunc nodes in targetlist */ + int numfuncs; /* total number of window functions */ + int numaggs; /* number that are plain aggregates */ + + WindowStatePerFunc perfunc; /* per-window-function information */ + WindowStatePerAgg peragg; /* per-plain-aggregate information */ + FmgrInfo *partEqfunctions; /* equality funcs for partition columns */ + FmgrInfo *ordEqfunctions; /* equality funcs for ordering columns */ + Tuplestorestate *buffer; /* stores rows of current partition */ + int current_ptr; /* read pointer # for current */ + int agg_ptr; /* read pointer # for aggregates */ + int64 spooled_rows; /* total # of rows in buffer */ + int64 currentpos; /* position of current row in partition */ + int64 frametailpos; /* current frame tail position */ + int64 aggregatedupto; /* rows before this one are aggregated */ + + MemoryContext wincontext; /* context for partition-lifespan data */ + ExprContext *tmpcontext; /* short-term evaluation context */ + + bool all_done; /* true if the scan is finished */ + bool partition_spooled; /* true if all tuples in current partition + * have been spooled into tuplestore */ + bool more_partitions; /* true if there's more partitions after + * this one */ + + TupleTableSlot *first_part_slot; /* first tuple of current or next + * partition */ + + /* temporary slots for tuples fetched back from tuplestore */ + TupleTableSlot *first_peer_slot; + TupleTableSlot *temp_slot_1; + TupleTableSlot *temp_slot_2; +} WindowAggState; + +/* ---------------- * UniqueState information * * Unique nodes are used "on top of" sort nodes to discard diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 7383697f6ce..22649cdc073 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.216 2008/12/19 16:25:19 petere Exp $ + * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.217 2008/12/28 18:54:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -66,6 +66,7 @@ typedef enum NodeTag T_Sort, T_Group, T_Agg, + T_WindowAgg, T_Unique, T_Hash, T_SetOp, @@ -103,6 +104,7 @@ typedef enum NodeTag T_SortState, T_GroupState, T_AggState, + T_WindowAggState, T_UniqueState, T_HashState, T_SetOpState, @@ -118,6 +120,7 @@ typedef enum NodeTag T_Const, T_Param, T_Aggref, + T_WindowFunc, T_ArrayRef, T_FuncExpr, T_OpExpr, @@ -164,6 +167,7 @@ typedef enum NodeTag T_ExprState = 400, T_GenericExprState, T_AggrefExprState, + T_WindowFuncExprState, T_ArrayRefExprState, T_FuncExprState, T_ScalarArrayOpExprState, @@ -350,6 +354,7 @@ typedef enum NodeTag T_ResTarget, T_TypeCast, T_SortBy, + T_WindowDef, T_RangeSubselect, T_RangeFunction, T_TypeName, @@ -360,6 +365,7 @@ typedef enum NodeTag T_OptionDefElem, T_RangeTblEntry, T_SortGroupClause, + T_WindowClause, T_FkConstraint, T_PrivGrantee, T_FuncWithArgs, @@ -383,6 +389,7 @@ typedef enum NodeTag */ T_TriggerData = 950, /* in commands/trigger.h */ T_ReturnSetInfo, /* in nodes/execnodes.h */ + T_WindowObjectData, /* private in nodeWindowAgg.c */ T_TIDBitmap /* in nodes/tidbitmap.h */ } NodeTag; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 2f22475bf10..43c4452d781 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.384 2008/12/19 16:25:19 petere Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.385 2008/12/28 18:54:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -120,6 +120,7 @@ typedef struct Query IntoClause *intoClause; /* target for SELECT INTO / CREATE TABLE AS */ bool hasAggs; /* has aggregates in tlist or havingQual */ + bool hasWindowFuncs; /* has window functions in tlist */ bool hasSubLinks; /* has subquery SubLink */ bool hasDistinctOn; /* distinctClause is from DISTINCT ON */ bool hasRecursive; /* WITH RECURSIVE was specified */ @@ -137,6 +138,8 @@ typedef struct Query Node *havingQual; /* qualifications applied to groups */ + List *windowClause; /* a list of WindowClause's */ + List *distinctClause; /* a list of SortGroupClause's */ List *sortClause; /* a list of SortGroupClause's */ @@ -269,7 +272,8 @@ typedef struct TypeCast * agg_star indicates we saw a 'foo(*)' construct, while agg_distinct * indicates we saw 'foo(DISTINCT ...)'. In either case, the construct * *must* be an aggregate call. Otherwise, it might be either an - * aggregate or some other kind of function. + * aggregate or some other kind of function. However, if OVER is present + * it had better be an aggregate or window function. */ typedef struct FuncCall { @@ -279,6 +283,7 @@ typedef struct FuncCall bool agg_star; /* argument was really '*' */ bool agg_distinct; /* arguments were labeled DISTINCT */ bool func_variadic; /* last argument was labeled VARIADIC */ + struct WindowDef *over; /* OVER clause, if any */ int location; /* token location, or -1 if unknown */ } FuncCall; @@ -376,6 +381,19 @@ typedef struct SortBy } SortBy; /* + * WindowDef - raw representation of WINDOW and OVER clauses + */ +typedef struct WindowDef +{ + NodeTag type; + char *name; /* window name (NULL in an OVER clause) */ + char *refname; /* referenced window name, if any */ + List *partitionClause; /* PARTITION BY expression list */ + List *orderClause; /* ORDER BY (list of SortBy) */ + int location; /* parse location, or -1 if none/unknown */ +} WindowDef; + +/* * RangeSubselect - subquery appearing in a FROM clause */ typedef struct RangeSubselect @@ -662,7 +680,8 @@ typedef struct RangeTblEntry /* * SortGroupClause - - * representation of ORDER BY, GROUP BY, DISTINCT, DISTINCT ON items + * representation of ORDER BY, GROUP BY, PARTITION BY, + * DISTINCT, DISTINCT ON items * * You might think that ORDER BY is only interested in defining ordering, * and GROUP/DISTINCT are only interested in defining equality. However, @@ -715,6 +734,31 @@ typedef struct SortGroupClause } SortGroupClause; /* + * WindowClause - + * transformed representation of WINDOW and OVER clauses + * + * A parsed Query's windowClause list contains these structs. "name" is set + * if the clause originally came from WINDOW, and is NULL if it originally + * was an OVER clause (but note that we collapse out duplicate OVERs). + * partitionClause and orderClause are lists of SortGroupClause structs. + * winref is an ID number referenced by WindowFunc nodes; it must be unique + * among the members of a Query's windowClause list. + * When refname isn't null, the partitionClause is always copied from there; + * the orderClause might or might not be copied. (We don't implement + * framing clauses yet, but if we did, they are never copied, per spec.) + */ +typedef struct WindowClause +{ + NodeTag type; + char *name; /* window name (NULL in an OVER clause) */ + char *refname; /* referenced window name, if any */ + List *partitionClause; /* PARTITION BY list */ + List *orderClause; /* ORDER BY list */ + Index winref; /* ID referenced by window functions */ + bool copiedOrder; /* did we copy orderClause from refname? */ +} WindowClause; + +/* * RowMarkClause - * representation of FOR UPDATE/SHARE clauses * @@ -858,6 +902,7 @@ typedef struct SelectStmt Node *whereClause; /* WHERE qualification */ List *groupClause; /* GROUP BY clauses */ Node *havingClause; /* HAVING conditional-expression */ + List *windowClause; /* WINDOW window_name AS (...), ... */ WithClause *withClause; /* WITH clause */ /* diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 16c25fd6d0e..e320fd5fb4c 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.105 2008/10/07 19:27:04 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.106 2008/12/28 18:54:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -537,6 +537,21 @@ typedef struct Agg } Agg; /* ---------------- + * window aggregate node + * ---------------- + */ +typedef struct WindowAgg +{ + Plan plan; + int partNumCols; /* number of columns in partition clause */ + AttrNumber *partColIdx; /* their indexes in the target list */ + Oid *partOperators; /* equality operators for partition columns */ + int ordNumCols; /* number of columns in ordering clause */ + AttrNumber *ordColIdx; /* their indexes in the target list */ + Oid *ordOperators; /* equality operators for ordering columns */ +} WindowAgg; + +/* ---------------- * unique node * ---------------- */ diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 2a2ea18520f..36edc80b9a6 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.143 2008/10/06 17:39:26 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.144 2008/12/28 18:54:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -222,6 +222,21 @@ typedef struct Aggref int location; /* token location, or -1 if unknown */ } Aggref; +/* + * WindowFunc + */ +typedef struct WindowFunc +{ + Expr xpr; + Oid winfnoid; /* pg_proc Oid of the function */ + Oid wintype; /* type Oid of result of the window function */ + List *args; /* arguments to the window function */ + Index winref; /* index of associated WindowClause */ + bool winstar; /* TRUE if argument list was really '*' */ + bool winagg; /* is function a simple aggregate? */ + int location; /* token location, or -1 if unknown */ +} WindowFunc; + /* ---------------- * ArrayRef: describes an array subscripting operation * diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 7b67d94700e..ac292692359 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.165 2008/12/01 21:06:13 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.166 2008/12/28 18:54:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -171,6 +171,7 @@ typedef struct PlannerInfo * actual pathkeys afterwards */ List *group_pathkeys; /* groupClause pathkeys, if any */ + List *window_pathkeys; /* pathkeys of bottom window, if any */ List *distinct_pathkeys; /* distinctClause pathkeys, if any */ List *sort_pathkeys; /* sortClause pathkeys, if any */ diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index 3623aade6a7..f4e668bef30 100644 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.95 2008/10/09 19:27:40 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.96 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,6 +27,13 @@ typedef struct Size transitionSpace; /* for pass-by-ref transition data */ } AggClauseCounts; +typedef struct +{ + int numWindowFuncs; /* total number of WindowFuncs found */ + Index maxWinRef; /* windowFuncs[] is indexed 0 .. maxWinRef */ + List **windowFuncs; /* lists of WindowFuncs for each winref */ +} WindowFuncLists; + extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop); @@ -47,8 +54,12 @@ extern Expr *make_ands_explicit(List *andclauses); extern List *make_ands_implicit(Expr *clause); extern bool contain_agg_clause(Node *clause); +extern List *pull_agg_clause(Node *clause); extern void count_agg_clauses(Node *clause, AggClauseCounts *counts); +extern bool contain_window_function(Node *clause); +extern WindowFuncLists *find_window_functions(Node *clause, Index maxWinRef); + extern double expression_returns_set_rows(Node *clause); extern bool contain_subplans(Node *clause); diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 181327caa81..777f7f0fabe 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.93 2008/10/04 21:56:55 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.94 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -85,6 +85,10 @@ extern void cost_agg(Path *path, PlannerInfo *root, int numGroupCols, double numGroups, Cost input_startup_cost, Cost input_total_cost, double input_tuples); +extern void cost_windowagg(Path *path, PlannerInfo *root, + int numWindowFuncs, int numPartCols, int numOrderCols, + Cost input_startup_cost, Cost input_total_cost, + double input_tuples); extern void cost_group(Path *path, PlannerInfo *root, int numGroupCols, double numGroups, Cost input_startup_cost, Cost input_total_cost, diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 641ebe42fb4..d6f5ff160f6 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.114 2008/10/07 19:27:04 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.115 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -56,6 +56,11 @@ extern Agg *make_agg(PlannerInfo *root, List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, long numGroups, int numAggs, Plan *lefttree); +extern WindowAgg *make_windowagg(PlannerInfo *root, List *tlist, + int numWindowFuncs, + int partNumCols, AttrNumber *partColIdx, Oid *partOperators, + int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, + Plan *lefttree); extern Group *make_group(PlannerInfo *root, List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, double numGroups, diff --git a/src/include/optimizer/tlist.h b/src/include/optimizer/tlist.h index d2c7f42e05f..dabef328dea 100644 --- a/src/include/optimizer/tlist.h +++ b/src/include/optimizer/tlist.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/tlist.h,v 1.52 2008/08/07 19:35:02 tgl Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/tlist.h,v 1.53 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,7 +21,7 @@ extern TargetEntry *tlist_member(Node *node, List *targetlist); extern TargetEntry *tlist_member_ignore_relabel(Node *node, List *targetlist); extern List *flatten_tlist(List *tlist); -extern List *add_to_flat_tlist(List *tlist, List *vars); +extern List *add_to_flat_tlist(List *tlist, List *exprs); extern List *get_tlist_exprs(List *tlist, bool includeJunk); extern bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK); diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h index bf3574e89fc..93b7f674e32 100644 --- a/src/include/parser/parse_agg.h +++ b/src/include/parser/parse_agg.h @@ -1,12 +1,12 @@ /*------------------------------------------------------------------------- * * parse_agg.h - * handle aggregates in parser + * handle aggregates and window functions in parser * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_agg.h,v 1.36 2008/01/01 19:45:58 momjian Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_agg.h,v 1.37 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,8 +16,11 @@ #include "parser/parse_node.h" extern void transformAggregateCall(ParseState *pstate, Aggref *agg); +extern void transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc, + WindowDef *windef); extern void parseCheckAggregates(ParseState *pstate, Query *qry); +extern void parseCheckWindowFuncs(ParseState *pstate, Query *qry); extern void build_aggregate_fnexprs(Oid *agg_input_types, int agg_num_inputs, diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h index ffea3466b5c..0463e7ae66e 100644 --- a/src/include/parser/parse_clause.h +++ b/src/include/parser/parse_clause.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_clause.h,v 1.52 2008/08/07 01:11:52 tgl Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_clause.h,v 1.53 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,9 +27,15 @@ extern Node *transformWhereClause(ParseState *pstate, Node *clause, extern Node *transformLimitClause(ParseState *pstate, Node *clause, const char *constructName); extern List *transformGroupClause(ParseState *pstate, List *grouplist, - List **targetlist, List *sortClause); + List **targetlist, List *sortClause, + bool isPartition); extern List *transformSortClause(ParseState *pstate, List *orderlist, List **targetlist, bool resolveUnknown); + +extern List *transformWindowDefinitions(ParseState *pstate, + List *windowdefs, + List **targetlist); + extern List *transformDistinctClause(ParseState *pstate, List **targetlist, List *sortClause); extern List *transformDistinctOnClause(ParseState *pstate, List *distinctlist, diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h index 8507a4ed7d5..b7023bf8d3d 100644 --- a/src/include/parser/parse_func.h +++ b/src/include/parser/parse_func.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.62 2008/12/18 18:20:35 tgl Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.63 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,6 +37,7 @@ typedef enum FUNCDETAIL_MULTIPLE, /* too many matching functions */ FUNCDETAIL_NORMAL, /* found a matching regular function */ FUNCDETAIL_AGGREGATE, /* found a matching aggregate function */ + FUNCDETAIL_WINDOWFUNC, /* found a matching window function */ FUNCDETAIL_COERCION /* it's a type coercion request */ } FuncDetailCode; @@ -44,7 +45,7 @@ typedef enum extern Node *ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, bool agg_star, bool agg_distinct, bool func_variadic, - bool is_column, int location); + WindowDef *over, bool is_column, int location); extern FuncDetailCode func_get_detail(List *funcname, List *fargs, int nargs, Oid *argtypes, diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index 8e0d3c201f2..0abe45df32c 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.58 2008/10/08 01:14:44 tgl Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.59 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,6 +57,12 @@ * p_future_ctes: list of CommonTableExprs (WITH items) that are not yet * visible due to scope rules. This is used to help improve error messages. * + * p_windowdefs: list of WindowDefs representing WINDOW and OVER clauses. + * We collect these while transforming expressions and then transform them + * afterwards (so that any resjunk tlist items needed for the sort/group + * clauses end up at the end of the query tlist). A WindowDef's location in + * this list, counting from 1, is the winref number to use to reference it. + * * p_paramtypes: an array of p_numparams type OIDs for $n parameter symbols * (zeroth entry in array corresponds to $1). If p_variableparams is true, the * set of param types is not predetermined; in that case, a zero array entry @@ -77,6 +83,7 @@ typedef struct ParseState List *p_varnamespace; /* current namespace for columns */ List *p_ctenamespace; /* current namespace for common table exprs */ List *p_future_ctes; /* common table exprs not yet in namespace */ + List *p_windowdefs; /* raw representations of window clauses */ Oid *p_paramtypes; /* OIDs of types for $n parameter symbols */ int p_numparams; /* allocated size of p_paramtypes[] */ int p_next_resno; /* next targetlist resno to assign */ @@ -84,6 +91,7 @@ typedef struct ParseState Node *p_value_substitute; /* what to replace VALUE with, if any */ bool p_variableparams; bool p_hasAggs; + bool p_hasWindowFuncs; bool p_hasSubLinks; bool p_is_insert; bool p_is_update; diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h index 50b4443de0d..9387e71354b 100644 --- a/src/include/rewrite/rewriteManip.h +++ b/src/include/rewrite/rewriteManip.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.47 2008/09/01 20:42:45 tgl Exp $ + * $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.48 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,7 +37,9 @@ extern void AddInvertedQual(Query *parsetree, Node *qual); extern bool contain_aggs_of_level(Node *node, int levelsup); extern int locate_agg_of_level(Node *node, int levelsup); +extern int locate_windowfunc(Node *node); extern bool checkExprHasAggs(Node *node); +extern bool checkExprHasWindowFuncs(Node *node); extern bool checkExprHasSubLink(Node *node); extern Node *ResolveNew(Node *node, int target_varno, int sublevels_up, diff --git a/src/include/utils/array.h b/src/include/utils/array.h index 8a7f10451f0..6d0f5bf13c6 100644 --- a/src/include/utils/array.h +++ b/src/include/utils/array.h @@ -49,7 +49,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/array.h,v 1.72 2008/11/14 00:51:47 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/array.h,v 1.73 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -250,7 +250,7 @@ extern ArrayBuildState *accumArrayResult(ArrayBuildState *astate, extern Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext); extern Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, - int *dims, int *lbs, MemoryContext rcontext); + int *dims, int *lbs, MemoryContext rcontext, bool release); /* * prototypes for functions defined in arrayutils.c diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index a00415aaa65..65be80c24b4 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.328 2008/12/19 16:25:19 petere Exp $ + * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.329 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -988,6 +988,23 @@ extern Datum uuid_ne(PG_FUNCTION_ARGS); extern Datum uuid_cmp(PG_FUNCTION_ARGS); extern Datum uuid_hash(PG_FUNCTION_ARGS); +/* windowfuncs.c */ +extern Datum window_row_number(PG_FUNCTION_ARGS); +extern Datum window_rank(PG_FUNCTION_ARGS); +extern Datum window_dense_rank(PG_FUNCTION_ARGS); +extern Datum window_percent_rank(PG_FUNCTION_ARGS); +extern Datum window_cume_dist(PG_FUNCTION_ARGS); +extern Datum window_ntile(PG_FUNCTION_ARGS); +extern Datum window_lag(PG_FUNCTION_ARGS); +extern Datum window_lag_with_offset(PG_FUNCTION_ARGS); +extern Datum window_lag_with_offset_and_default(PG_FUNCTION_ARGS); +extern Datum window_lead(PG_FUNCTION_ARGS); +extern Datum window_lead_with_offset(PG_FUNCTION_ARGS); +extern Datum window_lead_with_offset_and_default(PG_FUNCTION_ARGS); +extern Datum window_first_value(PG_FUNCTION_ARGS); +extern Datum window_last_value(PG_FUNCTION_ARGS); +extern Datum window_nth_value(PG_FUNCTION_ARGS); + /* access/transam/twophase.c */ extern Datum pg_prepared_xact(PG_FUNCTION_ARGS); diff --git a/src/include/utils/errcodes.h b/src/include/utils/errcodes.h index baecd7bafcb..4e393c62ac0 100644 --- a/src/include/utils/errcodes.h +++ b/src/include/utils/errcodes.h @@ -11,7 +11,7 @@ * * Copyright (c) 2003-2008, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.26 2008/10/04 21:56:55 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.27 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -122,6 +122,8 @@ #define ERRCODE_INDICATOR_OVERFLOW MAKE_SQLSTATE('2','2', '0','2','2') #define ERRCODE_INTERVAL_FIELD_OVERFLOW MAKE_SQLSTATE('2','2', '0','1','5') #define ERRCODE_INVALID_ARGUMENT_FOR_LOG MAKE_SQLSTATE('2','2', '0','1','E') +#define ERRCODE_INVALID_ARGUMENT_FOR_NTILE MAKE_SQLSTATE('2','2', '0','1','4') +#define ERRCODE_INVALID_ARGUMENT_FOR_NTH_VALUE MAKE_SQLSTATE('2','2', '0','1','6') #define ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION MAKE_SQLSTATE('2','2', '0', '1', 'F') #define ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION MAKE_SQLSTATE('2','2', '0', '1', 'G') #define ERRCODE_INVALID_CHARACTER_VALUE_FOR_CAST MAKE_SQLSTATE('2','2', '0','1','8') @@ -246,6 +248,7 @@ #define ERRCODE_INSUFFICIENT_PRIVILEGE MAKE_SQLSTATE('4','2', '5','0','1') #define ERRCODE_CANNOT_COERCE MAKE_SQLSTATE('4','2', '8','4','6') #define ERRCODE_GROUPING_ERROR MAKE_SQLSTATE('4','2', '8','0','3') +#define ERRCODE_WINDOWING_ERROR MAKE_SQLSTATE('4','2', 'P','2','0') #define ERRCODE_INVALID_RECURSION MAKE_SQLSTATE('4','2', 'P','1','9') #define ERRCODE_INVALID_FOREIGN_KEY MAKE_SQLSTATE('4','2', '8','3','0') #define ERRCODE_INVALID_NAME MAKE_SQLSTATE('4','2', '6','0','2') diff --git a/src/include/utils/tuplestore.h b/src/include/utils/tuplestore.h index 9f9981ff41d..bb9f19cce2c 100644 --- a/src/include/utils/tuplestore.h +++ b/src/include/utils/tuplestore.h @@ -24,7 +24,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/tuplestore.h,v 1.26 2008/12/27 17:39:00 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/tuplestore.h,v 1.27 2008/12/28 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -68,6 +68,8 @@ extern void tuplestore_copy_read_pointer(Tuplestorestate *state, extern void tuplestore_trim(Tuplestorestate *state); +extern bool tuplestore_in_memory(Tuplestorestate *state); + extern bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, TupleTableSlot *slot); extern bool tuplestore_advance(Tuplestorestate *state, bool forward); diff --git a/src/include/windowapi.h b/src/include/windowapi.h new file mode 100644 index 00000000000..25ba25fc50a --- /dev/null +++ b/src/include/windowapi.h @@ -0,0 +1,64 @@ +/*------------------------------------------------------------------------- + * + * windowapi.h + * API for window functions to extract data from their window + * + * A window function does not receive its arguments in the normal way + * (and therefore the concept of strictness is irrelevant). Instead it + * receives a "WindowObject", which it can fetch with PG_WINDOW_OBJECT() + * (note V1 calling convention must be used). Correct call context can + * be tested with WindowObjectIsValid(). Although argument values are + * not passed, the call is correctly set up so that PG_NARGS() can be + * used and argument type information can be obtained with + * get_fn_expr_argtype(), get_fn_expr_arg_stable(), etc. + * + * Operations on the WindowObject allow the window function to find out + * the current row number, total number of rows in the partition, etc + * and to evaluate its argument expression(s) at various rows in the + * window partition. See the header comments for each WindowObject API + * function in nodeWindowAgg.c for details. + * + * + * Portions Copyright (c) 2000-2008, PostgreSQL Global Development Group + * + * $PostgreSQL: pgsql/src/include/windowapi.h,v 1.1 2008/12/28 18:54:00 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef WINDOWAPI_H +#define WINDOWAPI_H + +/* values of "seektype" */ +#define WINDOW_SEEK_CURRENT 0 +#define WINDOW_SEEK_HEAD 1 +#define WINDOW_SEEK_TAIL 2 + +/* this struct is private in nodeWindowAgg.c */ +typedef struct WindowObjectData *WindowObject; + +#define PG_WINDOW_OBJECT() ((WindowObject) fcinfo->context) + +#define WindowObjectIsValid(winobj) \ + ((winobj) != NULL && IsA(winobj, WindowObjectData)) + +extern void *WinGetPartitionLocalMemory(WindowObject winobj, Size sz); + +extern int64 WinGetCurrentPosition(WindowObject winobj); +extern int64 WinGetPartitionRowCount(WindowObject winobj); + +extern void WinSetMarkPosition(WindowObject winobj, int64 markpos); + +extern bool WinRowsArePeers(WindowObject winobj, int64 pos1, int64 pos2); + +extern Datum WinGetFuncArgInPartition(WindowObject winobj, int argno, + int relpos, int seektype, bool set_mark, + bool *isnull, bool *isout); + +extern Datum WinGetFuncArgInFrame(WindowObject winobj, int argno, + int relpos, int seektype, bool set_mark, + bool *isnull, bool *isout); + +extern Datum WinGetFuncArgCurrent(WindowObject winobj, int argno, + bool *isnull); + +#endif /* WINDOWAPI_H */ |