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

Commite09996f

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 parent4e86f1b commite09996f

File tree

3 files changed

+46
-61
lines changed

3 files changed

+46
-61
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/jsonb.h"
1617
#include"utils/lsyscache.h"
1718
#include"utils/memutils.h"
@@ -1240,7 +1241,6 @@ hstore_to_json_loose(PG_FUNCTION_ARGS)
12401241
intcount=HS_COUNT(in);
12411242
char*base=STRPTR(in);
12421243
HEntry*entries=ARRPTR(in);
1243-
boolis_number;
12441244
StringInfoDatatmp,
12451245
dst;
12461246

@@ -1267,48 +1267,9 @@ hstore_to_json_loose(PG_FUNCTION_ARGS)
12671267
appendStringInfoString(&dst,"false");
12681268
else
12691269
{
1270-
is_number= false;
12711270
resetStringInfo(&tmp);
12721271
appendBinaryStringInfo(&tmp,HS_VAL(entries,base,i),HS_VALLEN(entries,i));
1273-
1274-
/*
1275-
* don't treat something with a leading zero followed by another
1276-
* digit as numeric - could be a zip code or similar
1277-
*/
1278-
if (tmp.len>0&&
1279-
!(tmp.data[0]=='0'&&
1280-
isdigit((unsignedchar)tmp.data[1]))&&
1281-
strspn(tmp.data,"+-0123456789Ee.")==tmp.len)
1282-
{
1283-
/*
1284-
* might be a number. See if we can input it as a numeric
1285-
* value. Ignore any actual parsed value.
1286-
*/
1287-
char*endptr="junk";
1288-
longlval;
1289-
1290-
lval=strtol(tmp.data,&endptr,10);
1291-
(void)lval;
1292-
if (*endptr=='\0')
1293-
{
1294-
/*
1295-
* strol man page says this means the whole string is
1296-
* valid
1297-
*/
1298-
is_number= true;
1299-
}
1300-
else
1301-
{
1302-
/* not an int - try a double */
1303-
doubledval;
1304-
1305-
dval=strtod(tmp.data,&endptr);
1306-
(void)dval;
1307-
if (*endptr=='\0')
1308-
is_number= true;
1309-
}
1310-
}
1311-
if (is_number)
1272+
if (IsValidJsonNumber(tmp.data,tmp.len))
13121273
appendBinaryStringInfo(&dst,tmp.data,tmp.len);
13131274
else
13141275
escape_json(&dst,tmp.data);

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

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,36 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
173173
(c) == '_' || \
174174
IS_HIGHBIT_SET(c))
175175

176+
/* utility function to check if a string is a valid JSON number */
177+
externbool
178+
IsValidJsonNumber(constchar*str,intlen)
179+
{
180+
boolnumeric_error;
181+
JsonLexContextdummy_lex;
182+
183+
184+
/*
185+
* json_lex_number expects a leading '-' to have been eaten already.
186+
*
187+
* having to cast away the constness of str is ugly, but there's not much
188+
* easy alternative.
189+
*/
190+
if (*str=='-')
191+
{
192+
dummy_lex.input= (char*)str+1;
193+
dummy_lex.input_length=len-1;
194+
}
195+
else
196+
{
197+
dummy_lex.input= (char*)str;
198+
dummy_lex.input_length=len;
199+
}
200+
201+
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error);
202+
203+
return !numeric_error;
204+
}
205+
176206
/*
177207
* Input.
178208
*/
@@ -1338,8 +1368,6 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13381368
{
13391369
char*outputstr;
13401370
text*jsontext;
1341-
boolnumeric_error;
1342-
JsonLexContextdummy_lex;
13431371

13441372
/* callers are expected to ensure that null keys are not passed in */
13451373
Assert( ! (key_scalar&&is_null));
@@ -1376,25 +1404,14 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13761404
break;
13771405
caseJSONTYPE_NUMERIC:
13781406
outputstr=OidOutputFunctionCall(outfuncoid,val);
1379-
if (key_scalar)
1380-
{
1381-
/* always quote keys */
1382-
escape_json(result,outputstr);
1383-
}
1407+
/*
1408+
* Don't call escape_json for a non-key if it's a valid JSON
1409+
* number.
1410+
*/
1411+
if (!key_scalar&&IsValidJsonNumber(outputstr,strlen(outputstr)))
1412+
appendStringInfoString(result,outputstr);
13841413
else
1385-
{
1386-
/*
1387-
* Don't call escape_json for a non-key if it's a valid JSON
1388-
* number.
1389-
*/
1390-
dummy_lex.input=*outputstr=='-' ?outputstr+1 :outputstr;
1391-
dummy_lex.input_length=strlen(dummy_lex.input);
1392-
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error);
1393-
if (!numeric_error)
1394-
appendStringInfoString(result,outputstr);
1395-
else
1396-
escape_json(result,outputstr);
1397-
}
1414+
escape_json(result,outputstr);
13981415
pfree(outputstr);
13991416
break;
14001417
caseJSONTYPE_DATE:

‎src/include/utils/jsonapi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,11 @@ extern JsonLexContext *makeJsonLexContextCstringLen(char *json,
117117
intlen,
118118
boolneed_escapes);
119119

120+
/*
121+
* Utility function to check if a string is a valid JSON number.
122+
*
123+
* str agrument does not need to be nul-terminated.
124+
*/
125+
externboolIsValidJsonNumber(constchar*str,intlen);
126+
120127
#endif/* JSONAPI_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp