#!/bin/bash
rm -rf repro1
initdb --no-data-checksums repro1 || exit 1
pg_ctl -D repro1 start || exit 2
psql -d postgres <<EOF
CREATE EXTENSION amcheck;
CREATE EXTENSION pageinspect;
SET default_toast_compression = 'pglz';
CREATE TABLE t (id int, v text COMPRESSION pglz);
INSERT INTO t SELECT 1, string_agg(repeat(md5(g::text), 3), '') FROM generate_series(1, 3000) g;
CHECKPOINT;
EOF

TOAST=`psql -d postgres -tA -c "SELECT reltoastrelid::regclass FROM pg_class WHERE relname='t';"`
echo "toast relation: $TOAST"
psql -d postgres -c "SELECT count(*) AS toast_chunks FROM $TOAST;"

# locate 1st byte of compressed data
read BLK LP_OFF T_HOFF LP_LEN < <(psql -d postgres -tA -F' ' -c "SELECT 0, lp_off, t_hoff, lp_len FROM heap_page_items(get_raw_page('$TOAST', 0)) WHERE t_data IS NOT NULL AND get_byte(t_data, 4) = 0 ORDER BY lp_off LIMIT 1;")
echo "chunk_seq=0 blk=$BLK lp_off=$LP_OFF t_hoff=$T_HOFF lp_len=$LP_LEN"
# 24-byte header + chunk_id(4) + chunk_seq(4) + varlena hdr(4)
OFF=$((BLK*8192 + LP_OFF + T_HOFF + 8 + 4 + 8 ))
FILE=$(psql -d postgres -tA -c "SELECT pg_relation_filepath('$TOAST');")
echo "corrupting 128 bytes of compressed data at file offset $OFF in $FILE"

pg_ctl -D repro1 stop -m fast || exit 3
dd if=/dev/zero of=repro1/$FILE bs=1 seek=$OFF count=128 conv=notrunc
pg_ctl -D repro1 start || exit 4

echo "checking for corruption:"
psql -d postgres <<EOF
SELECT * FROM verify_heapam('t', check_toast => true);   -- expected: 0 rows (blind to it)
COPY t TO '/dev/null';                                   -- expected: ERROR compressed pglz data is corrupt
SELECT length(v) FROM t;                                 -- expected: same ERROR
EOF
pg_ctl -D repro1 stop
