Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit cb3384a

Browse files
committed
Fix output of ISBN-13 numbers beginning with 979.
An EAN beginning with 979 (but not 9790 - those are ISMN's) are accepted as ISBN numbers, but they cannot be represented in the old, 10-digit ISBN format. They must be output in the new 13-digit ISBN-13 format. We printed out an incorrect value for those. Also add a regression test, to test this and some other basic functionality of the module. Patch by Fabien Coelho. This fixes bug #13442, reported by B.Z. Backpatch to 9.1, where we started to recognize ISBN-13 numbers.
1 parent d73d14c commit cb3384a

File tree

4 files changed

+345
-10
lines changed

4 files changed

+345
-10
lines changed

contrib/isn/Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ EXTENSION = isn
66
DATA = isn--1.0.sql isn--unpackaged--1.0.sql
77
PGFILEDESC = "isn - data types for international product numbering standards"
88

9+
REGRESS = isn
10+
911
ifdef USE_PGXS
1012
PG_CONFIG = pg_config
1113
PGXS := $(shell $(PG_CONFIG) --pgxs)

contrib/isn/expected/isn.out

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
--
2+
-- Test ISN extension
3+
--
4+
CREATE EXTENSION isn;
5+
--
6+
-- test valid conversions
7+
--
8+
SELECT '9780123456786'::EAN13, -- old book
9+
'9790123456785'::EAN13, -- music
10+
'9791234567896'::EAN13, -- new book
11+
'9771234567898'::EAN13, -- serial
12+
'0123456789012'::EAN13, -- upc
13+
'1234567890128'::EAN13;
14+
ean13 | ean13 | ean13 | ean13 | ean13 | ean13
15+
-------------------+-------------------+-----------------+-------------------+-----------------+-----------------
16+
978-0-12-345678-6 | 979-0-1234-5678-5 | 979-123456789-6 | 977-1234-567-89-8 | 012-345678901-2 | 123-456789012-8
17+
(1 row)
18+
19+
SELECT '9780123456786'::ISBN,
20+
'123456789X'::ISBN,
21+
'9780123456786'::ISBN13::ISBN,
22+
'9780123456786'::EAN13::ISBN;
23+
isbn | isbn | isbn | isbn
24+
---------------+---------------+---------------+---------------
25+
0-12-345678-9 | 1-234-56789-X | 0-12-345678-9 | 0-12-345678-9
26+
(1 row)
27+
28+
SELECT -- new books, shown as ISBN13 even for ISBN...
29+
'9791234567896'::ISBN,
30+
'9791234567896'::ISBN13::ISBN,
31+
'9791234567896'::EAN13::ISBN;
32+
isbn | isbn | isbn
33+
-----------------+-----------------+-----------------
34+
979-123456789-6 | 979-123456789-6 | 979-123456789-6
35+
(1 row)
36+
37+
SELECT '9780123456786'::ISBN13,
38+
'123456789X'::ISBN13,
39+
'9791234567896'::ISBN13,
40+
'9791234567896'::EAN13::ISBN13;
41+
isbn13 | isbn13 | isbn13 | isbn13
42+
-------------------+-------------------+-----------------+-----------------
43+
978-0-12-345678-6 | 978-1-234-56789-7 | 979-123456789-6 | 979-123456789-6
44+
(1 row)
45+
46+
SELECT '9790123456785'::ISMN,
47+
'9790123456785'::EAN13::ISMN,
48+
'M123456785'::ISMN,
49+
'M-1234-5678-5'::ISMN;
50+
ismn | ismn | ismn | ismn
51+
---------------+---------------+---------------+---------------
52+
M-1234-5678-5 | M-1234-5678-5 | M-1234-5678-5 | M-1234-5678-5
53+
(1 row)
54+
55+
SELECT '9790123456785'::ISMN13,
56+
'M123456785'::ISMN13,
57+
'M-1234-5678-5'::ISMN13;
58+
ismn13 | ismn13 | ismn13
59+
-------------------+-------------------+-------------------
60+
979-0-1234-5678-5 | 979-0-1234-5678-5 | 979-0-1234-5678-5
61+
(1 row)
62+
63+
SELECT '9771234567003'::ISSN,
64+
'12345679'::ISSN;
65+
issn | issn
66+
-----------+-----------
67+
1234-5679 | 1234-5679
68+
(1 row)
69+
70+
SELECT '9771234567003'::ISSN13,
71+
'12345679'::ISSN13,
72+
'9771234567898'::ISSN13,
73+
'9771234567898'::EAN13::ISSN13;
74+
issn13 | issn13 | issn13 | issn13
75+
-------------------+-------------------+-------------------+-------------------
76+
977-1234-567-00-3 | 977-1234-567-00-3 | 977-1234-567-89-8 | 977-1234-567-89-8
77+
(1 row)
78+
79+
SELECT '0123456789012'::UPC,
80+
'0123456789012'::EAN13::UPC;
81+
upc | upc
82+
--------------+--------------
83+
123456789012 | 123456789012
84+
(1 row)
85+
86+
--
87+
-- test invalid checksums
88+
--
89+
SELECT '1234567890'::ISBN;
90+
ERROR: invalid check digit for ISBN number: "1234567890", should be X
91+
LINE 1: SELECT '1234567890'::ISBN;
92+
^
93+
SELECT 'M123456780'::ISMN;
94+
ERROR: invalid check digit for ISMN number: "M123456780", should be 5
95+
LINE 1: SELECT 'M123456780'::ISMN;
96+
^
97+
SELECT '12345670'::ISSN;
98+
ERROR: invalid check digit for ISSN number: "12345670", should be 9
99+
LINE 1: SELECT '12345670'::ISSN;
100+
^
101+
SELECT '9780123456780'::ISBN;
102+
ERROR: invalid check digit for ISBN number: "9780123456780", should be 6
103+
LINE 1: SELECT '9780123456780'::ISBN;
104+
^
105+
SELECT '9791234567890'::ISBN13;
106+
ERROR: invalid check digit for ISBN number: "9791234567890", should be 6
107+
LINE 1: SELECT '9791234567890'::ISBN13;
108+
^
109+
SELECT '0123456789010'::UPC;
110+
ERROR: invalid check digit for UPC number: "0123456789010", should be 2
111+
LINE 1: SELECT '0123456789010'::UPC;
112+
^
113+
SELECT '1234567890120'::EAN13;
114+
ERROR: invalid check digit for EAN13 number: "1234567890120", should be 8
115+
LINE 1: SELECT '1234567890120'::EAN13;
116+
^
117+
--
118+
-- test invalid conversions
119+
--
120+
SELECT '9790123456785'::ISBN; -- not a book
121+
ERROR: cannot cast ISMN to ISBN for number: "9790123456785"
122+
LINE 1: SELECT '9790123456785'::ISBN;
123+
^
124+
SELECT '9771234567898'::ISBN; -- not a book
125+
ERROR: cannot cast ISSN to ISBN for number: "9771234567898"
126+
LINE 1: SELECT '9771234567898'::ISBN;
127+
^
128+
SELECT '0123456789012'::ISBN; -- not a book
129+
ERROR: cannot cast UPC to ISBN for number: "0123456789012"
130+
LINE 1: SELECT '0123456789012'::ISBN;
131+
^
132+
SELECT '9790123456785'::ISBN13; -- not a book
133+
ERROR: cannot cast ISMN to ISBN for number: "9790123456785"
134+
LINE 1: SELECT '9790123456785'::ISBN13;
135+
^
136+
SELECT '9771234567898'::ISBN13; -- not a book
137+
ERROR: cannot cast ISSN to ISBN for number: "9771234567898"
138+
LINE 1: SELECT '9771234567898'::ISBN13;
139+
^
140+
SELECT '0123456789012'::ISBN13; -- not a book
141+
ERROR: cannot cast UPC to ISBN for number: "0123456789012"
142+
LINE 1: SELECT '0123456789012'::ISBN13;
143+
^
144+
SELECT '9780123456786'::ISMN; -- not music
145+
ERROR: cannot cast ISBN to ISMN for number: "9780123456786"
146+
LINE 1: SELECT '9780123456786'::ISMN;
147+
^
148+
SELECT '9771234567898'::ISMN; -- not music
149+
ERROR: cannot cast ISSN to ISMN for number: "9771234567898"
150+
LINE 1: SELECT '9771234567898'::ISMN;
151+
^
152+
SELECT '9791234567896'::ISMN; -- not music
153+
ERROR: cannot cast ISBN to ISMN for number: "9791234567896"
154+
LINE 1: SELECT '9791234567896'::ISMN;
155+
^
156+
SELECT '0123456789012'::ISMN; -- not music
157+
ERROR: cannot cast UPC to ISMN for number: "0123456789012"
158+
LINE 1: SELECT '0123456789012'::ISMN;
159+
^
160+
SELECT '9780123456786'::ISSN; -- not serial
161+
ERROR: cannot cast ISBN to ISSN for number: "9780123456786"
162+
LINE 1: SELECT '9780123456786'::ISSN;
163+
^
164+
SELECT '9790123456785'::ISSN; -- not serial
165+
ERROR: cannot cast ISMN to ISSN for number: "9790123456785"
166+
LINE 1: SELECT '9790123456785'::ISSN;
167+
^
168+
SELECT '9791234567896'::ISSN; -- not serial
169+
ERROR: cannot cast ISBN to ISSN for number: "9791234567896"
170+
LINE 1: SELECT '9791234567896'::ISSN;
171+
^
172+
SELECT '0123456789012'::ISSN; -- not serial
173+
ERROR: cannot cast UPC to ISSN for number: "0123456789012"
174+
LINE 1: SELECT '0123456789012'::ISSN;
175+
^
176+
SELECT '9780123456786'::UPC; -- not a product
177+
ERROR: cannot cast ISBN to UPC for number: "9780123456786"
178+
LINE 1: SELECT '9780123456786'::UPC;
179+
^
180+
SELECT '9771234567898'::UPC; -- not a product
181+
ERROR: cannot cast ISSN to UPC for number: "9771234567898"
182+
LINE 1: SELECT '9771234567898'::UPC;
183+
^
184+
SELECT '9790123456785'::UPC; -- not a product
185+
ERROR: cannot cast ISMN to UPC for number: "9790123456785"
186+
LINE 1: SELECT '9790123456785'::UPC;
187+
^
188+
SELECT '9791234567896'::UPC; -- not a product
189+
ERROR: cannot cast ISBN to UPC for number: "9791234567896"
190+
LINE 1: SELECT '9791234567896'::UPC;
191+
^
192+
SELECT 'postgresql...'::EAN13;
193+
ERROR: invalid input syntax for EAN13 number: "postgresql..."
194+
LINE 1: SELECT 'postgresql...'::EAN13;
195+
^
196+
SELECT 'postgresql...'::ISBN;
197+
ERROR: invalid input syntax for ISBN number: "postgresql..."
198+
LINE 1: SELECT 'postgresql...'::ISBN;
199+
^
200+
SELECT 9780123456786::EAN13;
201+
ERROR: cannot cast type bigint to ean13
202+
LINE 1: SELECT 9780123456786::EAN13;
203+
^
204+
SELECT 9780123456786::ISBN;
205+
ERROR: cannot cast type bigint to isbn
206+
LINE 1: SELECT 9780123456786::ISBN;
207+
^
208+
--
209+
-- test some comparisons, must yield true
210+
--
211+
SELECT '12345679'::ISSN = '9771234567003'::EAN13 AS "ok",
212+
'M-1234-5678-5'::ISMN = '9790123456785'::EAN13 AS "ok",
213+
'9791234567896'::EAN13 != '123456789X'::ISBN AS "nope";
214+
ok | ok | nope
215+
----+----+------
216+
t | t | t
217+
(1 row)
218+
219+
--
220+
-- cleanup
221+
--
222+
DROP EXTENSION isn;

contrib/isn/isn.c

+17-10
Original file line numberDiff line numberDiff line change
@@ -443,16 +443,23 @@ ean2ISBN(char *isn)
443443
char *aux;
444444
unsigned check;
445445

446-
/* the number should come in this format: 978-0-000-00000-0 */
447-
/* Strip the first part and calculate the new check digit */
448-
hyphenate(isn, isn + 4, NULL, NULL);
449-
check = weight_checkdig(isn, 10);
450-
aux = strchr(isn, '\0');
451-
while (!isdigit((unsigned char) *--aux));
452-
if (check == 10)
453-
*aux = 'X';
454-
else
455-
*aux = check + '0';
446+
/*
447+
* The number should come in this format: 978-0-000-00000-0
448+
* or may be an ISBN-13 number, 979-..., which does not have a short
449+
* representation. Do the short output version if possible.
450+
*/
451+
if (strncmp("978-", isn, 4) == 0)
452+
{
453+
/* Strip the first part and calculate the new check digit */
454+
hyphenate(isn, isn + 4, NULL, NULL);
455+
check = weight_checkdig(isn, 10);
456+
aux = strchr(isn, '\0');
457+
while (!isdigit((unsigned char) *--aux));
458+
if (check == 10)
459+
*aux = 'X';
460+
else
461+
*aux = check + '0';
462+
}
456463
}
457464

458465
static inline void

contrib/isn/sql/isn.sql

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
--
2+
-- Test ISN extension
3+
--
4+
5+
CREATE EXTENSION isn;
6+
7+
--
8+
-- test valid conversions
9+
--
10+
SELECT '9780123456786'::EAN13, -- old book
11+
'9790123456785'::EAN13, -- music
12+
'9791234567896'::EAN13, -- new book
13+
'9771234567898'::EAN13, -- serial
14+
'0123456789012'::EAN13, -- upc
15+
'1234567890128'::EAN13;
16+
17+
SELECT '9780123456786'::ISBN,
18+
'123456789X'::ISBN,
19+
'9780123456786'::ISBN13::ISBN,
20+
'9780123456786'::EAN13::ISBN;
21+
22+
SELECT -- new books, shown as ISBN13 even for ISBN...
23+
'9791234567896'::ISBN,
24+
'9791234567896'::ISBN13::ISBN,
25+
'9791234567896'::EAN13::ISBN;
26+
27+
SELECT '9780123456786'::ISBN13,
28+
'123456789X'::ISBN13,
29+
'9791234567896'::ISBN13,
30+
'9791234567896'::EAN13::ISBN13;
31+
32+
SELECT '9790123456785'::ISMN,
33+
'9790123456785'::EAN13::ISMN,
34+
'M123456785'::ISMN,
35+
'M-1234-5678-5'::ISMN;
36+
37+
SELECT '9790123456785'::ISMN13,
38+
'M123456785'::ISMN13,
39+
'M-1234-5678-5'::ISMN13;
40+
41+
SELECT '9771234567003'::ISSN,
42+
'12345679'::ISSN;
43+
44+
SELECT '9771234567003'::ISSN13,
45+
'12345679'::ISSN13,
46+
'9771234567898'::ISSN13,
47+
'9771234567898'::EAN13::ISSN13;
48+
49+
SELECT '0123456789012'::UPC,
50+
'0123456789012'::EAN13::UPC;
51+
52+
--
53+
-- test invalid checksums
54+
--
55+
SELECT '1234567890'::ISBN;
56+
SELECT 'M123456780'::ISMN;
57+
SELECT '12345670'::ISSN;
58+
SELECT '9780123456780'::ISBN;
59+
SELECT '9791234567890'::ISBN13;
60+
SELECT '0123456789010'::UPC;
61+
SELECT '1234567890120'::EAN13;
62+
63+
--
64+
-- test invalid conversions
65+
--
66+
SELECT '9790123456785'::ISBN; -- not a book
67+
SELECT '9771234567898'::ISBN; -- not a book
68+
SELECT '0123456789012'::ISBN; -- not a book
69+
70+
SELECT '9790123456785'::ISBN13; -- not a book
71+
SELECT '9771234567898'::ISBN13; -- not a book
72+
SELECT '0123456789012'::ISBN13; -- not a book
73+
74+
SELECT '9780123456786'::ISMN; -- not music
75+
SELECT '9771234567898'::ISMN; -- not music
76+
SELECT '9791234567896'::ISMN; -- not music
77+
SELECT '0123456789012'::ISMN; -- not music
78+
79+
SELECT '9780123456786'::ISSN; -- not serial
80+
SELECT '9790123456785'::ISSN; -- not serial
81+
SELECT '9791234567896'::ISSN; -- not serial
82+
SELECT '0123456789012'::ISSN; -- not serial
83+
84+
SELECT '9780123456786'::UPC; -- not a product
85+
SELECT '9771234567898'::UPC; -- not a product
86+
SELECT '9790123456785'::UPC; -- not a product
87+
SELECT '9791234567896'::UPC; -- not a product
88+
89+
SELECT 'postgresql...'::EAN13;
90+
SELECT 'postgresql...'::ISBN;
91+
SELECT 9780123456786::EAN13;
92+
SELECT 9780123456786::ISBN;
93+
94+
--
95+
-- test some comparisons, must yield true
96+
--
97+
SELECT '12345679'::ISSN = '9771234567003'::EAN13 AS "ok",
98+
'M-1234-5678-5'::ISMN = '9790123456785'::EAN13 AS "ok",
99+
'9791234567896'::EAN13 != '123456789X'::ISBN AS "nope";
100+
101+
--
102+
-- cleanup
103+
--
104+
DROP EXTENSION isn;

0 commit comments

Comments
 (0)