Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitffd3944

Browse files
committed
Improve reporting for syntax errors in multi-line JSON data.
Point to the specific line where the error was detected; theprevious code tended to include several preceding lines as well.Avoid re-scanning the entire input to recompute which line thatwas. Simplify the logic a bit. Add test cases.Simon Riggs and Hamid Akhtar, reviewed by Daniel Gustafsson and myselfDiscussion:https://postgr.es/m/CANbhV-EPBnXm3MF_TTWBwwqgn1a1Ghmep9VHfqmNBQ8BT0f+_g@mail.gmail.com
1 parentbd69ddf commitffd3944

File tree

7 files changed

+113
-22
lines changed

7 files changed

+113
-22
lines changed

‎src/backend/utils/adt/jsonfuncs.c

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -641,30 +641,19 @@ report_json_context(JsonLexContext *lex)
641641
constchar*context_start;
642642
constchar*context_end;
643643
constchar*line_start;
644-
intline_number;
645644
char*ctxt;
646645
intctxtlen;
647646
constchar*prefix;
648647
constchar*suffix;
649648

650649
/* Choose boundaries for the part of the input we will display */
651-
context_start=lex->input;
650+
line_start=lex->line_start;
651+
context_start=line_start;
652652
context_end=lex->token_terminator;
653-
line_start=context_start;
654-
line_number=1;
655-
for (;;)
653+
654+
/* Advance until we are close enough to context_end */
655+
while (context_end-context_start >=50&&context_start<context_end)
656656
{
657-
/* Always advance over newlines */
658-
if (context_start<context_end&&*context_start=='\n')
659-
{
660-
context_start++;
661-
line_start=context_start;
662-
line_number++;
663-
continue;
664-
}
665-
/* Otherwise, done as soon as we are close enough to context_end */
666-
if (context_end-context_start<50)
667-
break;
668657
/* Advance to next multibyte character */
669658
if (IS_HIGHBIT_SET(*context_start))
670659
context_start+=pg_mblen(context_start);
@@ -694,7 +683,7 @@ report_json_context(JsonLexContext *lex)
694683
suffix= (lex->token_type!=JSON_TOKEN_END&&context_end-lex->input<lex->input_length&&*context_end!='\n'&&*context_end!='\r') ?"..." :"";
695684

696685
returnerrcontext("JSON data, line %d: %s%s%s",
697-
line_number,prefix,ctxt,suffix);
686+
lex->line_number,prefix,ctxt,suffix);
698687
}
699688

700689

‎src/common/jsonapi.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,10 +535,12 @@ json_lex(JsonLexContext *lex)
535535
while (len<lex->input_length&&
536536
(*s==' '||*s=='\t'||*s=='\n'||*s=='\r'))
537537
{
538-
if (*s=='\n')
538+
if (*s++=='\n')
539+
{
539540
++lex->line_number;
540-
++s;
541-
++len;
541+
lex->line_start=s;
542+
}
543+
len++;
542544
}
543545
lex->token_start=s;
544546

‎src/include/common/jsonapi.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ typedef struct JsonLexContext
7979
char*prev_token_terminator;
8080
JsonTokenTypetoken_type;
8181
intlex_level;
82-
intline_number;
83-
char*line_start;
82+
intline_number;/* line number, starting from 1 */
83+
char*line_start;/* where that line starts within input */
8484
StringInfostrval;
8585
}JsonLexContext;
8686

‎src/test/regress/expected/json.out

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,41 @@ LINE 1: SELECT ' '::json;
272272
^
273273
DETAIL: The input string ended unexpectedly.
274274
CONTEXT: JSON data, line 1:
275+
-- Multi-line JSON input to check ERROR reporting
276+
SELECT '{
277+
"one": 1,
278+
"two":"two",
279+
"three":
280+
true}'::json; -- OK
281+
json
282+
------------------------------
283+
{ +
284+
"one": 1, +
285+
"two":"two",+
286+
"three": +
287+
true}
288+
(1 row)
289+
290+
SELECT '{
291+
"one": 1,
292+
"two":,"two", -- ERROR extraneous comma before field "two"
293+
"three":
294+
true}'::json;
295+
ERROR: invalid input syntax for type json
296+
LINE 1: SELECT '{
297+
^
298+
DETAIL: Expected JSON value, but found ",".
299+
CONTEXT: JSON data, line 3: "two":,...
300+
SELECT '{
301+
"one": 1,
302+
"two":"two",
303+
"averyveryveryveryveryveryveryveryveryverylongfieldname":}'::json;
304+
ERROR: invalid input syntax for type json
305+
LINE 1: SELECT '{
306+
^
307+
DETAIL: Expected JSON value, but found "}".
308+
CONTEXT: JSON data, line 4: ...yveryveryveryveryveryveryveryverylongfieldname":}
309+
-- ERROR missing value for last field
275310
--constructors
276311
-- array_to_json
277312
SELECT array_to_json(array(select 1 as a));

‎src/test/regress/expected/jsonb.out

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,37 @@ LINE 1: SELECT ' '::jsonb;
272272
^
273273
DETAIL: The input string ended unexpectedly.
274274
CONTEXT: JSON data, line 1:
275+
-- Multi-line JSON input to check ERROR reporting
276+
SELECT '{
277+
"one": 1,
278+
"two":"two",
279+
"three":
280+
true}'::jsonb; -- OK
281+
jsonb
282+
-----------------------------------------
283+
{"one": 1, "two": "two", "three": true}
284+
(1 row)
285+
286+
SELECT '{
287+
"one": 1,
288+
"two":,"two", -- ERROR extraneous comma before field "two"
289+
"three":
290+
true}'::jsonb;
291+
ERROR: invalid input syntax for type json
292+
LINE 1: SELECT '{
293+
^
294+
DETAIL: Expected JSON value, but found ",".
295+
CONTEXT: JSON data, line 3: "two":,...
296+
SELECT '{
297+
"one": 1,
298+
"two":"two",
299+
"averyveryveryveryveryveryveryveryveryverylongfieldname":}'::jsonb;
300+
ERROR: invalid input syntax for type json
301+
LINE 1: SELECT '{
302+
^
303+
DETAIL: Expected JSON value, but found "}".
304+
CONTEXT: JSON data, line 4: ...yveryveryveryveryveryveryveryverylongfieldname":}
305+
-- ERROR missing value for last field
275306
-- make sure jsonb is passed through json generators without being escaped
276307
SELECT array_to_json(ARRAY [jsonb '{"a":1}', jsonb '{"b":[2,3]}']);
277308
array_to_json

‎src/test/regress/sql/json.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,23 @@ SELECT 'trues'::json;-- ERROR, not a keyword
5959
SELECT''::json;-- ERROR, no value
6060
SELECT''::json;-- ERROR, no value
6161

62+
-- Multi-line JSON input to check ERROR reporting
63+
SELECT'{
64+
"one": 1,
65+
"two":"two",
66+
"three":
67+
true}'::json;-- OK
68+
SELECT'{
69+
"one": 1,
70+
"two":,"two", -- ERROR extraneous comma before field "two"
71+
"three":
72+
true}'::json;
73+
SELECT'{
74+
"one": 1,
75+
"two":"two",
76+
"averyveryveryveryveryveryveryveryveryverylongfieldname":}'::json;
77+
-- ERROR missing value for last field
78+
6279
--constructors
6380
-- array_to_json
6481

‎src/test/regress/sql/jsonb.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,23 @@ SELECT 'trues'::jsonb;-- ERROR, not a keyword
5959
SELECT''::jsonb;-- ERROR, no value
6060
SELECT''::jsonb;-- ERROR, no value
6161

62+
-- Multi-line JSON input to check ERROR reporting
63+
SELECT'{
64+
"one": 1,
65+
"two":"two",
66+
"three":
67+
true}'::jsonb;-- OK
68+
SELECT'{
69+
"one": 1,
70+
"two":,"two", -- ERROR extraneous comma before field "two"
71+
"three":
72+
true}'::jsonb;
73+
SELECT'{
74+
"one": 1,
75+
"two":"two",
76+
"averyveryveryveryveryveryveryveryveryverylongfieldname":}'::jsonb;
77+
-- ERROR missing value for last field
78+
6279
-- make sure jsonb is passed through json generators without being escaped
6380
SELECT array_to_json(ARRAY [jsonb'{"a":1}', jsonb'{"b":[2,3]}']);
6481

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp