← Back to Overview

src/backend/parser/parse_clause.c

Coverage: 2/2 lines (100.0%)
Total Lines
2
modified
Covered
2
100.0%
Uncovered
0
0.0%
Keyboard navigation
transformWindowDefinitions() lines 2972-3179
Modified Lines Coverage: 2/2 lines (100.0%)
LineHitsSourceCommit
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 - } -