From 87c3b86daea53a35a9d00b3cb901205cf49a5fa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Fibich?= Date: Wed, 11 May 2022 09:41:48 +0200 Subject: [PATCH 1/3] #33: Fix trigger if table contains column with non-equality type for ignore_unchanged_values=false --- README.md | 4 +++- versioning_function.sql | 8 +++++--- versioning_function_nochecks.sql | 10 ++++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3087f14..c760178 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![](https://github.com/nearform/temporal_tables/workflows/ci/badge.svg) -_Version: 0.4.0_ +_Version: 0.4.1_ This is an attempt to rewrite the postgresql [temporal_tables](https://github.com/arkhipov/temporal_tables) extension in PL/pgSQL, without the need for external c extension. @@ -111,6 +111,8 @@ name | state | sys_period ### Ignore updates without actual change +**NOTE: This feature does not work for tables with columns with types that does not support equality operator (e.g. PostGIS types, JSON types, etc.).** + By default this extension creates a record in the history table for every update that occurs in the versioned table, regardless of any change actually happening. We added a fourth paramater to the trigger to change this behaviour and only record updates that result in an actual change. diff --git a/versioning_function.sql b/versioning_function.sql index 6c95930..5228fd9 100644 --- a/versioning_function.sql +++ b/versioning_function.sql @@ -14,7 +14,7 @@ DECLARE holder2 record; pg_version integer; BEGIN - -- version 0.4.0 + -- version 0.4.1 IF TG_WHEN != 'BEFORE' OR TG_LEVEL != 'ROW' THEN RAISE TRIGGER_PROTOCOL_VIOLATED USING @@ -36,8 +36,10 @@ BEGIN history_table := TG_ARGV[1]; ignore_unchanged_values := TG_ARGV[3]; - IF ignore_unchanged_values AND TG_OP = 'UPDATE' AND NEW IS NOT DISTINCT FROM OLD THEN - RETURN OLD; + IF ignore_unchanged_values AND TG_OP = 'UPDATE' THEN + IF NEW IS NOT DISTINCT FROM OLD THEN + RETURN OLD; + END IF; END IF; -- check if sys_period exists on original table diff --git a/versioning_function_nochecks.sql b/versioning_function_nochecks.sql index 9577d20..be3debb 100644 --- a/versioning_function_nochecks.sql +++ b/versioning_function_nochecks.sql @@ -11,14 +11,16 @@ DECLARE transaction_info txid_snapshot; existing_range tstzrange; BEGIN - -- version 0.4.0 + -- version 0.4.1 sys_period := TG_ARGV[0]; history_table := TG_ARGV[1]; ignore_unchanged_values := TG_ARGV[3]; - IF ignore_unchanged_values AND TG_OP = 'UPDATE' AND NEW IS NOT DISTINCT FROM OLD THEN - RETURN OLD; + IF ignore_unchanged_values AND TG_OP = 'UPDATE' THEN + IF NEW IS NOT DISTINCT FROM OLD THEN + RETURN OLD; + END IF; END IF; IF TG_OP = 'UPDATE' OR TG_OP = 'DELETE' THEN @@ -81,4 +83,4 @@ BEGIN RETURN OLD; END; -$$ LANGUAGE plpgsql; \ No newline at end of file +$$ LANGUAGE plpgsql; From 349b97296915ad48d0840abbf4e292cf46dc2137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Fibich?= Date: Wed, 11 May 2022 10:24:33 +0200 Subject: [PATCH 2/3] #33: Add positive and negative tests --- test/expected/non_equality_types.out | 7 +++++++ test/expected/non_equality_types_unchanged_values.out | 9 +++++++++ test/runTest.sh | 5 +++-- test/runTestNochecks.sh | 6 ++++-- test/sql/non_equality_types.sql | 11 +++++++++++ test/sql/non_equality_types_unchanged_values.sql | 11 +++++++++++ 6 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 test/expected/non_equality_types.out create mode 100644 test/expected/non_equality_types_unchanged_values.out create mode 100644 test/sql/non_equality_types.sql create mode 100644 test/sql/non_equality_types_unchanged_values.sql diff --git a/test/expected/non_equality_types.out b/test/expected/non_equality_types.out new file mode 100644 index 0000000..03bc934 --- /dev/null +++ b/test/expected/non_equality_types.out @@ -0,0 +1,7 @@ +SET client_min_messages TO error +CREATE TABLE non_equality_types (json json, sys_period tstzrange) +CREATE TRIGGER versioning_trigger +BEFORE INSERT OR UPDATE OR DELETE ON non_equality_types +FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'non_equality_types', false) +INSERT INTO non_equality_types VALUES ('{"a":1}'::json) +UPDATE non_equality_types SET json = '{"a":2}'::json WHERE 1=1 diff --git a/test/expected/non_equality_types_unchanged_values.out b/test/expected/non_equality_types_unchanged_values.out new file mode 100644 index 0000000..f8d6519 --- /dev/null +++ b/test/expected/non_equality_types_unchanged_values.out @@ -0,0 +1,9 @@ +SET client_min_messages TO error +CREATE TABLE non_equality_types_unchanged_values (json json, sys_period tstzrange) +CREATE TRIGGER versioning_trigger +BEFORE INSERT OR UPDATE OR DELETE ON non_equality_types_unchanged_values +FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'non_equality_types_unchanged_values', false, true) +INSERT INTO non_equality_types_unchanged_values VALUES ('{"a":1}'::json) +UPDATE non_equality_types_unchanged_values SET json = '{"a":2}'::json WHERE 1=1 +ERROR: could not identify an equality operator for type json +CONTEXT: PL/pgSQL function versioning() line 39 at IF diff --git a/test/runTest.sh b/test/runTest.sh index 6e706fa..0e1b7db 100644 --- a/test/runTest.sh +++ b/test/runTest.sh @@ -9,7 +9,8 @@ TESTS=" no_history_table no_history_system_period no_system_period invalid_system_period_values invalid_system_period invalid_types versioning upper_case structure combinations - different_schema unchanged_values" + different_schema unchanged_values + non_equality_types non_equality_types_unchanged_values" for name in $TESTS; do echo "" @@ -20,4 +21,4 @@ for name in $TESTS; do done -psql -q -c "drop database temporal_tables_test;" \ No newline at end of file +psql -q -c "drop database temporal_tables_test;" diff --git a/test/runTestNochecks.sh b/test/runTestNochecks.sh index d1a11be..2a941c6 100644 --- a/test/runTestNochecks.sh +++ b/test/runTestNochecks.sh @@ -5,7 +5,9 @@ psql temporal_tables_test -q -f versioning_function_nochecks.sql mkdir -p test/result -TESTS="versioning upper_case structure combinations different_schema unchanged_values" +TESTS=" + versioning upper_case structure combinations different_schema unchanged_values + non_equality_types non_equality_types_unchanged_values" for name in $TESTS; do echo "" @@ -16,4 +18,4 @@ for name in $TESTS; do done -psql -q -c "drop database temporal_tables_test;" \ No newline at end of file +psql -q -c "drop database temporal_tables_test;" diff --git a/test/sql/non_equality_types.sql b/test/sql/non_equality_types.sql new file mode 100644 index 0000000..e00ea36 --- /dev/null +++ b/test/sql/non_equality_types.sql @@ -0,0 +1,11 @@ +SET client_min_messages TO error; + +CREATE TABLE non_equality_types (json json, sys_period tstzrange); + +CREATE TRIGGER versioning_trigger +BEFORE INSERT OR UPDATE OR DELETE ON non_equality_types +FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'non_equality_types', false); + +INSERT INTO non_equality_types VALUES ('{"a":1}'::json); + +UPDATE non_equality_types SET json = '{"a":2}'::json WHERE 1=1; diff --git a/test/sql/non_equality_types_unchanged_values.sql b/test/sql/non_equality_types_unchanged_values.sql new file mode 100644 index 0000000..e05e9b1 --- /dev/null +++ b/test/sql/non_equality_types_unchanged_values.sql @@ -0,0 +1,11 @@ +SET client_min_messages TO error; + +CREATE TABLE non_equality_types_unchanged_values (json json, sys_period tstzrange); + +CREATE TRIGGER versioning_trigger +BEFORE INSERT OR UPDATE OR DELETE ON non_equality_types_unchanged_values +FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'non_equality_types_unchanged_values', false, true); + +INSERT INTO non_equality_types_unchanged_values VALUES ('{"a":1}'::json); + +UPDATE non_equality_types_unchanged_values SET json = '{"a":2}'::json WHERE 1=1; From 8b5095fd6ab5437231ce74f8794ad91b949c2cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Fibich?= Date: Tue, 25 Jul 2023 17:31:50 +0200 Subject: [PATCH 3/3] Fix invalid conflict resolving. --- test/runTestNochecks.sh | 1 - versioning_function_nochecks.sql | 7 ------- 2 files changed, 8 deletions(-) diff --git a/test/runTestNochecks.sh b/test/runTestNochecks.sh index 8eb992c..76a5b96 100644 --- a/test/runTestNochecks.sh +++ b/test/runTestNochecks.sh @@ -10,7 +10,6 @@ TESTS=" non_equality_types non_equality_types_unchanged_values unchanged_version_values " ->>>>>>> upstream/master for name in $TESTS; do echo "" diff --git a/versioning_function_nochecks.sql b/versioning_function_nochecks.sql index f0b47a4..a2847c6 100644 --- a/versioning_function_nochecks.sql +++ b/versioning_function_nochecks.sql @@ -14,23 +14,16 @@ DECLARE newVersion record; oldVersion record; BEGIN -<<<<<<< HEAD - -- version 0.4.1 -======= ->>>>>>> upstream/master sys_period := TG_ARGV[0]; history_table := TG_ARGV[1]; ignore_unchanged_values := TG_ARGV[3]; -<<<<<<< HEAD IF ignore_unchanged_values AND TG_OP = 'UPDATE' THEN IF NEW IS NOT DISTINCT FROM OLD THEN RETURN OLD; END IF; END IF; -======= ->>>>>>> upstream/master IF TG_OP = 'UPDATE' OR TG_OP = 'DELETE' THEN -- Ignore rows already modified in the current transaction