summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2025-03-16 17:45:48 +0000
committerTom Lane2025-03-16 17:45:48 +0000
commit44890442398cf3a65230d53167e61905d2b0d348 (patch)
tree1cb9b611315da7ac77b46aef74addc5918cb22d7
parent682c5be25c28192c56e9d5e2a9ca14673a2fcf4b (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/Makefile4
-rw-r--r--contrib/isn/expected/isn.out44
-rw-r--r--contrib/isn/isn--1.2--1.3.sql7
-rw-r--r--contrib/isn/isn.c27
-rw-r--r--contrib/isn/isn.control2
-rw-r--r--contrib/isn/isn.h1
-rw-r--r--contrib/isn/meson.build3
-rw-r--r--contrib/isn/sql/isn.sql13
-rw-r--r--doc/src/sgml/isn.sgml71
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!';