10000
We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
1 parent cd142e0 commit bd12080Copy full SHA for bd12080
src/backend/catalog/index.c
@@ -1884,6 +1884,62 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
1884
/* Copy data of pg_statistic from the old index to the new one */
1885
CopyStatistics(oldIndexId, newIndexId);
1886
1887
+ /* Copy pg_attribute.attstattarget for each index attribute */
1888
+ {
1889
+ HeapTuple attrTuple;
1890
+ Relation pg_attribute;
1891
+ SysScanDesc scan;
1892
+ ScanKeyData key[1];
1893
+
1894
+ pg_attribute = table_open(AttributeRelationId, RowExclusiveLock);
1895
+ ScanKeyInit(&key[0],
1896
+ Anum_pg_attribute_attrelid,
1897
+ BTEqualStrategyNumber, F_OIDEQ,
1898
+ ObjectIdGetDatum(newIndexId));
1899
+ scan = systable_beginscan(pg_attribute, AttributeRelidNumIndexId,
1900
+ true, NULL, 1, key);
1901
1902
+ while (HeapTupleIsValid((attrTuple = systable_getnext(scan))))
1903
1904
+ Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attrTuple);
1905
+ Datum repl_val[Natts_pg_attribute];
1906
+ bool repl_null[Natts_pg_attribute];
1907
+ bool repl_repl[Natts_pg_attribute];
1908
+ int attstattarget;
1909
+ HeapTuple newTuple;
1910
1911
+ /* Ignore dropped columns */
1912
+ if (att->attisdropped)
1913
+ continue;
1914
1915
+ /*
1916
+ * Get attstattarget from the old index and refresh the new value.
1917
+ */
1918
+ attstattarget = get_attstattarget(oldIndexId, att->attnum);
1919
1920
+ /* no need for a refresh if both match */
1921
+ if (attstattarget == att->attstattarget)
1922
1923
1924
+ memset(repl_val, 0, sizeof(repl_val));
1925
+ memset(repl_null, false, sizeof(repl_null));
1926
+ memset(repl_repl, false, sizeof(repl_repl));
1927
1928
+ repl_repl[Anum_pg_attribute_attstattarget - 1] = true;
1929
+ repl_val[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(attstattarget);
1930
1931
+ newTuple = heap_modify_tuple(attrTuple,
1932
+ RelationGetDescr(pg_attribute),
1933
+ repl_val, repl_null, repl_repl);
1934
+ CatalogTupleUpdate(pg_attribute, &newTuple->t_self, newTuple);
1935
1936
+ heap_freetuple(newTuple);
1937
+ }
1938
1939
+ systable_endscan(scan);
1940
+ table_close(pg_attribute, RowExclusiveLock);
1941
1942
1943
/* Close relations */
1944
table_close(pg_class, RowExclusiveLock);
1945
table_close(pg_index, RowExclusiveLock);
src/backend/utils/cache/lsyscache.c
@@ -871,6 +871,33 @@ get_attnum(Oid relid, const char *attname)
871
return InvalidAttrNumber;
872
}
873
874
+/*
875
+ * get_attstattarget
876
+ *
877
+ * Given the relation id and the attribute number,
878
+ * return the "attstattarget" field from the attribute relation.
879
880
+ * Errors if not found.
881
882
+int
883
+get_attstattarget(Oid relid, AttrNumber attnum)
884
+{
885
+ HeapTuple tp;
886
+ Form_pg_attribute att_tup;
887
+ int result;
888
889
+ tp = SearchSysCache2(ATTNUM,
890
+ ObjectIdGetDatum(relid),
891
+ Int16GetDatum(attnum));
892
+ if (!HeapTupleIsValid(tp))
893
+ elog(ERROR, "cache lookup failed for attribute %d of relation %u",
894
+ attnum, relid);
895
+ att_tup = (Form_pg_attribute) GETSTRUCT(tp);
896
+ result = att_tup->attstattarget;
897
+ ReleaseSysCache(tp);
898
+ return result;
899
+}
900
901
/*
902
* get_attgenerated
903
*
src/include/utils/lsyscache.h
@@ -90,6 +90,7 @@ extern Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype,
90
int16 procnum);
91
extern char *get_attname(Oid relid, AttrNumber attnum, bool missing_ok);
92
extern AttrNumber get_attnum(Oid relid, const char *attname);
93
+extern int get_attstattarget(Oid relid, AttrNumber attnum);
94
extern char get_attgenerated(Oid relid, AttrNumber attnum);
95
extern Oid get_atttype(Oid relid, AttrNumber attnum);
96
extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
src/test/regress/expected/create_index.out
@@ -2559,6 +2559,7 @@ CREATE UNIQUE INDEX concur_exprs_index_pred ON concur_exprs_tab (c1)
2559
CREATE UNIQUE INDEX concur_exprs_index_pred_2
2560
ON concur_exprs_tab ((1 / c1))
2561
WHERE ('-H') >= (c2::TEXT) COLLATE "C";
2562
+ALTER INDEX concur_exprs_index_expr ALTER COLUMN 1 SET STATISTICS 100;
2563
ANALYZE concur_exprs_tab;
2564
SELECT starelid::regclass, count(*) FROM pg_statistic WHERE starelid IN (
2565
'concur_exprs_index_expr'::regclass,
@@ -2638,6 +2639,20 @@ SELECT starelid::regclass, count(*) FROM pg_statistic WHERE starelid IN (
2638
2639
concur_exprs_index_expr | 1
2640
(1 row)
2641
2642
+-- attstattarget should remain intact
2643
+SELECT attrelid::regclass, attnum, attstattarget
2644
+ FROM pg_attribute WHERE attrelid IN (
2645
+ 'concur_exprs_index_expr'::regclass,
2646
+ 'concur_exprs_index_pred'::regclass,
2647
+ 'concur_exprs_index_pred_2'::regclass)
2648
+ ORDER BY 'concur_exprs_index_expr'::regclass::text, attnum;
2649
+ attrelid | attnum | attstattarget
2650
+---------------------------+--------+---------------
2651
+ concur_exprs_index_expr | 1 | 100
2652
+ concur_exprs_index_pred | 1 | -1
2653
+ concur_exprs_index_pred_2 | 1 | -1
2654
+(3 rows)
2655
2656
DROP TABLE concur_exprs_tab;
2657
-- Temporary tables and on-commit actions, where CONCURRENTLY is ignored.
2658
-- ON COMMIT PRESERVE ROWS, the default.
src/test/regress/sql/create_index.sql
@@ -1079,6 +1079,7 @@ CREATE UNIQUE INDEX concur_exprs_index_pred ON concur_exprs_tab (c1)
1079
1080
1081
1082
1083
1084
1085
@@ -1103,6 +1104,13 @@ SELECT starelid::regclass, count(*) FROM pg_statistic WHERE starelid IN (
1103
1104
'concur_exprs_index_pred'::regclass,
1105
'concur_exprs_index_pred_2'::regclass)
1106
GROUP BY starelid ORDER BY starelid::regclass::text;
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116