amcheck: Normalize index tuples containing uncompressed varlena
authorAlexander Korotkov <akorotkov@postgresql.org>
Sat, 23 Mar 2024 21:00:06 +0000 (23:00 +0200)
committerAlexander Korotkov <akorotkov@postgresql.org>
Sat, 23 Mar 2024 22:09:24 +0000 (00:09 +0200)
It might happen that the varlena value wasn't compressed by index_form_tuple()
due to current storage parameters.  If compression is currently enabled, we
need to compress such values to match index tuple coming from the heap.

Backpatch to all supported versions.

Discussion: https://postgr.es/m/flat/7bdbe559-d61a-4ae4-a6e1-48abdf3024cc%40postgrespro.ru
Author: Andrey Borodin
Reviewed-by: Alexander Lakhin, Michael Zhilin, Jian He, Alexander Korotkov
Backpatch-through: 12

contrib/amcheck/expected/check_btree.out
contrib/amcheck/sql/check_btree.sql
contrib/amcheck/verify_nbtree.c

index d87e71788660ff4057a930fdf1997cdac995a9d7..cf8284fe12e3070092b8fba518a758c5d4282d5a 100644 (file)
@@ -252,6 +252,16 @@ SELECT bt_index_check('varlena_bug_idx', true);
  
 (1 row)
 
+-- Also check that we compress varlena values, which were previously stored
+-- uncompressed in index.
+INSERT INTO varlena_bug VALUES (repeat('Test', 250));
+ALTER TABLE varlena_bug ALTER COLUMN v SET STORAGE extended;
+SELECT bt_index_check('varlena_bug_idx', true);
+ bt_index_check 
+----------------
+(1 row)
+
 -- cleanup
 DROP TABLE bttest_a;
 DROP TABLE bttest_b;
index b37fff0507876572311ac31f1c2d5df3e8f680fd..68bd71b064fc03db25419ff1fc3c215114212b0e 100644 (file)
@@ -158,6 +158,12 @@ x
 CREATE INDEX varlena_bug_idx on varlena_bug(v);
 SELECT bt_index_check('varlena_bug_idx', true);
 
+-- Also check that we compress varlena values, which were previously stored
+-- uncompressed in index.
+INSERT INTO varlena_bug VALUES (repeat('Test', 250));
+ALTER TABLE varlena_bug ALTER COLUMN v SET STORAGE extended;
+SELECT bt_index_check('varlena_bug_idx', true);
+
 -- cleanup
 DROP TABLE bttest_a;
 DROP TABLE bttest_b;
index e0dffd9bcca72281f07f9ceecd31a4517d352605..f71f1854e0a7bae9743c2645681dd97d24f3207a 100644 (file)
@@ -23,6 +23,7 @@
  */
 #include "postgres.h"
 
+#include "access/heaptoast.h"
 #include "access/htup_details.h"
 #include "access/nbtree.h"
 #include "access/table.h"
@@ -2981,6 +2982,18 @@ bt_normalize_tuple(BtreeCheckState *state, IndexTuple itup)
                            ItemPointerGetBlockNumber(&(itup->t_tid)),
                            ItemPointerGetOffsetNumber(&(itup->t_tid)),
                            RelationGetRelationName(state->rel))));
+       else if (!VARATT_IS_COMPRESSED(DatumGetPointer(normalized[i])) &&
+                VARSIZE(DatumGetPointer(normalized[i])) > TOAST_INDEX_TARGET &&
+                (att->attstorage == TYPSTORAGE_EXTENDED ||
+                 att->attstorage == TYPSTORAGE_MAIN))
+       {
+           /*
+            * This value will be compressed by index_form_tuple() with the
+            * current storage settings.  We may be here because this tuple
+            * was formed with different storage settings.  So, force forming.
+            */
+           formnewtup = true;
+       }
        else if (VARATT_IS_COMPRESSED(DatumGetPointer(normalized[i])))
        {
            formnewtup = true;