Skip to content

Commit 8ce9ae5

Browse files
author
Antonin Houska
committed
Set values of dropped columns to NULL.
There's no reason to copy the data that the applications won't see anymore.
1 parent 7969e2d commit 8ce9ae5

File tree

1 file changed

+66
-5
lines changed

1 file changed

+66
-5
lines changed

pg_squeeze.c

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ static void resolve_index_tablepaces(TablespaceInfo *tbsp_info,
119119
static void perform_initial_load(Relation rel_src, RangeVar *cluster_idx_rv,
120120
Snapshot snap_hist, Relation rel_dst,
121121
LogicalDecodingContext *ctx);
122+
static bool has_dropped_attribute(Relation rel);
122123
static Oid create_transient_table(CatalogState *cat_state, TupleDesc tup_desc,
123124
Oid tablespace, Oid relowner);
124125
static Oid *build_transient_indexes(Relation rel_dst, Relation rel_src,
@@ -896,6 +897,13 @@ check_prerequisites(Relation rel)
896897
{
897898
Form_pg_class form = RelationGetForm(rel);
898899

900+
/*
901+
* The extension is not generic enough to handle AMs other than "heap".
902+
*/
903+
if (form->relam != HEAP_TABLE_AM_OID)
904+
ereport(ERROR,
905+
(errmsg("pg_squeeze only supports the \"heap\" access method")));
906+
899907
/* Check the relation first. */
900908
if (form->relkind == RELKIND_PARTITIONED_TABLE)
901909
ereport(ERROR,
@@ -1970,6 +1978,10 @@ perform_initial_load(Relation rel_src, RangeVar *cluster_idx_rv,
19701978
old_cxt;
19711979
XLogRecPtr end_of_wal_prev = InvalidXLogRecPtr;
19721980
DecodingOutputState *dstate;
1981+
bool has_dropped_attr;
1982+
Datum values[MaxTupleAttributeNumber];
1983+
bool isnull[MaxTupleAttributeNumber];
1984+
19731985

19741986
/*
19751987
* Also remember that the WAL records created during the load should not
@@ -2058,6 +2070,9 @@ perform_initial_load(Relation rel_src, RangeVar *cluster_idx_rv,
20582070
/* Expect many insertions. */
20592071
bistate = GetBulkInsertState();
20602072

2073+
/* Has the relation at least one dropped attribute? */
2074+
has_dropped_attr = has_dropped_attribute(rel_src);
2075+
20612076
/*
20622077
* The processing can take many iterations. In case any data manipulation
20632078
* below leaked, try to defend against out-of-memory conditions by using a
@@ -2078,7 +2093,7 @@ perform_initial_load(Relation rel_src, RangeVar *cluster_idx_rv,
20782093
/* Sorting cannot be split into batches. */
20792094
for (i = 0;; i++)
20802095
{
2081-
bool flattened = false;
2096+
bool have_tup_copy = false;
20822097

20832098
/*
20842099
* While tuplesort is responsible for not exceeding
@@ -2150,15 +2165,43 @@ perform_initial_load(Relation rel_src, RangeVar *cluster_idx_rv,
21502165
{
21512166
tup_in = toast_flatten_tuple(tup_in,
21522167
RelationGetDescr(rel_src));
2153-
flattened = true;
2168+
have_tup_copy = true;
2169+
}
2170+
2171+
/*
2172+
* If at least one attribute has been dropped, we need to deform /
2173+
* form the tuple to make sure that set the values of the dropped
2174+
* attribute(s) are NULL. (Unfortunately we don't know if the
2175+
* table was already squeezed since the last ALTER TABLE ... DROP
2176+
* COLUMN ... command.)
2177+
*/
2178+
if (has_dropped_attr)
2179+
{
2180+
HeapTuple tup_orig = tup_in;
2181+
TupleDesc tup_desc = RelationGetDescr(rel_src);
2182+
int i;
2183+
2184+
heap_deform_tuple(tup_in, tup_desc, values, isnull);
2185+
2186+
for (i = 0; i < tup_desc->natts; i++)
2187+
{
2188+
if (TupleDescAttr(tup_desc, i)->attisdropped)
2189+
isnull[i] = true;
2190+
}
2191+
2192+
tup_in = heap_form_tuple(tup_desc, values, isnull);
2193+
if (have_tup_copy)
2194+
/* tup_in is a flat copy. We do not want two copies. */
2195+
heap_freetuple(tup_orig);
2196+
have_tup_copy = true;
21542197
}
21552198

21562199
if (use_sort)
21572200
{
21582201
tuplesort_putheaptuple(tuplesort, tup_in);
21592202
/* tuplesort should have copied the tuple. */
2160-
if (flattened)
2161-
pfree(tup_in);
2203+
if (have_tup_copy)
2204+
heap_freetuple(tup_in);
21622205
}
21632206
else
21642207
{
@@ -2204,7 +2247,7 @@ perform_initial_load(Relation rel_src, RangeVar *cluster_idx_rv,
22042247
}
22052248
}
22062249

2207-
if (!flattened)
2250+
if (!have_tup_copy)
22082251
tup_in = heap_copytuple(tup_in);
22092252

22102253
/*
@@ -2366,6 +2409,24 @@ perform_initial_load(Relation rel_src, RangeVar *cluster_idx_rv,
23662409
elog(DEBUG1, "pg_squeeze: the initial load completed");
23672410
}
23682411

2412+
/*
2413+
* Check if relation has at least one dropped attribute.
2414+
*/
2415+
static bool
2416+
has_dropped_attribute(Relation rel)
2417+
{
2418+
TupleDesc tup_desc = RelationGetDescr(rel);
2419+
2420+
for (int i = 0; i < tup_desc->natts; i++)
2421+
{
2422+
Form_pg_attribute attr = &tup_desc->attrs[i];
2423+
2424+
if (attr->attisdropped)
2425+
return true;
2426+
}
2427+
2428+
return false;
2429+
}
23692430

23702431
/*
23712432
* Create a table into which we'll copy the contents of the source table, as

0 commit comments

Comments
 (0)