* transformFrameOffset * Process a window frame offset expression * * In RANGE mode, rangeopfamily is the sort opfamily for the input ORDER BY * column, and rangeopcintype is the input data type the sort operator is * registered with. We expect the in_range function to be registered with * that same type. (In binary-compatible cases, it might be different from * the input column's actual
| 3865 | * We'll return the OID of the in_range function to *inRangeFunc. |
| 3866 | */ |
| 3867 | static Node * |
| 3868 | transformFrameOffset(ParseState *pstate, int frameOptions, |
| 3869 | Oid rangeopfamily, Oid rangeopcintype, Oid *inRangeFunc, |
| 3870 | Node *clause) |
| 3871 | { |
| 3872 | const char *constructName = NULL; |
| 3873 | Node *node; |
| 3874 | |
| 3875 | *inRangeFunc = InvalidOid; /* default result */ |
| 3876 | |
| 3877 | /* Quick exit if no offset expression */ |
| 3878 | if (clause == NULL) |
| 3879 | return NULL; |
| 3880 | |
| 3881 | if (frameOptions & FRAMEOPTION_ROWS) |
| 3882 | { |
| 3883 | /* Transform the raw expression tree */ |
| 3884 | node = transformExpr(pstate, clause, EXPR_KIND_WINDOW_FRAME_ROWS); |
| 3885 | |
| 3886 | /* |
| 3887 | * Like LIMIT clause, simply coerce to int8 |
| 3888 | */ |
| 3889 | constructName = "ROWS"; |
| 3890 | node = coerce_to_specific_type(pstate, node, INT8OID, constructName); |
| 3891 | } |
| 3892 | else if (frameOptions & FRAMEOPTION_RANGE) |
| 3893 | { |
| 3894 | /* |
| 3895 | * We must look up the in_range support function that's to be used, |
| 3896 | * possibly choosing one of several, and coerce the "offset" value to |
| 3897 | * the appropriate input type. |
| 3898 | */ |
| 3899 | Oid nodeType; |
| 3900 | Oid preferredType; |
| 3901 | int nfuncs = 0; |
| 3902 | int nmatches = 0; |
| 3903 | Oid selectedType = InvalidOid; |
| 3904 | Oid selectedFunc = InvalidOid; |
| 3905 | CatCList *proclist; |
| 3906 | int i; |
| 3907 | |
| 3908 | /* Transform the raw expression tree */ |
| 3909 | node = transformExpr(pstate, clause, EXPR_KIND_WINDOW_FRAME_RANGE); |
| 3910 | nodeType = exprType(node); |
| 3911 | |
| 3912 | /* |
| 3913 | * If there are multiple candidates, we'll prefer the one that exactly |
| 3914 | * matches nodeType; or if nodeType is as yet unknown, prefer the one |
| 3915 | * that exactly matches the sort column type. (The second rule is |
| 3916 | * like what we do for "known_type operator unknown".) |
| 3917 | */ |
| 3918 | preferredType = (nodeType != UNKNOWNOID) ? nodeType : rangeopcintype; |
| 3919 | |
| 3920 | /* Find the in_range support functions applicable to this case */ |
| 3921 | proclist = SearchSysCacheList2(AMPROCNUM, |
| 3922 | ObjectIdGetDatum(rangeopfamily), |
| 3923 | ObjectIdGetDatum(rangeopcintype)); |
| 3924 | for (i = 0; i < proclist->n_members; i++) |
no test coverage detected