|
40 | 40 | #include "commands/vacuum.h" |
41 | 41 | #include "executor/executor.h" |
42 | 42 | #include "foreign/fdwapi.h" |
| 43 | +#include "funcapi.h" |
43 | 44 | #include "miscadmin.h" |
44 | 45 | #include "nodes/nodeFuncs.h" |
45 | 46 | #include "parser/parse_oper.h" |
@@ -103,7 +104,7 @@ static int acquire_inherited_sample_rows(Relation onerel, int elevel, |
103 | 104 | HeapTuple *rows, int targrows, |
104 | 105 | double *totalrows, double *totaldeadrows); |
105 | 106 | static void update_attstats(Oid relid, bool inh, |
106 | | - int natts, VacAttrStats **vacattrstats); |
| 107 | + int natts, VacAttrStats **vacattrstats, bool is_global_temp); |
107 | 108 | static Datum std_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull); |
108 | 109 | static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull); |
109 | 110 |
|
@@ -323,6 +324,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params, |
323 | 324 | Oid save_userid; |
324 | 325 | int save_sec_context; |
325 | 326 | int save_nestlevel; |
| 327 | + bool is_global_temp = onerel->rd_rel->relpersistence == RELPERSISTENCE_SESSION; |
326 | 328 |
|
327 | 329 | if (inh) |
328 | 330 | ereport(elevel, |
@@ -586,14 +588,14 @@ do_analyze_rel(Relation onerel, VacuumParams *params, |
586 | 588 | * pg_statistic for columns we didn't process, we leave them alone.) |
587 | 589 | */ |
588 | 590 | update_attstats(RelationGetRelid(onerel), inh, |
589 | | - attr_cnt, vacattrstats); |
| 591 | + attr_cnt, vacattrstats, is_global_temp); |
590 | 592 |
|
591 | 593 | for (ind = 0; ind < nindexes; ind++) |
592 | 594 | { |
593 | 595 | AnlIndexData *thisdata = &indexdata[ind]; |
594 | 596 |
|
595 | 597 | update_attstats(RelationGetRelid(Irel[ind]), false, |
596 | | - thisdata->attr_cnt, thisdata->vacattrstats); |
| 598 | + thisdata->attr_cnt, thisdata->vacattrstats, is_global_temp); |
597 | 599 | } |
598 | 600 |
|
599 | 601 | /* |
@@ -1456,7 +1458,7 @@ acquire_inherited_sample_rows(Relation onerel, int elevel, |
1456 | 1458 | * by taking a self-exclusive lock on the relation in analyze_rel(). |
1457 | 1459 | */ |
1458 | 1460 | static void |
1459 | | -update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats) |
| 1461 | +update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats, bool is_global_temp) |
1460 | 1462 | { |
1461 | 1463 | Relation sd; |
1462 | 1464 | int attno; |
@@ -1558,30 +1560,42 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats) |
1558 | 1560 | } |
1559 | 1561 | } |
1560 | 1562 |
|
1561 | | - /* Is there already a pg_statistic tuple for this attribute? */ |
1562 | | - oldtup = SearchSysCache3(STATRELATTINH, |
1563 | | - ObjectIdGetDatum(relid), |
1564 | | - Int16GetDatum(stats->attr->attnum), |
1565 | | - BoolGetDatum(inh)); |
1566 | | - |
1567 | | - if (HeapTupleIsValid(oldtup)) |
| 1563 | + if (is_global_temp) |
1568 | 1564 | { |
1569 | | - /* Yes, replace it */ |
1570 | | - stup = heap_modify_tuple(oldtup, |
1571 | | - RelationGetDescr(sd), |
1572 | | - values, |
1573 | | - nulls, |
1574 | | - replaces); |
1575 | | - ReleaseSysCache(oldtup); |
1576 | | - CatalogTupleUpdate(sd, &stup->t_self, stup); |
| 1565 | + stup = heap_form_tuple(RelationGetDescr(sd), values, nulls); |
| 1566 | + InsertSysCache(STATRELATTINH, |
| 1567 | + ObjectIdGetDatum(relid), |
| 1568 | + Int16GetDatum(stats->attr->attnum), |
| 1569 | + BoolGetDatum(inh), |
| 1570 | + 0, |
| 1571 | + stup); |
1577 | 1572 | } |
1578 | 1573 | else |
1579 | 1574 | { |
1580 | | - /* No, insert new tuple */ |
1581 | | - stup = heap_form_tuple(RelationGetDescr(sd), values, nulls); |
1582 | | - CatalogTupleInsert(sd, stup); |
1583 | | - } |
| 1575 | + /* Is there already a pg_statistic tuple for this attribute? */ |
| 1576 | + oldtup = SearchSysCache3(STATRELATTINH, |
| 1577 | + ObjectIdGetDatum(relid), |
| 1578 | + Int16GetDatum(stats->attr->attnum), |
| 1579 | + BoolGetDatum(inh)); |
1584 | 1580 |
|
| 1581 | + if (HeapTupleIsValid(oldtup)) |
| 1582 | + { |
| 1583 | + /* Yes, replace it */ |
| 1584 | + stup = heap_modify_tuple(oldtup, |
| 1585 | + RelationGetDescr(sd), |
| 1586 | + values, |
| 1587 | + nulls, |
| 1588 | + replaces); |
| 1589 | + ReleaseSysCache(oldtup); |
| 1590 | + CatalogTupleUpdate(sd, &stup->t_self, stup); |
| 1591 | + } |
| 1592 | + else |
| 1593 | + { |
| 1594 | + /* No, insert new tuple */ |
| 1595 | + stup = heap_form_tuple(RelationGetDescr(sd), values, nulls); |
| 1596 | + CatalogTupleInsert(sd, stup); |
| 1597 | + } |
| 1598 | + } |
1585 | 1599 | heap_freetuple(stup); |
1586 | 1600 | } |
1587 | 1601 |
|
@@ -2890,3 +2904,72 @@ analyze_mcv_list(int *mcv_counts, |
2890 | 2904 | } |
2891 | 2905 | return num_mcv; |
2892 | 2906 | } |
| 2907 | + |
| 2908 | +PG_FUNCTION_INFO_V1(pg_gtt_statistic_for_relation); |
| 2909 | + |
| 2910 | +typedef struct |
| 2911 | +{ |
| 2912 | + int staattnum; |
| 2913 | + bool stainherit; |
| 2914 | +} PgTempStatIteratorCtx; |
| 2915 | + |
| 2916 | +Datum |
| 2917 | +pg_gtt_statistic_for_relation(PG_FUNCTION_ARGS) |
| 2918 | +{ |
| 2919 | + Oid starelid = PG_GETARG_OID(0); |
| 2920 | + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; |
| 2921 | + Tuplestorestate *tupstore; |
| 2922 | + MemoryContext per_query_ctx; |
| 2923 | + MemoryContext oldcontext; |
| 2924 | + TupleDesc tupdesc; |
| 2925 | + bool stainherit = false; |
| 2926 | + |
| 2927 | + /* check to see if caller supports us returning a tuplestore */ |
| 2928 | + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) |
| 2929 | + elog(ERROR, "return type must be a row type"); |
| 2930 | + |
| 2931 | + /* check to see if caller supports us returning a tuplestore */ |
| 2932 | + if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) |
| 2933 | + ereport(ERROR, |
| 2934 | + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 2935 | + errmsg("set-valued function called in context that cannot accept a set"))); |
| 2936 | + if (!(rsinfo->allowedModes & SFRM_Materialize)) |
| 2937 | + ereport(ERROR, |
| 2938 | + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 2939 | + errmsg("materialize mode required, but it is not " \ |
| 2940 | + "allowed in this context"))); |
| 2941 | + |
| 2942 | + /* Build tuplestore to hold the result rows */ |
| 2943 | + per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; |
| 2944 | + oldcontext = MemoryContextSwitchTo(per_query_ctx); |
| 2945 | + |
| 2946 | + /* Build a tuple descriptor for our result type */ |
| 2947 | + |
| 2948 | + tupstore = tuplestore_begin_heap(true, false, work_mem); |
| 2949 | + rsinfo->returnMode = SFRM_Materialize; |
| 2950 | + rsinfo->setResult = tupstore; |
| 2951 | + rsinfo->setDesc = tupdesc; |
| 2952 | + |
| 2953 | + do |
| 2954 | + { |
| 2955 | + int staattnum = 0; |
| 2956 | + while (true) |
| 2957 | + { |
| 2958 | + HeapTuple statup = SearchSysCacheCopy3(STATRELATTINH, |
| 2959 | + ObjectIdGetDatum(starelid), |
| 2960 | + Int16GetDatum(++staattnum), |
| 2961 | + BoolGetDatum(stainherit)); |
| 2962 | + if (statup != NULL) |
| 2963 | + tuplestore_puttuple(tupstore, statup); |
| 2964 | + else |
| 2965 | + break; |
| 2966 | + } |
| 2967 | + stainherit = !stainherit; |
| 2968 | + } while (stainherit); |
| 2969 | + |
| 2970 | + MemoryContextSwitchTo(oldcontext); |
| 2971 | + |
| 2972 | + tuplestore_donestoring(tupstore); |
| 2973 | + |
| 2974 | + return (Datum) 0; |
| 2975 | +} |
0 commit comments