/** * @file compatibility.h * @brief PostgreSQL cross-version compatibility shims for ProvSQL. * * ProvSQL supports a range of PostgreSQL major versions. This header * centralises the small API differences between those versions so that * the rest of the codebase can call a single, stable interface. * * Currently handled differences: * - **List API (13+)**: @c list_delete_cell() and @c lnext() gained or * lost a @p prev argument between PostgreSQL 12 and 13. The * @c my_list_delete_cell() and @c my_lnext() wrappers hide this. * - **list_insert_nth() (< 13)**: In PostgreSQL 12 and earlier the * list implementation was a linked list and this helper did not exist; * @c compatibility.c provides a backport. * - **Predefined function OIDs (< 14)**: The @c F_COUNT_ANY, * @c F_COUNT_, and @c F_SUM_INT4 macros were introduced in PostgreSQL * 14. Stable OID values for older releases are defined here. * - **list_make5() (13)**: existed pre-13, dropped by the PG13 list * rewrite, re-added in PG14; backported for the PG13 gap as a macro * over @c list_make4() + @c lappend(). * - **FuncnameGetCandidates() / OpernameGetCandidates() (14, 19)**: * PostgreSQL 14 added an @p include_out_arguments parameter to the * former; PostgreSQL 19 added a mandatory @p fgc_flags out-parameter * to both. The @c *Compat wrappers take the PG 14-style argument * list and drop / dummy-fill the extra arguments as needed. */ #ifndef COMPATIBILITY_H #define COMPATIBILITY_H #include "postgres.h" #include "nodes/pg_list.h" #include "catalog/namespace.h" /** * @brief Version-agnostic wrapper around @c list_delete_cell(). * * PostgreSQL 13 changed @c list_delete_cell() to no longer require the * previous cell pointer (because lists became arrays). This inline * helper selects the correct call form at compile time. * * @param list The list to modify. * @param cell The cell to delete. * @param prev The cell immediately before @p cell (ignored on PG ≥ 13). * @return The modified list. */ static inline List *my_list_delete_cell(List *list, ListCell *cell, ListCell *prev) { #if PG_VERSION_NUM >= 130000 return list_delete_cell(list, cell); #else return list_delete_cell(list, cell, prev); #endif } /** * @brief Version-agnostic wrapper around @c lnext(). * * PostgreSQL 13 added the list pointer parameter to @c lnext() to * support the array-based list implementation. This inline helper * selects the correct call form at compile time. * * @param l The list (ignored on PG < 13). * @param c The current cell. * @return The next cell, or @c NULL if @p c is the last element. */ static inline ListCell *my_lnext(const List *l, const ListCell *c) { #if PG_VERSION_NUM >= 130000 return lnext(l, c); #else return lnext(c); #endif } /** * @brief Version-agnostic wrapper around @c FuncnameGetCandidates(). * * Takes the PostgreSQL 14+ argument list. On PG < 14 the * @p include_out_arguments parameter (added in 14) is dropped; on * PG >= 19 the @p fgc_flags out-parameter (added in 19, must not be * @c NULL) receives a discarded local, as no caller inspects the * lookup-failure flags. */ static inline FuncCandidateList FuncnameGetCandidatesCompat(List *names, int nargs, List *argnames, bool expand_variadic, bool expand_defaults, bool include_out_arguments, bool missing_ok) { #if PG_VERSION_NUM >= 190000 int fgc_flags; return FuncnameGetCandidates(names, nargs, argnames, expand_variadic, expand_defaults, include_out_arguments, missing_ok, &fgc_flags); #elif PG_VERSION_NUM >= 140000 return FuncnameGetCandidates(names, nargs, argnames, expand_variadic, expand_defaults, include_out_arguments, missing_ok); #else return FuncnameGetCandidates(names, nargs, argnames, expand_variadic, expand_defaults, missing_ok); #endif } /** * @brief Version-agnostic wrapper around @c OpernameGetCandidates(). * * PostgreSQL 19 added an @p fgc_flags out-parameter (must not be * @c NULL); it receives a discarded local, as no caller inspects the * lookup-failure flags. */ static inline FuncCandidateList OpernameGetCandidatesCompat(List *names, char oprkind, bool missing_schema_ok) { #if PG_VERSION_NUM >= 190000 int fgc_flags; return OpernameGetCandidates(names, oprkind, missing_schema_ok, &fgc_flags); #else return OpernameGetCandidates(names, oprkind, missing_schema_ok); #endif } #if PG_VERSION_NUM < 130000 /** * @brief Insert @p datum at position @p pos in @p list (PG < 13 backport). * * PostgreSQL 13 introduced @c list_insert_nth() when lists were * reimplemented as arrays. This declaration provides the same function * for older PostgreSQL versions; the implementation lives in * @c compatibility.c. * * @param list The list to insert into (may be @c NIL). * @param pos Zero-based index at which to insert the new element. * @param datum The value to insert. * @return The (possibly reallocated) list. */ List *list_insert_nth(List *list, int pos, void *datum); #endif #if PG_VERSION_NUM < 140000 /** @brief OID of @c count(*) / @c count(any) aggregate function (pre-PG 14). */ #define F_COUNT_ANY 2147 /** @brief OID of @c count() aggregate function (pre-PG 14). */ #define F_COUNT_ 2803 /** @brief OID of @c sum(int4) aggregate function (pre-PG 14). */ #define F_SUM_INT4 2108 #endif #if PG_VERSION_NUM < 120000 /** @brief Query-walker flag examining RTEs before recursing into them. * PostgreSQL 12 renamed @c QTW_EXAMINE_RTES to this, when it added * @c QTW_EXAMINE_RTES_AFTER. */ #define QTW_EXAMINE_RTES_BEFORE QTW_EXAMINE_RTES #endif #if PG_VERSION_NUM >= 130000 && PG_VERSION_NUM < 140000 /** @brief Five-element list constructor. The linked-list implementation * (pre-PG 13) had it as a macro; the PG13 array rewrite dropped it; PG14 * brought it back. Backport it for the PG13 gap only. */ #define list_make5(x1, x2, x3, x4, x5) lappend(list_make4(x1, x2, x3, x4), x5) #endif #if PG_VERSION_NUM < 130000 /** @brief Alignment codes for the array routines (@c construct_array / * @c deconstruct_array). The @c TYPALIGN_* macros (in @c catalog/pg_type.h) * were introduced in PostgreSQL 13; on PG 11-12 the alignment is passed as * the older @c 'i' / @c 'c' characters. */ #define TYPALIGN_INT 'i' #define TYPALIGN_CHAR 'c' #endif #if PG_VERSION_NUM < 140000 /** @brief OID of the @c array_agg(anynonarray) aggregate (pre-PG 14). * The @c F_ARRAY_AGG_ANYNONARRAY macro only exists since PostgreSQL 14, * when @c fmgroids.h gained overload-disambiguated names for aggregates; * before that, aggregates had no @c fmgroids.h entry at all. Same * stable OID. */ #define F_ARRAY_AGG_ANYNONARRAY 2335 #endif #ifndef F_RANK_ /** @brief OIDs of the ranking window functions (pre-PG 14, where * @c fmgroids.h names them after their C symbols, @c F_WINDOW_RANK...). */ #define F_ROW_NUMBER 3100 #define F_RANK_ 3101 #define F_DENSE_RANK_ 3102 #endif #ifndef F_CUME_DIST_ /** @brief OID of the @c cume_dist() window function (pre-PG 14, where * @c fmgroids.h names it @c F_WINDOW_CUME_DIST). */ #define F_CUME_DIST_ 3104 #endif #ifndef F_NTILE /** @brief OID of the @c ntile() window function (pre-PG 14, where * @c fmgroids.h names it @c F_WINDOW_NTILE). */ #define F_NTILE 3105 #endif #ifndef F_PERCENT_RANK_ /** @brief OID of the @c percent_rank() window function (pre-PG 14, where * @c fmgroids.h names it @c F_WINDOW_PERCENT_RANK). */ #define F_PERCENT_RANK_ 3103 #endif #endif /* COMPATIBILITY_H */