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 <v@viktorh.net> Diagnosed-by: Daniel Gustafsson <daniel@yesql.se> Author: Viktor Holmberg <v@viktorh.net> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/790bc1f9-74dc-4b50-94d2-8147315b1556@Spark
This commit is contained in:
parent
682c5be25c
commit
4489044239
@ -3,8 +3,8 @@
|
|||||||
MODULES = isn
|
MODULES = isn
|
||||||
|
|
||||||
EXTENSION = isn
|
EXTENSION = isn
|
||||||
DATA = isn--1.1.sql isn--1.1--1.2.sql \
|
DATA = isn--1.0--1.1.sql isn--1.1.sql \
|
||||||
isn--1.0--1.1.sql
|
isn--1.1--1.2.sql isn--1.2--1.3.sql
|
||||||
PGFILEDESC = "isn - data types for international product numbering standards"
|
PGFILEDESC = "isn - data types for international product numbering standards"
|
||||||
|
|
||||||
# the other .h files are data tables, we don't install those
|
# the other .h files are data tables, we don't install those
|
||||||
|
@ -279,6 +279,50 @@ FROM (VALUES ('9780123456786', 'UPC'),
|
|||||||
9771234567003 | ISSN | t | | | |
|
9771234567003 | ISSN | t | | | |
|
||||||
(3 rows)
|
(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
|
-- cleanup
|
||||||
--
|
--
|
||||||
|
7
contrib/isn/isn--1.2--1.3.sql
Normal file
7
contrib/isn/isn--1.2--1.3.sql
Normal file
@ -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;
|
@ -21,6 +21,7 @@
|
|||||||
#include "UPC.h"
|
#include "UPC.h"
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
#include "isn.h"
|
#include "isn.h"
|
||||||
|
#include "utils/guc.h"
|
||||||
|
|
||||||
PG_MODULE_MAGIC;
|
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"};
|
static const char *const isn_names[] = {"EAN13/UPC/ISxN", "EAN13/UPC/ISxN", "EAN13", "ISBN", "ISMN", "ISSN", "UPC"};
|
||||||
|
|
||||||
|
/* GUC value */
|
||||||
static bool g_weak = false;
|
static bool g_weak = false;
|
||||||
|
|
||||||
|
|
||||||
@ -929,6 +931,20 @@ _PG_init(void)
|
|||||||
if (!check_table(UPC_range, UPC_index))
|
if (!check_table(UPC_range, UPC_index))
|
||||||
elog(ERROR, "UPC failed check");
|
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
|
/* isn_out
|
||||||
@ -1109,17 +1125,16 @@ make_valid(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* this function temporarily sets weak input flag
|
/* this function temporarily sets weak input flag
|
||||||
* (to lose the strictness of check digit acceptance)
|
* (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);
|
PG_FUNCTION_INFO_V1(accept_weak_input);
|
||||||
Datum
|
Datum
|
||||||
accept_weak_input(PG_FUNCTION_ARGS)
|
accept_weak_input(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
#ifdef ISN_WEAK_MODE
|
bool newvalue = PG_GETARG_BOOL(0);
|
||||||
g_weak = PG_GETARG_BOOL(0);
|
|
||||||
#else
|
(void) set_config_option("isn.weak", newvalue ? "on" : "off",
|
||||||
/* function has no effect */
|
PGC_USERSET, PGC_S_SESSION,
|
||||||
#endif /* ISN_WEAK_MODE */
|
GUC_ACTION_SET, true, 0, false);
|
||||||
PG_RETURN_BOOL(g_weak);
|
PG_RETURN_BOOL(g_weak);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# isn extension
|
# isn extension
|
||||||
comment = 'data types for international product numbering standards'
|
comment = 'data types for international product numbering standards'
|
||||||
default_version = '1.2'
|
default_version = '1.3'
|
||||||
module_pathname = '$libdir/isn'
|
module_pathname = '$libdir/isn'
|
||||||
relocatable = true
|
relocatable = true
|
||||||
trusted = true
|
trusted = true
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
|
|
||||||
#undef ISN_DEBUG
|
#undef ISN_DEBUG
|
||||||
#define ISN_WEAK_MODE
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* uint64 is the internal storage format for ISNs.
|
* uint64 is the internal storage format for ISNs.
|
||||||
|
@ -19,8 +19,9 @@ contrib_targets += isn
|
|||||||
install_data(
|
install_data(
|
||||||
'isn.control',
|
'isn.control',
|
||||||
'isn--1.0--1.1.sql',
|
'isn--1.0--1.1.sql',
|
||||||
'isn--1.1--1.2.sql',
|
|
||||||
'isn--1.1.sql',
|
'isn--1.1.sql',
|
||||||
|
'isn--1.1--1.2.sql',
|
||||||
|
'isn--1.2--1.3.sql',
|
||||||
kwargs: contrib_data_args,
|
kwargs: contrib_data_args,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -120,6 +120,19 @@ FROM (VALUES ('9780123456786', 'UPC'),
|
|||||||
AS a(str,typ),
|
AS a(str,typ),
|
||||||
LATERAL pg_input_error_info(a.str, a.typ) as errinfo;
|
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
|
-- cleanup
|
||||||
--
|
--
|
||||||
|
@ -230,7 +230,7 @@
|
|||||||
<para>
|
<para>
|
||||||
The <filename>isn</filename> module provides the standard comparison operators,
|
The <filename>isn</filename> module provides the standard comparison operators,
|
||||||
plus B-tree and hash indexing support for all these data types. In
|
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,
|
In this table,
|
||||||
<type>isn</type> means any one of the module's data types.
|
<type>isn</type> means any one of the module's data types.
|
||||||
</para>
|
</para>
|
||||||
@ -250,27 +250,6 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<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>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Sets the weak input mode, and returns new setting.
|
|
||||||
</para></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry role="func_table_entry"><para role="func_signature">
|
|
||||||
<function>isn_weak</function> ()
|
|
||||||
<returnvalue>boolean</returnvalue>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Returns the current status of the weak mode.
|
|
||||||
</para></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry role="func_table_entry"><para role="func_signature">
|
<entry role="func_table_entry"><para role="func_signature">
|
||||||
<indexterm><primary>make_valid</primary></indexterm>
|
<indexterm><primary>make_valid</primary></indexterm>
|
||||||
@ -278,7 +257,7 @@
|
|||||||
<returnvalue>isn</returnvalue>
|
<returnvalue>isn</returnvalue>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Validates an invalid number (clears the invalid flag).
|
Clears the invalid-check-digit flag of the value.
|
||||||
</para></entry>
|
</para></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
@ -289,18 +268,62 @@
|
|||||||
<returnvalue>boolean</returnvalue>
|
<returnvalue>boolean</returnvalue>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Checks for the presence of the invalid flag.
|
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>isn_weak</primary></indexterm>
|
||||||
|
<function>isn_weak</function> ( <type>boolean</type> )
|
||||||
|
<returnvalue>boolean</returnvalue>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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">
|
||||||
|
<function>isn_weak</function> ()
|
||||||
|
<returnvalue>boolean</returnvalue>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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>
|
</para></entry>
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
<para>
|
<sect2 id="isn-configuration-parameters">
|
||||||
<firstterm>Weak</firstterm> mode is used to be able to insert invalid data
|
<title>Configuration Parameters</title>
|
||||||
into a table. Invalid means the check digit is wrong, not that there are
|
|
||||||
missing numbers.
|
<variablelist>
|
||||||
</para>
|
<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>
|
<para>
|
||||||
Why would you want to use the weak mode? Well, it could be that
|
Why would you want to use the weak mode? Well, it could be that
|
||||||
@ -325,9 +348,9 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
You can also force the insertion of invalid numbers even when not in the
|
You can also force the insertion of marked-as-invalid numbers even when not
|
||||||
weak mode, by appending the <literal>!</literal> character at the end of the
|
in the weak mode, by appending the <literal>!</literal> character at the
|
||||||
number.
|
end of the number.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -366,11 +389,11 @@ SELECT issn('3251231?');
|
|||||||
SELECT ismn('979047213542?');
|
SELECT ismn('979047213542?');
|
||||||
|
|
||||||
--Using the weak mode:
|
--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('978-0-11-000533-4');
|
||||||
INSERT INTO test VALUES('9780141219307');
|
INSERT INTO test VALUES('9780141219307');
|
||||||
INSERT INTO test VALUES('2-205-00876-X');
|
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);
|
SELECT id FROM test WHERE NOT is_valid(id);
|
||||||
UPDATE test SET id = make_valid(id) WHERE id = '2-205-00876-X!';
|
UPDATE test SET id = make_valid(id) WHERE id = '2-205-00876-X!';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user