| Line | Hits | Source | Commit |
| 2972 |
- |
transformWindowDefinitions(ParseState *pstate, |
- |
| 2973 |
- |
List *windowdefs, |
- |
| 2974 |
- |
List **targetlist) |
- |
| 2975 |
- |
{ |
- |
| 2976 |
- |
List *result = NIL; |
- |
| 2977 |
- |
Index winref = 0; |
- |
| 2978 |
- |
ListCell *lc; |
- |
| 2979 |
- |
|
- |
| 2980 |
- |
foreach(lc, windowdefs) |
- |
| 2981 |
- |
{ |
- |
| 2982 |
- |
WindowDef *windef = (WindowDef *) lfirst(lc); |
- |
| 2983 |
- |
WindowClause *refwc = NULL; |
- |
| 2984 |
- |
List *partitionClause; |
- |
| 2985 |
- |
List *orderClause; |
- |
| 2986 |
- |
Oid rangeopfamily = InvalidOid; |
- |
| 2987 |
- |
Oid rangeopcintype = InvalidOid; |
- |
| 2988 |
- |
WindowClause *wc; |
- |
| 2989 |
- |
|
- |
| 2990 |
- |
winref++; |
- |
| 2991 |
- |
|
- |
| 2992 |
- |
/* |
- |
| 2993 |
- |
* Check for duplicate window names. |
- |
| 2994 |
- |
*/ |
- |
| 2995 |
- |
if (windef->name && |
- |
| 2996 |
- |
findWindowClause(result, windef->name) != NULL) |
- |
| 2997 |
- |
ereport(ERROR, |
- |
| 2998 |
- |
(errcode(ERRCODE_WINDOWING_ERROR), |
- |
| 2999 |
- |
errmsg("window \"%s\" is already defined", windef->name), |
- |
| 3000 |
- |
parser_errposition(pstate, windef->location))); |
- |
| 3001 |
- |
|
- |
| 3002 |
- |
/* |
- |
| 3003 |
- |
* If it references a previous window, look that up. |
- |
| 3004 |
- |
*/ |
- |
| 3005 |
- |
if (windef->refname) |
- |
| 3006 |
- |
{ |
- |
| 3007 |
- |
refwc = findWindowClause(result, windef->refname); |
- |
| 3008 |
- |
if (refwc == NULL) |
- |
| 3009 |
- |
ereport(ERROR, |
- |
| 3010 |
- |
(errcode(ERRCODE_UNDEFINED_OBJECT), |
- |
| 3011 |
- |
errmsg("window \"%s\" does not exist", |
- |
| 3012 |
- |
windef->refname), |
- |
| 3013 |
- |
parser_errposition(pstate, windef->location))); |
- |
| 3014 |
- |
} |
- |
| 3015 |
- |
|
- |
| 3016 |
- |
/* |
- |
| 3017 |
- |
* Transform PARTITION and ORDER specs, if any. These are treated |
- |
| 3018 |
- |
* almost exactly like top-level GROUP BY and ORDER BY clauses, |
- |
| 3019 |
- |
* including the special handling of nondefault operator semantics. |
- |
| 3020 |
- |
*/ |
- |
| 3021 |
- |
orderClause = transformSortClause(pstate, |
- |
| 3022 |
- |
windef->orderClause, |
- |
| 3023 |
- |
targetlist, |
- |
| 3024 |
- |
EXPR_KIND_WINDOW_ORDER, |
- |
| 3025 |
- |
true /* force SQL99 rules */ ); |
- |
| 3026 |
- |
partitionClause = transformGroupClause(pstate, |
- |
| 3027 |
- |
windef->partitionClause, |
- |
| 3028 |
- |
false /* not GROUP BY ALL */ , |
- |
| 3029 |
- |
NULL, |
- |
| 3030 |
- |
targetlist, |
- |
| 3031 |
- |
orderClause, |
- |
| 3032 |
- |
EXPR_KIND_WINDOW_PARTITION, |
- |
| 3033 |
- |
true /* force SQL99 rules */ ); |
- |
| 3034 |
- |
|
- |
| 3035 |
- |
/* |
- |
| 3036 |
- |
* And prepare the new WindowClause. |
- |
| 3037 |
- |
*/ |
- |
| 3038 |
- |
wc = makeNode(WindowClause); |
- |
| 3039 |
6295 |
wc->rpSkipTo = ST_NONE; /* ST_NONE marks this as a non-RPR window; |
c54ba27Row pattern recognition patch (parse/analysis). |
| 3040 |
- |
* overridden by transformRPR() if RPR is used */ |
c54ba27Row pattern recognition patch (parse/analysis). |
| 3041 |
- |
wc->name = windef->name; |
- |
| 3042 |
- |
wc->refname = windef->refname; |
- |
| 3043 |
- |
|
- |
| 3044 |
- |
/* |
- |
| 3045 |
- |
* Per spec, a windowdef that references a previous one copies the |
- |
| 3046 |
- |
* previous partition clause (and mustn't specify its own). It can |
- |
| 3047 |
- |
* specify its own ordering clause, but only if the previous one had |
- |
| 3048 |
- |
* none. It always specifies its own frame clause, and the previous |
- |
| 3049 |
- |
* one must not have a frame clause. Yeah, it's bizarre that each of |
- |
| 3050 |
- |
* these cases works differently, but SQL:2008 says so; see 7.11 |
- |
| 3051 |
- |
* <window clause> syntax rule 10 and general rule 1. The frame |
- |
| 3052 |
- |
* clause rule is especially bizarre because it makes "OVER foo" |
- |
| 3053 |
- |
* different from "OVER (foo)", and requires the latter to throw an |
- |
| 3054 |
- |
* error if foo has a nondefault frame clause. Well, ours not to |
- |
| 3055 |
- |
* reason why, but we do go out of our way to throw a useful error |
- |
| 3056 |
- |
* message for such cases. |
- |
| 3057 |
- |
*/ |
- |
| 3058 |
- |
if (refwc) |
- |
| 3059 |
- |
{ |
- |
| 3060 |
- |
if (partitionClause) |
- |
| 3061 |
- |
ereport(ERROR, |
- |
| 3062 |
- |
(errcode(ERRCODE_WINDOWING_ERROR), |
- |
| 3063 |
- |
errmsg("cannot override PARTITION BY clause of window \"%s\"", |
- |
| 3064 |
- |
windef->refname), |
- |
| 3065 |
- |
parser_errposition(pstate, windef->location))); |
- |
| 3066 |
- |
wc->partitionClause = copyObject(refwc->partitionClause); |
- |
| 3067 |
- |
} |
- |
| 3068 |
- |
else |
- |
| 3069 |
- |
wc->partitionClause = partitionClause; |
- |
| 3070 |
- |
if (refwc) |
- |
| 3071 |
- |
{ |
- |
| 3072 |
- |
if (orderClause && refwc->orderClause) |
- |
| 3073 |
- |
ereport(ERROR, |
- |
| 3074 |
- |
(errcode(ERRCODE_WINDOWING_ERROR), |
- |
| 3075 |
- |
errmsg("cannot override ORDER BY clause of window \"%s\"", |
- |
| 3076 |
- |
windef->refname), |
- |
| 3077 |
- |
parser_errposition(pstate, windef->location))); |
- |
| 3078 |
- |
if (orderClause) |
- |
| 3079 |
- |
{ |
- |
| 3080 |
- |
wc->orderClause = orderClause; |
- |
| 3081 |
- |
wc->copiedOrder = false; |
- |
| 3082 |
- |
} |
- |
| 3083 |
- |
else |
- |
| 3084 |
- |
{ |
- |
| 3085 |
- |
wc->orderClause = copyObject(refwc->orderClause); |
- |
| 3086 |
- |
wc->copiedOrder = true; |
- |
| 3087 |
- |
} |
- |
| 3088 |
- |
} |
- |
| 3089 |
- |
else |
- |
| 3090 |
- |
{ |
- |
| 3091 |
- |
wc->orderClause = orderClause; |
- |
| 3092 |
- |
wc->copiedOrder = false; |
- |
| 3093 |
- |
} |
- |
| 3094 |
- |
if (refwc && refwc->frameOptions != FRAMEOPTION_DEFAULTS) |
- |
| 3095 |
- |
{ |
- |
| 3096 |
- |
/* |
- |
| 3097 |
- |
* Use this message if this is a WINDOW clause, or if it's an OVER |
- |
| 3098 |
- |
* clause that includes ORDER BY or framing clauses. (We already |
- |
| 3099 |
- |
* rejected PARTITION BY above, so no need to check that.) |
- |
| 3100 |
- |
*/ |
- |
| 3101 |
- |
if (windef->name || |
- |
| 3102 |
- |
orderClause || windef->frameOptions != FRAMEOPTION_DEFAULTS) |
- |
| 3103 |
- |
ereport(ERROR, |
- |
| 3104 |
- |
(errcode(ERRCODE_WINDOWING_ERROR), |
- |
| 3105 |
- |
errmsg("cannot copy window \"%s\" because it has a frame clause", |
- |
| 3106 |
- |
windef->refname), |
- |
| 3107 |
- |
parser_errposition(pstate, windef->location))); |
- |
| 3108 |
- |
/* Else this clause is just OVER (foo), so say this: */ |
- |
| 3109 |
- |
ereport(ERROR, |
- |
| 3110 |
- |
(errcode(ERRCODE_WINDOWING_ERROR), |
- |
| 3111 |
- |
errmsg("cannot copy window \"%s\" because it has a frame clause", |
- |
| 3112 |
- |
windef->refname), |
- |
| 3113 |
- |
errhint("Omit the parentheses in this OVER clause."), |
- |
| 3114 |
- |
parser_errposition(pstate, windef->location))); |
- |
| 3115 |
- |
} |
- |
| 3116 |
- |
wc->frameOptions = windef->frameOptions; |
- |
| 3117 |
- |
|
- |
| 3118 |
- |
/* |
- |
| 3119 |
- |
* RANGE offset PRECEDING/FOLLOWING requires exactly one ORDER BY |
- |
| 3120 |
- |
* column; check that and get its sort opfamily info. |
- |
| 3121 |
- |
*/ |
- |
| 3122 |
- |
if ((wc->frameOptions & FRAMEOPTION_RANGE) && |
- |
| 3123 |
- |
(wc->frameOptions & (FRAMEOPTION_START_OFFSET | |
- |
| 3124 |
- |
FRAMEOPTION_END_OFFSET))) |
- |
| 3125 |
- |
{ |
- |
| 3126 |
- |
SortGroupClause *sortcl; |
- |
| 3127 |
- |
Node *sortkey; |
- |
| 3128 |
- |
CompareType rangecmptype; |
- |
| 3129 |
- |
|
- |
| 3130 |
- |
if (list_length(wc->orderClause) != 1) |
- |
| 3131 |
- |
ereport(ERROR, |
- |
| 3132 |
- |
(errcode(ERRCODE_WINDOWING_ERROR), |
- |
| 3133 |
- |
errmsg("RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column"), |
- |
| 3134 |
- |
parser_errposition(pstate, windef->location))); |
- |
| 3135 |
- |
sortcl = linitial_node(SortGroupClause, wc->orderClause); |
- |
| 3136 |
- |
sortkey = get_sortgroupclause_expr(sortcl, *targetlist); |
- |
| 3137 |
- |
/* Find the sort operator in pg_amop */ |
- |
| 3138 |
- |
if (!get_ordering_op_properties(sortcl->sortop, |
- |
| 3139 |
- |
&rangeopfamily, |
- |
| 3140 |
- |
&rangeopcintype, |
- |
| 3141 |
- |
&rangecmptype)) |
- |
| 3142 |
- |
elog(ERROR, "operator %u is not a valid ordering operator", |
- |
| 3143 |
- |
sortcl->sortop); |
- |
| 3144 |
- |
/* Record properties of sort ordering */ |
- |
| 3145 |
- |
wc->inRangeColl = exprCollation(sortkey); |
- |
| 3146 |
- |
wc->inRangeAsc = !sortcl->reverse_sort; |
- |
| 3147 |
- |
wc->inRangeNullsFirst = sortcl->nulls_first; |
- |
| 3148 |
- |
} |
- |
| 3149 |
- |
|
- |
| 3150 |
- |
/* Per spec, GROUPS mode requires an ORDER BY clause */ |
- |
| 3151 |
- |
if (wc->frameOptions & FRAMEOPTION_GROUPS) |
- |
| 3152 |
- |
{ |
- |
| 3153 |
- |
if (wc->orderClause == NIL) |
- |
| 3154 |
- |
ereport(ERROR, |
- |
| 3155 |
- |
(errcode(ERRCODE_WINDOWING_ERROR), |
- |
| 3156 |
- |
errmsg("GROUPS mode requires an ORDER BY clause"), |
- |
| 3157 |
- |
parser_errposition(pstate, windef->location))); |
- |
| 3158 |
- |
} |
- |
| 3159 |
- |
|
- |
| 3160 |
- |
/* Process frame offset expressions */ |
- |
| 3161 |
- |
wc->startOffset = transformFrameOffset(pstate, wc->frameOptions, |
- |
| 3162 |
- |
rangeopfamily, rangeopcintype, |
- |
| 3163 |
- |
&wc->startInRangeFunc, |
- |
| 3164 |
- |
windef->startOffset); |
- |
| 3165 |
- |
wc->endOffset = transformFrameOffset(pstate, wc->frameOptions, |
- |
| 3166 |
- |
rangeopfamily, rangeopcintype, |
- |
| 3167 |
- |
&wc->endInRangeFunc, |
- |
| 3168 |
- |
windef->endOffset); |
- |
| 3169 |
- |
|
c54ba27Row pattern recognition patch (parse/analysis). |
| 3170 |
- |
/* Process Row Pattern Recognition related clauses */ |
c54ba27Row pattern recognition patch (parse/analysis). |
| 3171 |
6259 |
transformRPR(pstate, wc, windef, targetlist); |
c54ba27Row pattern recognition patch (parse/analysis). |
| 3172 |
- |
|
c54ba27Row pattern recognition patch (parse/analysis). |
| 3173 |
- |
wc->winref = winref; |
- |
| 3174 |
- |
|
- |
| 3175 |
- |
result = lappend(result, wc); |
- |
| 3176 |
- |
} |
- |
| 3177 |
- |
|
- |
| 3178 |
- |
return result; |
- |
| 3179 |
- |
} |
- |