|
32 | 32 | #include "access/htup_details.h"
|
33 | 33 | #include "access/multixact.h"
|
34 | 34 | #include "access/tableam.h"
|
| 35 | +#include "access/toasterapi.h" |
35 | 36 | #include "access/transam.h"
|
36 | 37 | #include "access/xact.h"
|
37 | 38 | #include "catalog/namespace.h"
|
@@ -1832,6 +1833,76 @@ vac_truncate_clog(TransactionId frozenXID,
|
1832 | 1833 | LWLockRelease(WrapLimitsVacuumLock);
|
1833 | 1834 | }
|
1834 | 1835 |
|
| 1836 | +static Oid |
| 1837 | +get_main_rel_for_toast_rel(Oid toastrelid) |
| 1838 | +{ |
| 1839 | + Relation class_rel = table_open(RelationRelationId, AccessShareLock); |
| 1840 | + SysScanDesc scan = systable_beginscan(class_rel, InvalidOid, false, |
| 1841 | + NULL, 0, NULL); |
| 1842 | + HeapTuple tup; |
| 1843 | + Oid relid = InvalidOid; |
| 1844 | + |
| 1845 | + while ((tup = systable_getnext(scan)) != NULL) |
| 1846 | + { |
| 1847 | + Form_pg_class relform = (Form_pg_class) GETSTRUCT(tup); |
| 1848 | + |
| 1849 | + if (relform->reltoastrelid == toastrelid) |
| 1850 | + { |
| 1851 | + relid = relform->oid; |
| 1852 | + break; |
| 1853 | + } |
| 1854 | + } |
| 1855 | + |
| 1856 | + systable_endscan(scan); |
| 1857 | + table_close(class_rel, NoLock); |
| 1858 | + |
| 1859 | + if (!OidIsValid(relid)) |
| 1860 | + elog(ERROR, "could not find main relation for TOAST relation %u", |
| 1861 | + toastrelid); |
| 1862 | + |
| 1863 | + return relid; |
| 1864 | +} |
| 1865 | + |
| 1866 | +static bool |
| 1867 | +toastrel_vacuum_full_is_disabled(Relation toastrel, VacuumParams *params) |
| 1868 | +{ |
| 1869 | + Oid mainrelid = get_main_rel_for_toast_rel(RelationGetRelid(toastrel)); |
| 1870 | + Relation mainrel = vacuum_open_relation(mainrelid, NULL, params->options, |
| 1871 | + params->log_min_duration >= 0, |
| 1872 | + AccessShareLock); |
| 1873 | + TupleDesc maindesc; |
| 1874 | + bool res = false; |
| 1875 | + |
| 1876 | + if (!mainrel) |
| 1877 | + return true; |
| 1878 | + |
| 1879 | + maindesc = RelationGetDescr(mainrel); |
| 1880 | + |
| 1881 | + for (int i = 0; i < maindesc->natts; i++) |
| 1882 | + { |
| 1883 | + Oid toasterid = TupleDescAttr(maindesc, i)->atttoaster; |
| 1884 | + |
| 1885 | + if (OidIsValid(toasterid)) |
| 1886 | + { |
| 1887 | + TsrRoutine *toaster = SearchTsrCache(toasterid); |
| 1888 | + |
| 1889 | + if (toaster->relinfo && |
| 1890 | + (toaster->relinfo(toastrel) & TOASTREL_VACUUM_FULL_DISABLED)) |
| 1891 | + { |
| 1892 | + ereport(WARNING, |
| 1893 | + (errmsg("skipping \"%s\" --- %s is disabled by toaster", |
| 1894 | + RelationGetRelationName(toastrel), |
| 1895 | + "VACUUM FULL"))); |
| 1896 | + res = true; |
| 1897 | + break; |
| 1898 | + } |
| 1899 | + } |
| 1900 | + } |
| 1901 | + |
| 1902 | + relation_close(mainrel, AccessShareLock); |
| 1903 | + |
| 1904 | + return res; |
| 1905 | +} |
1835 | 1906 |
|
1836 | 1907 | /*
|
1837 | 1908 | * vacuum_rel() -- vacuum one heap relation
|
@@ -1997,6 +2068,20 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
|
1997 | 2068 | return true;
|
1998 | 2069 | }
|
1999 | 2070 |
|
| 2071 | + /* |
| 2072 | + * Check if VACUUM FULL of TOAST relation is disabled by the |
| 2073 | + * toasters. |
| 2074 | + */ |
| 2075 | + if (rel->rd_rel->relkind == RELKIND_TOASTVALUE && |
| 2076 | + (params->options & VACOPT_FULL) != 0 && |
| 2077 | + toastrel_vacuum_full_is_disabled(rel, params)) |
| 2078 | + { |
| 2079 | + relation_close(rel, lmode); |
| 2080 | + PopActiveSnapshot(); |
| 2081 | + CommitTransactionCommand(); |
| 2082 | + return false; |
| 2083 | + } |
| 2084 | + |
2000 | 2085 | /*
|
2001 | 2086 | * Get a session-level lock too. This will protect our access to the
|
2002 | 2087 | * relation across multiple transactions, so that we can vacuum the
|
|
0 commit comments