Skip to content

Commit f7d7383

Browse files
committed
Hardcode SHA-256 expected values and add PostgreSQL SHA2 test
SHA-256 checksums captured from MySQL 8.0 CI run, verified consistent across 9.0.1. Added PostgreSQL SHA-256 test using pgcrypto's encode(digest(..., 'sha256'), 'hex'). Both use the same expected values as MySQL, ensuring cross-database checksum compatibility.
1 parent af1e75c commit f7d7383

3 files changed

Lines changed: 112 additions & 6 deletions

File tree

.github/workflows/ci-postgresql.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,18 @@ jobs:
9494
fi
9595
echo "SHA OK ($sha_ok matches)"
9696
97+
- name: Test SHA2 integrity
98+
run: |
99+
SBDIR=$(ls -d ~/sandboxes/pg_sandbox_*)
100+
$SBDIR/use < postgresql/test_employees_sha2.sql > /tmp/test_sha2.txt 2>&1
101+
cat /tmp/test_sha2.txt
102+
sha2_ok=$(grep -iw ok /tmp/test_sha2.txt | wc -l | tr -d ' \t')
103+
if [ "$sha2_ok" != "8" ]; then
104+
echo "SHA2 FAIL - expected 8 OK - found $sha2_ok"
105+
exit 1
106+
fi
107+
echo "SHA2 OK ($sha2_ok matches)"
108+
97109
- name: Load objects (stored procedures/functions)
98110
run: |
99111
SBDIR=$(ls -d ~/sandboxes/pg_sandbox_*)

postgresql/test_employees_sha2.sql

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
-- Test employees database integrity using SHA-256 checksums
2+
-- PostgreSQL version using pgcrypto extension
3+
4+
\connect employees
5+
6+
SELECT 'TESTING INSTALLATION' AS info;
7+
8+
CREATE EXTENSION IF NOT EXISTS pgcrypto;
9+
10+
DROP TABLE IF EXISTS expected_values, found_values;
11+
CREATE TABLE expected_values (
12+
table_name VARCHAR(30) NOT NULL PRIMARY KEY,
13+
recs INT NOT NULL,
14+
crc_sha2 VARCHAR(100) NOT NULL
15+
);
16+
17+
CREATE TABLE found_values (LIKE expected_values);
18+
19+
-- Expected SHA-256 checksums (same values as MySQL's SHA2(..., 256))
20+
INSERT INTO expected_values VALUES
21+
('employees', 300024, '21f5d003842f24853e251d3d5116798bafe257ec3d1bb448b5365b68deaabbf4'),
22+
('departments', 9, '377c5d727383a32633e2973f8e3411beffe29e2f4cc297c586fa6b24aa7df9ba'),
23+
('dept_manager', 24, '3a4e69723deec413a7d8a4f5ce55013830303fa617b6380ed2b0fd2d48b1c768'),
24+
('dept_emp', 331603, '34548ee9989dd4d5e065168b43249c8d3eb48bfbbfb3f2fc1cf01be6658f6a75'),
25+
('titles', 443308, 'a9e940ef9ba1029a8f0356fdbe495430bedc59eec5ceb4f71e0cc35ddcbf9980'),
26+
('salaries', 2844047, '4e99e691a9ea98fefc0b4fec8ca4e758baeefba2967bd8d6474810a9a5f6e729');
27+
SELECT table_name, recs AS expected_records, crc_sha2 AS expected_crc FROM expected_values;
28+
29+
-- Helper function: computes incremental SHA-256 over rows returned by query.
30+
-- The query must return a single column named "row_text".
31+
-- This replicates MySQL's @crc := SHA2(CONCAT_WS('#', @crc, ...), 256)
32+
-- by using crc := encode(digest(crc || '#' || row_text, 'sha256'), 'hex')
33+
CREATE OR REPLACE FUNCTION compute_table_sha256(p_query TEXT)
34+
RETURNS TEXT
35+
LANGUAGE plpgsql
36+
AS $$
37+
DECLARE
38+
crc TEXT := '';
39+
r RECORD;
40+
BEGIN
41+
FOR r IN EXECUTE p_query LOOP
42+
crc := encode(digest(crc || '#' || r.row_text, 'sha256'), 'hex');
43+
END LOOP;
44+
RETURN crc;
45+
END;
46+
$$;
47+
48+
-- Compute checksums for each table
49+
INSERT INTO found_values VALUES
50+
('employees',
51+
(SELECT COUNT(*) FROM employees),
52+
(SELECT compute_table_sha256($$SELECT CONCAT_WS('#', emp_no, birth_date, first_name, last_name, gender, hire_date) AS row_text FROM employees ORDER BY emp_no$$))),
53+
54+
('departments',
55+
(SELECT COUNT(*) FROM departments),
56+
(SELECT compute_table_sha256($$SELECT CONCAT_WS('#', dept_no, dept_name) AS row_text FROM departments ORDER BY dept_no$$))),
57+
58+
('dept_manager',
59+
(SELECT COUNT(*) FROM dept_manager),
60+
(SELECT compute_table_sha256($$SELECT CONCAT_WS('#', dept_no, emp_no, from_date, to_date) AS row_text FROM dept_manager ORDER BY dept_no, emp_no$$))),
61+
62+
('dept_emp',
63+
(SELECT COUNT(*) FROM dept_emp),
64+
(SELECT compute_table_sha256($$SELECT CONCAT_WS('#', dept_no, emp_no, from_date, to_date) AS row_text FROM dept_emp ORDER BY dept_no, emp_no$$))),
65+
66+
('titles',
67+
(SELECT COUNT(*) FROM titles),
68+
(SELECT compute_table_sha256($$SELECT CONCAT_WS('#', emp_no, title, from_date, to_date) AS row_text FROM titles ORDER BY emp_no, title, from_date$$))),
69+
70+
('salaries',
71+
(SELECT COUNT(*) FROM salaries),
72+
(SELECT compute_table_sha256($$SELECT CONCAT_WS('#', emp_no, salary, from_date, to_date) AS row_text FROM salaries ORDER BY emp_no, from_date, to_date$$)));
73+
74+
SELECT table_name, recs AS found_records, crc_sha2 AS found_crc FROM found_values;
75+
76+
SELECT
77+
e.table_name,
78+
CASE WHEN e.recs=f.recs THEN 'OK' ELSE 'not ok' END AS records_match,
79+
CASE WHEN e.crc_sha2=f.crc_sha2 THEN 'ok' ELSE 'not ok' END AS crc_match
80+
FROM
81+
expected_values e INNER JOIN found_values f USING (table_name);
82+
83+
SELECT 'CRC' AS summary,
84+
CASE WHEN NOT EXISTS (
85+
SELECT 1 FROM expected_values e JOIN found_values f ON e.table_name=f.table_name WHERE f.crc_sha2 != e.crc_sha2
86+
) THEN 'OK' ELSE 'FAIL' END AS result
87+
UNION ALL
88+
SELECT 'count',
89+
CASE WHEN NOT EXISTS (
90+
SELECT 1 FROM expected_values e JOIN found_values f ON e.table_name=f.table_name WHERE f.recs != e.recs
91+
) THEN 'OK' ELSE 'FAIL' END;
92+
93+
DROP FUNCTION compute_table_sha256(TEXT);
94+
DROP TABLE expected_values, found_values;

test_employees_sha2.sql

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ CREATE TABLE found_values (LIKE expected_values);
1818

1919
-- Expected SHA-256 checksums (computed from the canonical data set)
2020
INSERT INTO `expected_values` VALUES
21-
('employees', 300024, 'PLACEHOLDER'),
22-
('departments', 9, 'PLACEHOLDER'),
23-
('dept_manager', 24, 'PLACEHOLDER'),
24-
('dept_emp', 331603, 'PLACEHOLDER'),
25-
('titles', 443308, 'PLACEHOLDER'),
26-
('salaries', 2844047, 'PLACEHOLDER');
21+
('employees', 300024, '21f5d003842f24853e251d3d5116798bafe257ec3d1bb448b5365b68deaabbf4'),
22+
('departments', 9, '377c5d727383a32633e2973f8e3411beffe29e2f4cc297c586fa6b24aa7df9ba'),
23+
('dept_manager', 24, '3a4e69723deec413a7d8a4f5ce55013830303fa617b6380ed2b0fd2d48b1c768'),
24+
('dept_emp', 331603, '34548ee9989dd4d5e065168b43249c8d3eb48bfbbfb3f2fc1cf01be6658f6a75'),
25+
('titles', 443308, 'a9e940ef9ba1029a8f0356fdbe495430bedc59eec5ceb4f71e0cc35ddcbf9980'),
26+
('salaries', 2844047, '4e99e691a9ea98fefc0b4fec8ca4e758baeefba2967bd8d6474810a9a5f6e729');
2727
SELECT table_name, recs AS expected_records, crc_sha2 AS expected_crc FROM expected_values;
2828

2929
DROP TABLE IF EXISTS tchecksum;

0 commit comments

Comments
 (0)