@@ -153,6 +153,7 @@ static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype);
153
153
static void deparseParam (Param * node , deparse_expr_cxt * context );
154
154
static void deparseSubscriptingRef (SubscriptingRef * node , deparse_expr_cxt * context );
155
155
static void deparseFuncExpr (FuncExpr * node , deparse_expr_cxt * context );
156
+ static void deparseFuncColnames (StringInfo buf , int varno , RangeTblEntry * rte , bool qualify_col );
156
157
static void deparseOpExpr (OpExpr * node , deparse_expr_cxt * context );
157
158
static bool isPlainForeignVar (Expr * node , deparse_expr_cxt * context );
158
159
static void deparseOperatorName (StringInfo buf , Form_pg_operator opform );
@@ -1977,23 +1978,98 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
1977
1978
{
1978
1979
RangeTblEntry * rte = planner_rt_fetch (foreignrel -> relid , root );
1979
1980
1980
- /*
1981
- * Core code already has some lock on each rel being planned, so we
1982
- * can use NoLock here.
1983
- */
1984
- Relation rel = table_open (rte -> relid , NoLock );
1981
+ Assert (rte -> rtekind == RTE_RELATION || rte -> rtekind == RTE_FUNCTION );
1982
+ if (rte -> rtekind == RTE_RELATION )
1983
+ {
1984
+ /*
1985
+ * Core code already has some lock on each rel being planned, so
1986
+ * we can use NoLock here.
1987
+ */
1988
+ Relation rel = table_open (rte -> relid , NoLock );
1985
1989
1986
- deparseRelation (buf , rel );
1990
+ deparseRelation (buf , rel );
1991
+
1992
+ table_close (rel , NoLock );
1993
+ }
1994
+ else if (rte -> rtekind == RTE_FUNCTION )
1995
+ {
1996
+ RangeTblFunction * rtfunc ;
1997
+ deparse_expr_cxt context ;
1998
+ ListCell * lc ;
1999
+ bool first = true;
2000
+ int n ;
2001
+
2002
+ n = list_length (rte -> functions );
2003
+ Assert (n >= 1 );
2004
+
2005
+ if (n > 1 )
2006
+ appendStringInfoString (buf , "ROWS FROM (" );
2007
+
2008
+ foreach (lc , rte -> functions )
2009
+ {
2010
+ if (!first )
2011
+ appendStringInfoString (buf , ", " );
2012
+ else
2013
+ first = false;
2014
+
2015
+ rtfunc = (RangeTblFunction * ) lfirst (lc );
2016
+
2017
+ context .root = root ;
2018
+ context .foreignrel = foreignrel ;
2019
+ context .scanrel = foreignrel ;
2020
+ context .buf = buf ;
2021
+ context .params_list = params_list ;
2022
+
2023
+ deparseExpr ((Expr * ) rtfunc -> funcexpr , & context );
2024
+ }
2025
+
2026
+ if (n > 1 )
2027
+ appendStringInfoString (buf , ")" );
2028
+ }
1987
2029
1988
2030
/*
1989
2031
* Add a unique alias to avoid any conflict in relation names due to
1990
2032
* pulled up subqueries in the query being built for a pushed down
1991
2033
* join.
1992
2034
*/
1993
2035
if (use_alias )
2036
+ {
1994
2037
appendStringInfo (buf , " %s%d" , REL_ALIAS_PREFIX , foreignrel -> relid );
2038
+ if (rte -> rtekind == RTE_FUNCTION )
2039
+ {
2040
+ appendStringInfo (buf , " (" );
2041
+ deparseFuncColnames (buf , 0 , rte , false);
2042
+ appendStringInfo (buf , ") " );
2043
+ }
2044
+ }
2045
+ }
2046
+ }
1995
2047
1996
- table_close (rel , NoLock );
2048
+ /*
2049
+ * Deparse function columns alias list
2050
+ */
2051
+ static void
2052
+ deparseFuncColnames (StringInfo buf , int varno , RangeTblEntry * rte , bool qualify_col )
2053
+ {
2054
+ bool first = true;
2055
+ ListCell * lc ;
2056
+
2057
+ Assert (rte );
2058
+ Assert (rte -> rtekind == RTE_FUNCTION );
2059
+ Assert (rte -> eref );
2060
+
2061
+ foreach (lc , rte -> eref -> colnames )
2062
+ {
2063
+ char * colname = strVal (lfirst (lc ));
2064
+
2065
+ if (colname [0 ] == '\0' )
2066
+ continue ;
2067
+ if (!first )
2068
+ appendStringInfoString (buf , "," );
2069
+ if (qualify_col )
2070
+ ADD_REL_QUALIFIER (buf , varno );
2071
+ appendStringInfoString (buf , quote_identifier (colname ));
2072
+ first = false;
1997
2073
}
1998
2074
}
1999
2075
@@ -2717,23 +2793,6 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte,
2717
2793
/* Required only to be passed down to deparseTargetList(). */
2718
2794
List * retrieved_attrs ;
2719
2795
2720
- /*
2721
- * The lock on the relation will be held by upper callers, so it's
2722
- * fine to open it with no lock here.
2723
- */
2724
- rel = table_open (rte -> relid , NoLock );
2725
-
2726
- /*
2727
- * The local name of the foreign table can not be recognized by the
2728
- * foreign server and the table it references on foreign server might
2729
- * have different column ordering or different columns than those
2730
- * declared locally. Hence we have to deparse whole-row reference as
2731
- * ROW(columns referenced locally). Construct this by deparsing a
2732
- * "whole row" attribute.
2733
- */
2734
- attrs_used = bms_add_member (NULL ,
2735
- 0 - FirstLowInvalidHeapAttributeNumber );
2736
-
2737
2796
/*
2738
2797
* In case the whole-row reference is under an outer join then it has
2739
2798
* to go NULL whenever the rest of the row goes NULL. Deparsing a join
@@ -2748,16 +2807,43 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte,
2748
2807
}
2749
2808
2750
2809
appendStringInfoString (buf , "ROW(" );
2751
- deparseTargetList (buf , rte , varno , rel , false, attrs_used , qualify_col ,
2752
- & retrieved_attrs );
2810
+ if (rte -> rtekind == RTE_RELATION )
2811
+ {
2812
+ /*
2813
+ * The local name of the foreign table can not be recognized by
2814
+ * the foreign server and the table it references on foreign
2815
+ * server might have different column ordering or different
2816
+ * columns than those declared locally. Hence we have to deparse
2817
+ * whole-row reference as ROW(columns referenced locally).
2818
+ * Construct this by deparsing a "whole row" attribute.
2819
+ */
2820
+ attrs_used = bms_add_member (NULL ,
2821
+ 0 - FirstLowInvalidHeapAttributeNumber );
2822
+
2823
+ /*
2824
+ * The lock on the relation will be held by upper callers, so it's
2825
+ * fine to open it with no lock here.
2826
+ */
2827
+ rel = table_open (rte -> relid , NoLock );
2828
+ deparseTargetList (buf , rte , varno , rel , false, attrs_used , qualify_col ,
2829
+ & retrieved_attrs );
2830
+ table_close (rel , NoLock );
2831
+ bms_free (attrs_used );
2832
+ }
2833
+ else if (rte -> rtekind == RTE_FUNCTION )
2834
+ {
2835
+ /*
2836
+ * Function call is translated as-is, function returns the same
2837
+ * columns in the same order as on local server
2838
+ */
2839
+ deparseFuncColnames (buf , varno , rte , qualify_col );
2840
+ }
2753
2841
appendStringInfoChar (buf , ')' );
2754
2842
2755
2843
/* Complete the CASE WHEN statement started above. */
2756
2844
if (qualify_col )
2757
2845
appendStringInfoString (buf , " END" );
2758
2846
2759
- table_close (rel , NoLock );
2760
- bms_free (attrs_used );
2761
2847
}
2762
2848
else
2763
2849
{
@@ -2772,29 +2858,40 @@ deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte,
2772
2858
* If it's a column of a foreign table, and it has the column_name FDW
2773
2859
* option, use that value.
2774
2860
*/
2775
- options = GetForeignColumnOptions (rte -> relid , varattno );
2776
- foreach (lc , options )
2861
+ if (rte -> rtekind == RTE_RELATION )
2777
2862
{
2778
- DefElem * def = (DefElem * ) lfirst (lc );
2779
-
2780
- if (strcmp (def -> defname , "column_name" ) == 0 )
2863
+ options = GetForeignColumnOptions (rte -> relid , varattno );
2864
+ foreach (lc , options )
2781
2865
{
2782
- colname = defGetString (def );
2783
- break ;
2866
+ DefElem * def = (DefElem * ) lfirst (lc );
2867
+
2868
+ if (strcmp (def -> defname , "column_name" ) == 0 )
2869
+ {
2870
+ colname = defGetString (def );
2871
+ break ;
2872
+ }
2784
2873
}
2785
- }
2786
2874
2787
- /*
2788
- * If it's a column of a regular table or it doesn't have column_name
2789
- * FDW option, use attribute name.
2790
- */
2791
- if (colname == NULL )
2792
- colname = get_attname (rte -> relid , varattno , false);
2875
+ /*
2876
+ * If it's a column of a regular table or it doesn't have
2877
+ * column_name FDW option, use attribute name.
2878
+ */
2879
+ if (colname == NULL )
2880
+ colname = get_attname (rte -> relid , varattno , false);
2793
2881
2794
- if (qualify_col )
2795
- ADD_REL_QUALIFIER (buf , varno );
2882
+ if (qualify_col )
2883
+ ADD_REL_QUALIFIER (buf , varno );
2796
2884
2797
- appendStringInfoString (buf , quote_identifier (colname ));
2885
+ appendStringInfoString (buf , quote_identifier (colname ));
2886
+ }
2887
+ else if (rte -> rtekind == RTE_FUNCTION )
2888
+ {
2889
+ colname = get_rte_attribute_name (rte , varattno );
2890
+
2891
+ if (qualify_col )
2892
+ ADD_REL_QUALIFIER (buf , varno );
2893
+ appendStringInfoString (buf , quote_identifier (colname ));
2894
+ }
2798
2895
}
2799
2896
}
2800
2897
0 commit comments