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

Commit55c8807

Browse files
committed
Fix hstore_to_json_loose's detection of valid JSON number values.
We expose a function IsValidJsonNumber that internally calls the lexerfor json numbers. That allows us to use the same test everywhere,instead of inventing a broken test for hstore conversions. The newfunction is also used in datum_to_json, replacing the code that is nowmoved to the new function.Backpatch to 9.3 where hstore_to_json_loose was introduced.
1 parent5c9a4a8 commit55c8807

File tree

3 files changed

+42
-48
lines changed

3 files changed

+42
-48
lines changed

‎contrib/hstore/hstore_io.c

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include"libpq/pqformat.h"
1313
#include"utils/builtins.h"
1414
#include"utils/json.h"
15+
#include"utils/jsonapi.h"
1516
#include"utils/lsyscache.h"
1617
#include"utils/memutils.h"
1718
#include"utils/typcache.h"
@@ -1253,7 +1254,6 @@ hstore_to_json_loose(PG_FUNCTION_ARGS)
12531254
intcount=HS_COUNT(in);
12541255
char*base=STRPTR(in);
12551256
HEntry*entries=ARRPTR(in);
1256-
boolis_number;
12571257
StringInfoDatatmp,
12581258
dst;
12591259

@@ -1280,48 +1280,9 @@ hstore_to_json_loose(PG_FUNCTION_ARGS)
12801280
appendStringInfoString(&dst,"false");
12811281
else
12821282
{
1283-
is_number= false;
12841283
resetStringInfo(&tmp);
12851284
appendBinaryStringInfo(&tmp,HS_VAL(entries,base,i),HS_VALLEN(entries,i));
1286-
1287-
/*
1288-
* don't treat something with a leading zero followed by another
1289-
* digit as numeric - could be a zip code or similar
1290-
*/
1291-
if (tmp.len>0&&
1292-
!(tmp.data[0]=='0'&&
1293-
isdigit((unsignedchar)tmp.data[1]))&&
1294-
strspn(tmp.data,"+-0123456789Ee.")==tmp.len)
1295-
{
1296-
/*
1297-
* might be a number. See if we can input it as a numeric
1298-
* value. Ignore any actual parsed value.
1299-
*/
1300-
char*endptr="junk";
1301-
longlval;
1302-
1303-
lval=strtol(tmp.data,&endptr,10);
1304-
(void)lval;
1305-
if (*endptr=='\0')
1306-
{
1307-
/*
1308-
* strol man page says this means the whole string is
1309-
* valid
1310-
*/
1311-
is_number= true;
1312-
}
1313-
else
1314-
{
1315-
/* not an int - try a double */
1316-
doubledval;
1317-
1318-
dval=strtod(tmp.data,&endptr);
1319-
(void)dval;
1320-
if (*endptr=='\0')
1321-
is_number= true;
1322-
}
1323-
}
1324-
if (is_number)
1285+
if (IsValidJsonNumber(tmp.data,tmp.len))
13251286
appendBinaryStringInfo(&dst,tmp.data,tmp.len);
13261287
else
13271288
escape_json(&dst,tmp.data);

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,36 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
164164
(c) == '_' || \
165165
IS_HIGHBIT_SET(c))
166166

167+
/* utility function to check if a string is a valid JSON number */
168+
externbool
169+
IsValidJsonNumber(constchar*str,intlen)
170+
{
171+
boolnumeric_error;
172+
JsonLexContextdummy_lex;
173+
174+
175+
/*
176+
* json_lex_number expects a leading '-' to have been eaten already.
177+
*
178+
* having to cast away the constness of str is ugly, but there's not much
179+
* easy alternative.
180+
*/
181+
if (*str=='-')
182+
{
183+
dummy_lex.input= (char*)str+1;
184+
dummy_lex.input_length=len-1;
185+
}
186+
else
187+
{
188+
dummy_lex.input= (char*)str;
189+
dummy_lex.input_length=len;
190+
}
191+
192+
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error);
193+
194+
return !numeric_error;
195+
}
196+
167197
/*
168198
* Input.
169199
*/
@@ -1306,8 +1336,6 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13061336
{
13071337
char*outputstr;
13081338
text*jsontext;
1309-
boolnumeric_error;
1310-
JsonLexContextdummy_lex;
13111339

13121340
if (is_null)
13131341
{
@@ -1332,12 +1360,10 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13321360
caseJSONTYPE_NUMERIC:
13331361
outputstr=OidOutputFunctionCall(outfuncoid,val);
13341362
/*
1335-
* Don't call escape_json here if it's a valid JSON number.
1363+
* Don't call escape_json for a non-key if it's a valid JSON
1364+
* number.
13361365
*/
1337-
dummy_lex.input=*outputstr=='-' ?outputstr+1 :outputstr;
1338-
dummy_lex.input_length=strlen(dummy_lex.input);
1339-
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error);
1340-
if (!numeric_error)
1366+
if (!key_scalar&&IsValidJsonNumber(outputstr,strlen(outputstr)))
13411367
appendStringInfoString(result,outputstr);
13421368
else
13431369
escape_json(result,outputstr);

‎src/include/utils/jsonapi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,11 @@ extern void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem);
107107
*/
108108
externJsonLexContext*makeJsonLexContext(text*json,boolneed_escapes);
109109

110+
/*
111+
* Utility function to check if a string is a valid JSON number.
112+
*
113+
* str agrument does not need to be nul-terminated.
114+
*/
115+
externboolIsValidJsonNumber(constchar*str,intlen);
116+
110117
#endif/* JSONAPI_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp