4040#include "utils/expandeddatum.h"
4141#include "utils/fmgroids.h"
4242#include "utils/rel.h"
43+ #include "utils/snapmgr.h"
4344#include "utils/typcache.h"
4445#include "utils/tqual.h"
4546
@@ -81,6 +82,7 @@ static int toast_open_indexes(Relation toastrel,
8182int * num_indexes );
8283static void toast_close_indexes (Relation * toastidxs ,int num_indexes ,
8384LOCKMODE lock );
85+ static void init_toast_snapshot (Snapshot toast_snapshot );
8486
8587
8688/* ----------
@@ -1665,6 +1667,7 @@ toast_delete_datum(Relation rel, Datum value)
16651667HeapTuple toasttup ;
16661668int num_indexes ;
16671669int validIndex ;
1670+ SnapshotData SnapshotToast ;
16681671
16691672if (!VARATT_IS_EXTERNAL_ONDISK (attr ))
16701673return ;
@@ -1696,8 +1699,9 @@ toast_delete_datum(Relation rel, Datum value)
16961699 * sequence or not, but since we've already locked the index we might as
16971700 * well use systable_beginscan_ordered.)
16981701 */
1702+ init_toast_snapshot (& SnapshotToast );
16991703toastscan = systable_beginscan_ordered (toastrel ,toastidxs [validIndex ],
1700- SnapshotToast ,1 ,& toastkey );
1704+ & SnapshotToast ,1 ,& toastkey );
17011705while ((toasttup = systable_getnext_ordered (toastscan ,ForwardScanDirection ))!= NULL )
17021706{
17031707/*
@@ -1730,6 +1734,7 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid)
17301734int num_indexes ;
17311735int validIndex ;
17321736Relation * toastidxs ;
1737+ SnapshotData SnapshotToast ;
17331738
17341739/* Fetch a valid index relation */
17351740validIndex = toast_open_indexes (toastrel ,
@@ -1748,9 +1753,10 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid)
17481753/*
17491754 * Is there any such chunk?
17501755 */
1756+ init_toast_snapshot (& SnapshotToast );
17511757toastscan = systable_beginscan (toastrel ,
17521758RelationGetRelid (toastidxs [validIndex ]),
1753- true,SnapshotToast ,1 ,& toastkey );
1759+ true,& SnapshotToast ,1 ,& toastkey );
17541760
17551761if (systable_getnext (toastscan )!= NULL )
17561762result = true;
@@ -1813,6 +1819,7 @@ toast_fetch_datum(struct varlena * attr)
18131819int32 chunksize ;
18141820int num_indexes ;
18151821int validIndex ;
1822+ SnapshotData SnapshotToast ;
18161823
18171824if (!VARATT_IS_EXTERNAL_ONDISK (attr ))
18181825elog (ERROR ,"toast_fetch_datum shouldn't be called for non-ondisk datums" );
@@ -1859,8 +1866,9 @@ toast_fetch_datum(struct varlena * attr)
18591866 */
18601867nextidx = 0 ;
18611868
1869+ init_toast_snapshot (& SnapshotToast );
18621870toastscan = systable_beginscan_ordered (toastrel ,toastidxs [validIndex ],
1863- SnapshotToast ,1 ,& toastkey );
1871+ & SnapshotToast ,1 ,& toastkey );
18641872while ((ttup = systable_getnext_ordered (toastscan ,ForwardScanDirection ))!= NULL )
18651873{
18661874/*
@@ -1990,6 +1998,7 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
19901998int32 chcpyend ;
19911999int num_indexes ;
19922000int validIndex ;
2001+ SnapshotData SnapshotToast ;
19932002
19942003if (!VARATT_IS_EXTERNAL_ONDISK (attr ))
19952004elog (ERROR ,"toast_fetch_datum_slice shouldn't be called for non-ondisk datums" );
@@ -2082,9 +2091,10 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
20822091 *
20832092 * The index is on (valueid, chunkidx) so they will come in order
20842093 */
2094+ init_toast_snapshot (& SnapshotToast );
20852095nextidx = startchunk ;
20862096toastscan = systable_beginscan_ordered (toastrel ,toastidxs [validIndex ],
2087- SnapshotToast ,nscankeys ,toastkey );
2097+ & SnapshotToast ,nscankeys ,toastkey );
20882098while ((ttup = systable_getnext_ordered (toastscan ,ForwardScanDirection ))!= NULL )
20892099{
20902100/*
@@ -2289,3 +2299,22 @@ toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock)
22892299index_close (toastidxs [i ],lock );
22902300pfree (toastidxs );
22912301}
2302+
2303+ /* ----------
2304+ * init_toast_snapshot
2305+ *
2306+ *Initialize an appropriate TOAST snapshot. We must use an MVCC snapshot
2307+ *to initialize the TOAST snapshot; since we don't know which one to use,
2308+ *just use the oldest one. This is safe: at worst, we will get a "snapshot
2309+ *too old" error that might have been avoided otherwise.
2310+ */
2311+ static void
2312+ init_toast_snapshot (Snapshot toast_snapshot )
2313+ {
2314+ Snapshot snapshot = GetOldestSnapshot ();
2315+
2316+ if (snapshot == NULL )
2317+ elog (ERROR ,"no known snapshots" );
2318+
2319+ InitToastSnapshot (toast_snapshot ,snapshot -> lsn ,snapshot -> whenTaken );
2320+ }