← Back to Overview

src/backend/parser/parse_clause.c

Coverage: 1/1 lines (100.0%)
Total Lines
1
modified
Covered
1
100.0%
Uncovered
0
0.0%
키보드 네비게이션
transformWindowDefinitions() lines 2825-3030
Modified Lines Coverage: 1/1 lines (100.0%)
LineHitsSourceCommit
2825 - transformWindowDefinitions(ParseState *pstate, -
2826 - List *windowdefs, -
2827 - List **targetlist) -
2828 - { -
2829 - List *result = NIL; -
2830 - Index winref = 0; -
2831 - ListCell *lc; -
2832 - -
2833 - foreach(lc, windowdefs) -
2834 - { -
2835 - WindowDef *windef = (WindowDef *) lfirst(lc); -
2836 - WindowClause *refwc = NULL; -
2837 - List *partitionClause; -
2838 - List *orderClause; -
2839 - Oid rangeopfamily = InvalidOid; -
2840 - Oid rangeopcintype = InvalidOid; -
2841 - WindowClause *wc; -
2842 - -
2843 - winref++; -
2844 - -
2845 - /* -
2846 - * Check for duplicate window names. -
2847 - */ -
2848 - if (windef->name && -
2849 - findWindowClause(result, windef->name) != NULL) -
2850 - ereport(ERROR, -
2851 - (errcode(ERRCODE_WINDOWING_ERROR), -
2852 - errmsg("window \"%s\" is already defined", windef->name), -
2853 - parser_errposition(pstate, windef->location))); -
2854 - -
2855 - /* -
2856 - * If it references a previous window, look that up. -
2857 - */ -
2858 - if (windef->refname) -
2859 - { -
2860 - refwc = findWindowClause(result, windef->refname); -
2861 - if (refwc == NULL) -
2862 - ereport(ERROR, -
2863 - (errcode(ERRCODE_UNDEFINED_OBJECT), -
2864 - errmsg("window \"%s\" does not exist", -
2865 - windef->refname), -
2866 - parser_errposition(pstate, windef->location))); -
2867 - } -
2868 - -
2869 - /* -
2870 - * Transform PARTITION and ORDER specs, if any. These are treated -
2871 - * almost exactly like top-level GROUP BY and ORDER BY clauses, -
2872 - * including the special handling of nondefault operator semantics. -
2873 - */ -
2874 - orderClause = transformSortClause(pstate, -
2875 - windef->orderClause, -
2876 - targetlist, -
2877 - EXPR_KIND_WINDOW_ORDER, -
2878 - true /* force SQL99 rules */ ); -
2879 - partitionClause = transformGroupClause(pstate, -
2880 - windef->partitionClause, -
2881 - false /* not GROUP BY ALL */ , -
2882 - NULL, -
2883 - targetlist, -
2884 - orderClause, -
2885 - EXPR_KIND_WINDOW_PARTITION, -
2886 - true /* force SQL99 rules */ ); -
2887 - -
2888 - /* -
2889 - * And prepare the new WindowClause. -
2890 - */ -
2891 - wc = makeNode(WindowClause); -
2892 - wc->name = windef->name; -
2893 - wc->refname = windef->refname; -
2894 - -
2895 - /* -
2896 - * Per spec, a windowdef that references a previous one copies the -
2897 - * previous partition clause (and mustn't specify its own). It can -
2898 - * specify its own ordering clause, but only if the previous one had -
2899 - * none. It always specifies its own frame clause, and the previous -
2900 - * one must not have a frame clause. Yeah, it's bizarre that each of -
2901 - * these cases works differently, but SQL:2008 says so; see 7.11 -
2902 - * <window clause> syntax rule 10 and general rule 1. The frame -
2903 - * clause rule is especially bizarre because it makes "OVER foo" -
2904 - * different from "OVER (foo)", and requires the latter to throw an -
2905 - * error if foo has a nondefault frame clause. Well, ours not to -
2906 - * reason why, but we do go out of our way to throw a useful error -
2907 - * message for such cases. -
2908 - */ -
2909 - if (refwc) -
2910 - { -
2911 - if (partitionClause) -
2912 - ereport(ERROR, -
2913 - (errcode(ERRCODE_WINDOWING_ERROR), -
2914 - errmsg("cannot override PARTITION BY clause of window \"%s\"", -
2915 - windef->refname), -
2916 - parser_errposition(pstate, windef->location))); -
2917 - wc->partitionClause = copyObject(refwc->partitionClause); -
2918 - } -
2919 - else -
2920 - wc->partitionClause = partitionClause; -
2921 - if (refwc) -
2922 - { -
2923 - if (orderClause && refwc->orderClause) -
2924 - ereport(ERROR, -
2925 - (errcode(ERRCODE_WINDOWING_ERROR), -
2926 - errmsg("cannot override ORDER BY clause of window \"%s\"", -
2927 - windef->refname), -
2928 - parser_errposition(pstate, windef->location))); -
2929 - if (orderClause) -
2930 - { -
2931 - wc->orderClause = orderClause; -
2932 - wc->copiedOrder = false; -
2933 - } -
2934 - else -
2935 - { -
2936 - wc->orderClause = copyObject(refwc->orderClause); -
2937 - wc->copiedOrder = true; -
2938 - } -
2939 - } -
2940 - else -
2941 - { -
2942 - wc->orderClause = orderClause; -
2943 - wc->copiedOrder = false; -
2944 - } -
2945 - if (refwc && refwc->frameOptions != FRAMEOPTION_DEFAULTS) -
2946 - { -
2947 - /* -
2948 - * Use this message if this is a WINDOW clause, or if it's an OVER -
2949 - * clause that includes ORDER BY or framing clauses. (We already -
2950 - * rejected PARTITION BY above, so no need to check that.) -
2951 - */ -
2952 - if (windef->name || -
2953 - orderClause || windef->frameOptions != FRAMEOPTION_DEFAULTS) -
2954 - ereport(ERROR, -
2955 - (errcode(ERRCODE_WINDOWING_ERROR), -
2956 - errmsg("cannot copy window \"%s\" because it has a frame clause", -
2957 - windef->refname), -
2958 - parser_errposition(pstate, windef->location))); -
2959 - /* Else this clause is just OVER (foo), so say this: */ -
2960 - ereport(ERROR, -
2961 - (errcode(ERRCODE_WINDOWING_ERROR), -
2962 - errmsg("cannot copy window \"%s\" because it has a frame clause", -
2963 - windef->refname), -
2964 - errhint("Omit the parentheses in this OVER clause."), -
2965 - parser_errposition(pstate, windef->location))); -
2966 - } -
2967 - wc->frameOptions = windef->frameOptions; -
2968 - -
2969 - /* -
2970 - * RANGE offset PRECEDING/FOLLOWING requires exactly one ORDER BY -
2971 - * column; check that and get its sort opfamily info. -
2972 - */ -
2973 - if ((wc->frameOptions & FRAMEOPTION_RANGE) && -
2974 - (wc->frameOptions & (FRAMEOPTION_START_OFFSET | -
2975 - FRAMEOPTION_END_OFFSET))) -
2976 - { -
2977 - SortGroupClause *sortcl; -
2978 - Node *sortkey; -
2979 - CompareType rangecmptype; -
2980 - -
2981 - if (list_length(wc->orderClause) != 1) -
2982 - ereport(ERROR, -
2983 - (errcode(ERRCODE_WINDOWING_ERROR), -
2984 - errmsg("RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column"), -
2985 - parser_errposition(pstate, windef->location))); -
2986 - sortcl = linitial_node(SortGroupClause, wc->orderClause); -
2987 - sortkey = get_sortgroupclause_expr(sortcl, *targetlist); -
2988 - /* Find the sort operator in pg_amop */ -
2989 - if (!get_ordering_op_properties(sortcl->sortop, -
2990 - &rangeopfamily, -
2991 - &rangeopcintype, -
2992 - &rangecmptype)) -
2993 - elog(ERROR, "operator %u is not a valid ordering operator", -
2994 - sortcl->sortop); -
2995 - /* Record properties of sort ordering */ -
2996 - wc->inRangeColl = exprCollation(sortkey); -
2997 - wc->inRangeAsc = !sortcl->reverse_sort; -
2998 - wc->inRangeNullsFirst = sortcl->nulls_first; -
2999 - } -
3000 - -
3001 - /* Per spec, GROUPS mode requires an ORDER BY clause */ -
3002 - if (wc->frameOptions & FRAMEOPTION_GROUPS) -
3003 - { -
3004 - if (wc->orderClause == NIL) -
3005 - ereport(ERROR, -
3006 - (errcode(ERRCODE_WINDOWING_ERROR), -
3007 - errmsg("GROUPS mode requires an ORDER BY clause"), -
3008 - parser_errposition(pstate, windef->location))); -
3009 - } -
3010 - -
3011 - /* Process frame offset expressions */ -
3012 - wc->startOffset = transformFrameOffset(pstate, wc->frameOptions, -
3013 - rangeopfamily, rangeopcintype, -
3014 - &wc->startInRangeFunc, -
3015 - windef->startOffset); -
3016 - wc->endOffset = transformFrameOffset(pstate, wc->frameOptions, -
3017 - rangeopfamily, rangeopcintype, -
3018 - &wc->endInRangeFunc, -
3019 - windef->endOffset); -
3020 - d23df91Row pattern recognition patch (parse/analysis).
3021 - /* Process Row Pattern Recognition related clauses */ d23df91Row pattern recognition patch (parse/analysis).
3022 576 transformRPR(pstate, wc, windef, targetlist); d23df91Row pattern recognition patch (parse/analysis).
3023 - d23df91Row pattern recognition patch (parse/analysis).
3024 - wc->winref = winref; -
3025 - -
3026 - result = lappend(result, wc); -
3027 - } -
3028 - -
3029 - return result; -
3030 - } -