|
| 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; |
0 commit comments