Skip to content

Commit 4489044

Browse files
committed
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
1 parent 682c5be commit 4489044

File tree

9 files changed

+137
-35
lines changed

9 files changed

+137
-35
lines changed

contrib/isn/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
MODULES = isn
44

55
EXTENSION = isn
6-
DATA = isn--1.1.sql isn--1.1--1.2.sql \
7-
isn--1.0--1.1.sql
6+
DATA = isn--1.0--1.1.sql isn--1.1.sql \
7+
isn--1.1--1.2.sql isn--1.2--1.3.sql
88
PGFILEDESC = "isn - data types for international product numbering standards"
99

1010
# the other .h files are data tables, we don't install those

contrib/isn/expected/isn.out

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,50 @@ FROM (VALUES ('9780123456786', 'UPC'),
279279
9771234567003 | ISSN | t | | | |
280280
(3 rows)
281281

282+
--
283+
-- test weak mode
284+
--
285+
SELECT '2222222222221'::ean13; -- fail
286+
ERROR: invalid check digit for EAN13 number: "2222222222221", should be 2
287+
LINE 1: SELECT '2222222222221'::ean13;
288+
^
289+
SET isn.weak TO TRUE;
290+
SELECT '2222222222221'::ean13;
291+
ean13
292+
------------------
293+
222-222222222-2!
294+
(1 row)
295+
296+
SELECT is_valid('2222222222221'::ean13);
297+
is_valid
298+
----------
299+
f
300+
(1 row)
301+
302+
SELECT make_valid('2222222222221'::ean13);
303+
make_valid
304+
-----------------
305+
222-222222222-2
306+
(1 row)
307+
308+
SELECT isn_weak(); -- backwards-compatibility wrappers for accessing the GUC
309+
isn_weak
310+
----------
311+
t
312+
(1 row)
313+
314+
SELECT isn_weak(false);
315+
isn_weak
316+
----------
317+
f
318+
(1 row)
319+
320+
SHOW isn.weak;
321+
isn.weak
322+
----------
323+
off
324+
(1 row)
325+
282326
--
283327
-- cleanup
284328
--

contrib/isn/isn--1.2--1.3.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* contrib/isn/isn--1.2--1.3.sql */
2+
3+
-- complain if script is sourced in psql, rather than via ALTER EXTENSION
4+
\echo Use "ALTER EXTENSION isn UPDATE TO '1.3'" to load this file. \quit
5+
6+
ALTER FUNCTION isn_weak(boolean) VOLATILE PARALLEL UNSAFE;
7+
ALTER FUNCTION isn_weak() STABLE PARALLEL SAFE;

contrib/isn/isn.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "UPC.h"
2222
#include "fmgr.h"
2323
#include "isn.h"
24+
#include "utils/guc.h"
2425

2526
PG_MODULE_MAGIC;
2627

@@ -39,6 +40,7 @@ enum isn_type
3940

4041
static const char *const isn_names[] = {"EAN13/UPC/ISxN", "EAN13/UPC/ISxN", "EAN13", "ISBN", "ISMN", "ISSN", "UPC"};
4142

43+
/* GUC value */
4244
static bool g_weak = false;
4345

4446

@@ -929,6 +931,20 @@ _PG_init(void)
929931
if (!check_table(UPC_range, UPC_index))
930932
elog(ERROR, "UPC failed check");
931933
}
934+
935+
/* Define a GUC variable for weak mode. */
936+
DefineCustomBoolVariable("isn.weak",
937+
"Accept input with invalid ISN check digits.",
938+
NULL,
939+
&g_weak,
940+
false,
941+
PGC_USERSET,
942+
0,
943+
NULL,
944+
NULL,
945+
NULL);
946+
947+
MarkGUCPrefixReserved("isn");
932948
}
933949

934950
/* isn_out
@@ -1109,17 +1125,16 @@ make_valid(PG_FUNCTION_ARGS)
11091125

11101126
/* this function temporarily sets weak input flag
11111127
* (to lose the strictness of check digit acceptance)
1112-
* It's a helper function, not intended to be used!!
11131128
*/
11141129
PG_FUNCTION_INFO_V1(accept_weak_input);
11151130
Datum
11161131
accept_weak_input(PG_FUNCTION_ARGS)
11171132
{
1118-
#ifdef ISN_WEAK_MODE
1119-
g_weak = PG_GETARG_BOOL(0);
1120-
#else
1121-
/* function has no effect */
1122-
#endif /* ISN_WEAK_MODE */
1133+
bool newvalue = PG_GETARG_BOOL(0);
1134+
1135+
(void) set_config_option("isn.weak", newvalue ? "on" : "off",
1136+
PGC_USERSET, PGC_S_SESSION,
1137+
GUC_ACTION_SET, true, 0, false);
11231138
PG_RETURN_BOOL(g_weak);
11241139
}
11251140

contrib/isn/isn.control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# isn extension
22
comment = 'data types for international product numbering standards'
3-
default_version = '1.2'
3+
default_version = '1.3'
44
module_pathname = '$libdir/isn'
55
relocatable = true
66
trusted = true

contrib/isn/isn.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include "fmgr.h"
1919

2020
#undef ISN_DEBUG
21-
#define ISN_WEAK_MODE
2221

2322
/*
2423
* uint64 is the internal storage format for ISNs.

contrib/isn/meson.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ contrib_targets += isn
1919
install_data(
2020
'isn.control',
2121
'isn--1.0--1.1.sql',
22-
'isn--1.1--1.2.sql',
2322
'isn--1.1.sql',
23+
'isn--1.1--1.2.sql',
24+
'isn--1.2--1.3.sql',
2425
kwargs: contrib_data_args,
2526
)
2627

contrib/isn/sql/isn.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,19 @@ FROM (VALUES ('9780123456786', 'UPC'),
120120
AS a(str,typ),
121121
LATERAL pg_input_error_info(a.str, a.typ) as errinfo;
122122

123+
--
124+
-- test weak mode
125+
--
126+
SELECT '2222222222221'::ean13; -- fail
127+
SET isn.weak TO TRUE;
128+
SELECT '2222222222221'::ean13;
129+
SELECT is_valid('2222222222221'::ean13);
130+
SELECT make_valid('2222222222221'::ean13);
131+
132+
SELECT isn_weak(); -- backwards-compatibility wrappers for accessing the GUC
133+
SELECT isn_weak(false);
134+
SHOW isn.weak;
135+
123136
--
124137
-- cleanup
125138
--

doc/src/sgml/isn.sgml

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@
230230
<para>
231231
The <filename>isn</filename> module provides the standard comparison operators,
232232
plus B-tree and hash indexing support for all these data types. In
233-
addition there are several specialized functions; shown in <xref linkend="isn-functions"/>.
233+
addition, there are several specialized functions, shown in <xref linkend="isn-functions"/>.
234234
In this table,
235235
<type>isn</type> means any one of the module's data types.
236236
</para>
@@ -252,55 +252,78 @@
252252
<tbody>
253253
<row>
254254
<entry role="func_table_entry"><para role="func_signature">
255-
<indexterm><primary>isn_weak</primary></indexterm>
256-
<function>isn_weak</function> ( <type>boolean</type> )
257-
<returnvalue>boolean</returnvalue>
255+
<indexterm><primary>make_valid</primary></indexterm>
256+
<function>make_valid</function> ( <type>isn</type> )
257+
<returnvalue>isn</returnvalue>
258258
</para>
259259
<para>
260-
Sets the weak input mode, and returns new setting.
260+
Clears the invalid-check-digit flag of the value.
261261
</para></entry>
262262
</row>
263263

264264
<row>
265265
<entry role="func_table_entry"><para role="func_signature">
266-
<function>isn_weak</function> ()
266+
<indexterm><primary>is_valid</primary></indexterm>
267+
<function>is_valid</function> ( <type>isn</type> )
267268
<returnvalue>boolean</returnvalue>
268269
</para>
269270
<para>
270-
Returns the current status of the weak mode.
271+
Checks for the presence of the invalid-check-digit flag.
271272
</para></entry>
272273
</row>
273274

274275
<row>
275276
<entry role="func_table_entry"><para role="func_signature">
276-
<indexterm><primary>make_valid</primary></indexterm>
277-
<function>make_valid</function> ( <type>isn</type> )
278-
<returnvalue>isn</returnvalue>
277+
<indexterm><primary>isn_weak</primary></indexterm>
278+
<function>isn_weak</function> ( <type>boolean</type> )
279+
<returnvalue>boolean</returnvalue>
279280
</para>
280281
<para>
281-
Validates an invalid number (clears the invalid flag).
282+
Sets the weak input mode, and returns the new setting.
283+
This function is retained for backward compatibility.
284+
The recommended way to set weak mode is via
285+
the <varname>isn.weak</varname> configuration parameter.
282286
</para></entry>
283287
</row>
284288

285289
<row>
286290
<entry role="func_table_entry"><para role="func_signature">
287-
<indexterm><primary>is_valid</primary></indexterm>
288-
<function>is_valid</function> ( <type>isn</type> )
291+
<function>isn_weak</function> ()
289292
<returnvalue>boolean</returnvalue>
290293
</para>
291294
<para>
292-
Checks for the presence of the invalid flag.
295+
Returns the current status of the weak mode.
296+
This function is retained for backward compatibility.
297+
The recommended way to check weak mode is via
298+
the <varname>isn.weak</varname> configuration parameter.
293299
</para></entry>
294300
</row>
295301
</tbody>
296302
</tgroup>
297303
</table>
304+
</sect2>
298305

299-
<para>
300-
<firstterm>Weak</firstterm> mode is used to be able to insert invalid data
301-
into a table. Invalid means the check digit is wrong, not that there are
302-
missing numbers.
303-
</para>
306+
<sect2 id="isn-configuration-parameters">
307+
<title>Configuration Parameters</title>
308+
309+
<variablelist>
310+
<varlistentry id="isn-configuration-parameters-weak">
311+
<term>
312+
<varname>isn.weak</varname> (<type>boolean</type>)
313+
<indexterm>
314+
<primary><varname>isn.weak</varname> configuration parameter</primary>
315+
</indexterm>
316+
</term>
317+
<listitem>
318+
<para>
319+
<varname>isn.weak</varname> enables the weak input mode, which allows
320+
ISN input values to be accepted even when their check digit is wrong.
321+
The default is <literal>false</literal>, which rejects invalid check
322+
digits.
323+
</para>
324+
</listitem>
325+
</varlistentry>
326+
</variablelist>
304327

305328
<para>
306329
Why would you want to use the weak mode? Well, it could be that
@@ -325,9 +348,9 @@
325348
</para>
326349

327350
<para>
328-
You can also force the insertion of invalid numbers even when not in the
329-
weak mode, by appending the <literal>!</literal> character at the end of the
330-
number.
351+
You can also force the insertion of marked-as-invalid numbers even when not
352+
in the weak mode, by appending the <literal>!</literal> character at the
353+
end of the number.
331354
</para>
332355

333356
<para>
@@ -366,11 +389,11 @@ SELECT issn('3251231?');
366389
SELECT ismn('979047213542?');
367390

368391
--Using the weak mode:
369-
SELECT isn_weak(true);
392+
SET isn.weak TO true;
370393
INSERT INTO test VALUES('978-0-11-000533-4');
371394
INSERT INTO test VALUES('9780141219307');
372395
INSERT INTO test VALUES('2-205-00876-X');
373-
SELECT isn_weak(false);
396+
SET isn.weak TO false;
374397

375398
SELECT id FROM test WHERE NOT is_valid(id);
376399
UPDATE test SET id = make_valid(id) WHERE id = '2-205-00876-X!';

0 commit comments

Comments
 (0)