Jsonb should always display leading zero

This commit is contained in:
gentle_hu
2023-03-01 11:45:02 +08:00
parent 9ca77f6327
commit e134f38892
3 changed files with 89 additions and 69 deletions

View File

@ -19,6 +19,7 @@
#include "utils/jsonapi.h"
#include "utils/jsonb.h"
#include "knl/knl_thread.h"
#include "miscadmin.h"
typedef struct JsonbInState {
JsonbParseState *parseState;
@ -374,78 +375,97 @@ char *JsonbToCString(StringInfo out, JsonbSuperHeader in, int estimated_len)
JsonbValue v;
int level = 0;
bool redo_switch = false;
/*
* Number in jsonb is stored by numeric, we should set display_leading_zero to on,
* otherwise, "0.1" will be displayed as ".1", it is not supposed for a JSON data.
*/
unsigned int original_behavior = u_sess->utils_cxt.behavior_compat_flags;
u_sess->utils_cxt.behavior_compat_flags = original_behavior | OPT_DISPLAY_LEADING_ZERO;
if (out == NULL)
out = makeStringInfo();
PG_TRY();
{
if (out == NULL)
out = makeStringInfo();
enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);
it = JsonbIteratorInit(in);
enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);
it = JsonbIteratorInit(in);
while (redo_switch || ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)) {
redo_switch = false;
switch (type) {
case WJB_BEGIN_ARRAY:
if (!first)
appendBinaryStringInfo(out, ", ", 2);
first = true;
while (redo_switch || ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)) {
redo_switch = false;
switch (type) {
case WJB_BEGIN_ARRAY:
if (!first)
appendBinaryStringInfo(out, ", ", 2);
first = true;
if (!v.array.rawScalar)
appendStringInfoChar(out, '[');
level++;
break;
case WJB_BEGIN_OBJECT:
if (!first)
appendBinaryStringInfo(out, ", ", 2);
first = true;
appendStringInfoCharMacro(out, '{');
if (!v.array.rawScalar)
appendStringInfoChar(out, '[');
level++;
break;
case WJB_BEGIN_OBJECT:
if (!first)
appendBinaryStringInfo(out, ", ", 2);
first = true;
appendStringInfoCharMacro(out, '{');
level++;
break;
case WJB_KEY:
if (!first)
appendBinaryStringInfo(out, ", ", 2);
first = true;
level++;
break;
case WJB_KEY:
if (!first)
appendBinaryStringInfo(out, ", ", 2);
first = true;
/* json rules guarantee this is a string */
jsonb_put_escaped_value(out, &v);
appendBinaryStringInfo(out, ": ", 2);
type = JsonbIteratorNext(&it, &v, false);
if (type == WJB_VALUE) {
first = false;
/* json rules guarantee this is a string */
jsonb_put_escaped_value(out, &v);
} else {
Assert(type == WJB_BEGIN_OBJECT || type == WJB_BEGIN_ARRAY);
/*
* We need to rerun the current switch() since we need to
* output the object which we just got from the iterator
* before calling the iterator again.
*/
redo_switch = true;
}
break;
case WJB_ELEM:
if (!first)
appendBinaryStringInfo(out, ", ", 2);
else
appendBinaryStringInfo(out, ": ", 2);
type = JsonbIteratorNext(&it, &v, false);
if (type == WJB_VALUE) {
first = false;
jsonb_put_escaped_value(out, &v);
} else {
Assert(type == WJB_BEGIN_OBJECT || type == WJB_BEGIN_ARRAY);
/*
* We need to rerun the current switch() since we need to
* output the object which we just got from the iterator
* before calling the iterator again.
*/
redo_switch = true;
}
break;
case WJB_ELEM:
if (!first)
appendBinaryStringInfo(out, ", ", 2);
else
first = false;
jsonb_put_escaped_value(out, &v);
break;
case WJB_END_ARRAY:
level--;
if (!v.array.rawScalar)
appendStringInfoChar(out, ']');
first = false;
jsonb_put_escaped_value(out, &v);
break;
case WJB_END_ARRAY:
level--;
if (!v.array.rawScalar)
appendStringInfoChar(out, ']');
first = false;
break;
case WJB_END_OBJECT:
level--;
appendStringInfoCharMacro(out, '}');
first = false;
break;
default:
elog(ERROR, "unknown flag of jsonb iterator");
break;
case WJB_END_OBJECT:
level--;
appendStringInfoCharMacro(out, '}');
first = false;
break;
default:
elog(ERROR, "unknown flag of jsonb iterator");
}
}
u_sess->utils_cxt.behavior_compat_flags = original_behavior;
Assert(level == 0);
}
Assert(level == 0);
PG_CATCH();
{
u_sess->utils_cxt.behavior_compat_flags = original_behavior;
PG_RE_THROW();
}
PG_END_TRY();
return out->data;
}

View File

@ -110,7 +110,7 @@ referenced column: jsonb
SELECT '0.1'::jsonb; -- OK
jsonb
-------
.1
0.1
(1 row)
SELECT '9223372036854775808'::jsonb; -- OK, even though it's too large for int8

View File

@ -54,9 +54,9 @@ DETAIL: Token "." is invalid.
CONTEXT: JSON data, line 1: -1.5e5....
referenced column: jsonb
select '-1.5e-5'::jsonb;
jsonb
----------
-.000015
jsonb
-----------
-0.000015
(1 row)
select '-1.5e+5'::jsonb;
@ -229,7 +229,7 @@ from cmpjsonb order by 1,2,3,4,5,6,7,8,9;
"" | [] | -1 | f | t | t | t | f | f
"a" | "b" | -1 | f | t | t | t | f | f
"a" | "cc" | -1 | f | t | t | t | f | f
"a" | -.586 | -1 | f | t | t | t | f | f
"a" | -0.586 | -1 | f | t | t | t | f | f
"aa" | "aa" | 0 | t | f | f | t | f | t
"s" | ["s"] | -1 | f | t | t | t | f | f
"true" | true | -1 | f | t | t | t | f | f
@ -291,7 +291,7 @@ from cmpjsonb order by 1,2,3,4,5,6,7,8;
"" | [] | f | t | t | t | f | f
"a" | "b" | f | t | t | t | f | f
"a" | "cc" | f | t | t | t | f | f
"a" | -.586 | f | t | t | t | f | f
"a" | -0.586 | f | t | t | t | f | f
"aa" | "aa" | t | f | f | t | f | t
"s" | ["s"] | f | t | t | t | f | f
"true" | true | f | t | t | t | f | f