diff options
author | Tom Lane | 2025-03-16 17:45:48 +0000 |
---|---|---|
committer | Tom Lane | 2025-03-16 17:45:48 +0000 |
commit | 44890442398cf3a65230d53167e61905d2b0d348 (patch) | |
tree | 1cb9b611315da7ac77b46aef74addc5918cb22d7 | |
parent | 682c5be25c28192c56e9d5e2a9ca14673a2fcf4b (diff) |
contrib/isn: Make weak mode a GUC setting, and fix related functions.
isn's weak mode used to be a simple static variable, settable only
via the isn_weak(boolean) function. This wasn't optimal, as this
means it doesn't respect transactions nor respond to RESET ALL.
This patch makes isn.weak a GUC parameter instead, so that
it acts like any other user-settable parameter.
The isn_weak() functions are retained for backwards compatibility.
But we must fix their volatility markings: they were marked IMMUTABLE
which is surely incorrect, and PARALLEL RESTRICTED which isn't right
for GUC-related functions either. Mark isn_weak(boolean) as
VOLATILE and PARALLEL UNSAFE, matching set_config(). Mark isn_weak()
as STABLE and PARALLEL SAFE, matching current_setting().
Reported-by: Viktor Holmberg <[email protected]>
Diagnosed-by: Daniel Gustafsson <[email protected]>
Author: Viktor Holmberg <[email protected]>
Reviewed-by: Tom Lane <[email protected]>
Discussion: https://postgr.es/m/790bc1f9-74dc-4b50-94d2-8147315b1556@Spark
-rw-r--r-- | contrib/isn/Makefile | 4 | ||||
-rw-r--r-- | contrib/isn/expected/isn.out | 44 | ||||
-rw-r--r-- | contrib/isn/isn--1.2--1.3.sql | 7 | ||||
-rw-r--r-- | contrib/isn/isn.c | 27 | ||||
-rw-r--r-- | contrib/isn/isn.control | 2 | ||||
-rw-r--r-- | contrib/isn/isn.h | 1 | ||||
-rw-r--r-- | contrib/isn/meson.build | 3 | ||||
-rw-r--r-- | contrib/isn/sql/isn.sql | 13 | ||||
-rw-r--r-- | doc/src/sgml/isn.sgml | 71 |
9 files changed, 137 insertions, 35 deletions
diff --git a/contrib/isn/Makefile b/contrib/isn/Makefile index 1037506c705..bfe8977bb64 100644 --- a/contrib/isn/Makefile +++ b/contrib/isn/Makefile @@ -3,8 +3,8 @@ MODULES = isn EXTENSION = isn -DATA = isn--1.1.sql isn--1.1--1.2.sql \ - isn--1.0--1.1.sql +DATA = isn--1.0--1.1.sql isn--1.1.sql \ + isn--1.1--1.2.sql isn--1.2--1.3.sql PGFILEDESC = "isn - data types for international product numbering standards" # the other .h files are data tables, we don't install those diff --git a/contrib/isn/expected/isn.out b/contrib/isn/expected/isn.out index 2f05b7eb861..c533768d926 100644 --- a/contrib/isn/expected/isn.out +++ b/contrib/isn/expected/isn.out @@ -280,6 +280,50 @@ FROM (VALUES ('9780123456786', 'UPC'), (3 rows) -- +-- test weak mode +-- +SELECT '2222222222221'::ean13; -- fail +ERROR: invalid check digit for EAN13 number: "2222222222221", should be 2 +LINE 1: SELECT '2222222222221'::ean13; + ^ +SET isn.weak TO TRUE; +SELECT '2222222222221'::ean13; + ean13 +------------------ + 222-222222222-2! +(1 row) + +SELECT is_valid('2222222222221'::ean13); + is_valid +---------- + f +(1 row) + +SELECT make_valid('2222222222221'::ean13); + make_valid +----------------- + 222-222222222-2 +(1 row) + +SELECT isn_weak(); -- backwards-compatibility wrappers for accessing the GUC + isn_weak +---------- + t +(1 row) + +SELECT isn_weak(false); + isn_weak +---------- + f +(1 row) + +SHOW isn.weak; + isn.weak +---------- + off +(1 row) + +-- -- cleanup -- DROP EXTENSION isn; diff --git a/contrib/isn/isn--1.2--1.3.sql b/contrib/isn/isn--1.2--1.3.sql new file mode 100644 index 00000000000..a8e30ff44fb --- /dev/null +++ b/contrib/isn/isn--1.2--1.3.sql @@ -0,0 +1,7 @@ +/* contrib/isn/isn--1.2--1.3.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION isn UPDATE TO '1.3'" to load this file. \quit + +ALTER FUNCTION isn_weak(boolean) VOLATILE PARALLEL UNSAFE; +ALTER FUNCTION isn_weak() STABLE PARALLEL SAFE; diff --git a/contrib/isn/isn.c b/contrib/isn/isn.c index db765ee490d..5783c188737 100644 --- a/contrib/isn/isn.c +++ b/contrib/isn/isn.c @@ -21,6 +21,7 @@ #include "UPC.h" #include "fmgr.h" #include "isn.h" +#include "utils/guc.h" PG_MODULE_MAGIC; @@ -39,6 +40,7 @@ enum isn_type static const char *const isn_names[] = {"EAN13/UPC/ISxN", "EAN13/UPC/ISxN", "EAN13", "ISBN", "ISMN", "ISSN", "UPC"}; +/* GUC value */ static bool g_weak = false; @@ -929,6 +931,20 @@ _PG_init(void) if (!check_table(UPC_range, UPC_index)) elog(ERROR, "UPC failed check"); } + + /* Define a GUC variable for weak mode. */ + DefineCustomBoolVariable("isn.weak", + "Accept input with invalid ISN check digits.", + NULL, + &g_weak, + false, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); + + MarkGUCPrefixReserved("isn"); } /* isn_out @@ -1109,17 +1125,16 @@ make_valid(PG_FUNCTION_ARGS) /* this function temporarily sets weak input flag * (to lose the strictness of check digit acceptance) - * It's a helper function, not intended to be used!! */ PG_FUNCTION_INFO_V1(accept_weak_input); Datum accept_weak_input(PG_FUNCTION_ARGS) { -#ifdef ISN_WEAK_MODE - g_weak = PG_GETARG_BOOL(0); -#else - /* function has no effect */ -#endif /* ISN_WEAK_MODE */ + bool newvalue = PG_GETARG_BOOL(0); + + (void) set_config_option("isn.weak", newvalue ? "on" : "off", + PGC_USERSET, PGC_S_SESSION, + GUC_ACTION_SET, true, 0, false); PG_RETURN_BOOL(g_weak); } diff --git a/contrib/isn/isn.control b/contrib/isn/isn.control index 1cb5e2b2340..e7daea52b84 100644 --- a/contrib/isn/isn.control +++ b/contrib/isn/isn.control @@ -1,6 +1,6 @@ # isn extension comment = 'data types for international product numbering standards' -default_version = '1.2' +default_version = '1.3' module_pathname = '$libdir/isn' relocatable = true trusted = true diff --git a/contrib/isn/isn.h b/contrib/isn/isn.h index 038eb362c39..399896ad417 100644 --- a/contrib/isn/isn.h +++ b/contrib/isn/isn.h @@ -18,7 +18,6 @@ #include "fmgr.h" #undef ISN_DEBUG -#define ISN_WEAK_MODE /* * uint64 is the internal storage format for ISNs. diff --git a/contrib/isn/meson.build b/contrib/isn/meson.build index fbbeeff01bb..39cf781684e 100644 --- a/contrib/isn/meson.build +++ b/contrib/isn/meson.build @@ -19,8 +19,9 @@ contrib_targets += isn install_data( 'isn.control', 'isn--1.0--1.1.sql', - 'isn--1.1--1.2.sql', 'isn--1.1.sql', + 'isn--1.1--1.2.sql', + 'isn--1.2--1.3.sql', kwargs: contrib_data_args, ) diff --git a/contrib/isn/sql/isn.sql b/contrib/isn/sql/isn.sql index 2c2ea077d1e..043e5580b0d 100644 --- a/contrib/isn/sql/isn.sql +++ b/contrib/isn/sql/isn.sql @@ -121,6 +121,19 @@ FROM (VALUES ('9780123456786', 'UPC'), LATERAL pg_input_error_info(a.str, a.typ) as errinfo; -- +-- test weak mode +-- +SELECT '2222222222221'::ean13; -- fail +SET isn.weak TO TRUE; +SELECT '2222222222221'::ean13; +SELECT is_valid('2222222222221'::ean13); +SELECT make_valid('2222222222221'::ean13); + +SELECT isn_weak(); -- backwards-compatibility wrappers for accessing the GUC +SELECT isn_weak(false); +SHOW isn.weak; + +-- -- cleanup -- DROP EXTENSION isn; diff --git a/doc/src/sgml/isn.sgml b/doc/src/sgml/isn.sgml index 45a867d98c2..1f08ada6218 100644 --- a/doc/src/sgml/isn.sgml +++ b/doc/src/sgml/isn.sgml @@ -230,7 +230,7 @@ <para> The <filename>isn</filename> module provides the standard comparison operators, plus B-tree and hash indexing support for all these data types. In - addition there are several specialized functions; shown in <xref linkend="isn-functions"/>. + addition, there are several specialized functions, shown in <xref linkend="isn-functions"/>. In this table, <type>isn</type> means any one of the module's data types. </para> @@ -252,55 +252,78 @@ <tbody> <row> <entry role="func_table_entry"><para role="func_signature"> - <indexterm><primary>isn_weak</primary></indexterm> - <function>isn_weak</function> ( <type>boolean</type> ) - <returnvalue>boolean</returnvalue> + <indexterm><primary>make_valid</primary></indexterm> + <function>make_valid</function> ( <type>isn</type> ) + <returnvalue>isn</returnvalue> </para> <para> - Sets the weak input mode, and returns new setting. + Clears the invalid-check-digit flag of the value. </para></entry> </row> <row> <entry role="func_table_entry"><para role="func_signature"> - <function>isn_weak</function> () + <indexterm><primary>is_valid</primary></indexterm> + <function>is_valid</function> ( <type>isn</type> ) <returnvalue>boolean</returnvalue> </para> <para> - Returns the current status of the weak mode. + Checks for the presence of the invalid-check-digit flag. </para></entry> </row> <row> <entry role="func_table_entry"><para role="func_signature"> - <indexterm><primary>make_valid</primary></indexterm> - <function>make_valid</function> ( <type>isn</type> ) - <returnvalue>isn</returnvalue> + <indexterm><primary>isn_weak</primary></indexterm> + <function>isn_weak</function> ( <type>boolean</type> ) + <returnvalue>boolean</returnvalue> </para> <para> - Validates an invalid number (clears the invalid flag). + Sets the weak input mode, and returns the new setting. + This function is retained for backward compatibility. + The recommended way to set weak mode is via + the <varname>isn.weak</varname> configuration parameter. </para></entry> </row> <row> <entry role="func_table_entry"><para role="func_signature"> - <indexterm><primary>is_valid</primary></indexterm> - <function>is_valid</function> ( <type>isn</type> ) + <function>isn_weak</function> () <returnvalue>boolean</returnvalue> </para> <para> - Checks for the presence of the invalid flag. + Returns the current status of the weak mode. + This function is retained for backward compatibility. + The recommended way to check weak mode is via + the <varname>isn.weak</varname> configuration parameter. </para></entry> </row> </tbody> </tgroup> </table> + </sect2> - <para> - <firstterm>Weak</firstterm> mode is used to be able to insert invalid data - into a table. Invalid means the check digit is wrong, not that there are - missing numbers. - </para> + <sect2 id="isn-configuration-parameters"> + <title>Configuration Parameters</title> + + <variablelist> + <varlistentry id="isn-configuration-parameters-weak"> + <term> + <varname>isn.weak</varname> (<type>boolean</type>) + <indexterm> + <primary><varname>isn.weak</varname> configuration parameter</primary> + </indexterm> + </term> + <listitem> + <para> + <varname>isn.weak</varname> enables the weak input mode, which allows + ISN input values to be accepted even when their check digit is wrong. + The default is <literal>false</literal>, which rejects invalid check + digits. + </para> + </listitem> + </varlistentry> + </variablelist> <para> Why would you want to use the weak mode? Well, it could be that @@ -325,9 +348,9 @@ </para> <para> - You can also force the insertion of invalid numbers even when not in the - weak mode, by appending the <literal>!</literal> character at the end of the - number. + You can also force the insertion of marked-as-invalid numbers even when not + in the weak mode, by appending the <literal>!</literal> character at the + end of the number. </para> <para> @@ -366,11 +389,11 @@ SELECT issn('3251231?'); SELECT ismn('979047213542?'); --Using the weak mode: -SELECT isn_weak(true); +SET isn.weak TO true; INSERT INTO test VALUES('978-0-11-000533-4'); INSERT INTO test VALUES('9780141219307'); INSERT INTO test VALUES('2-205-00876-X'); -SELECT isn_weak(false); +SET isn.weak TO false; SELECT id FROM test WHERE NOT is_valid(id); UPDATE test SET id = make_valid(id) WHERE id = '2-205-00876-X!'; |