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;
}