Minor code review for json.c.
Improve commenting, conform to project style for use of ++ etc. No functional changes.
This commit is contained in:
parent
36b7e3da17
commit
f871ef74a5
|
@ -25,9 +25,9 @@
|
||||||
#include "utils/json.h"
|
#include "utils/json.h"
|
||||||
#include "utils/typcache.h"
|
#include "utils/typcache.h"
|
||||||
|
|
||||||
typedef enum
|
typedef enum /* types of JSON values */
|
||||||
{
|
{
|
||||||
JSON_VALUE_INVALID,
|
JSON_VALUE_INVALID, /* non-value tokens are reported as this */
|
||||||
JSON_VALUE_STRING,
|
JSON_VALUE_STRING,
|
||||||
JSON_VALUE_NUMBER,
|
JSON_VALUE_NUMBER,
|
||||||
JSON_VALUE_OBJECT,
|
JSON_VALUE_OBJECT,
|
||||||
|
@ -37,17 +37,17 @@ typedef enum
|
||||||
JSON_VALUE_NULL
|
JSON_VALUE_NULL
|
||||||
} JsonValueType;
|
} JsonValueType;
|
||||||
|
|
||||||
typedef struct
|
typedef struct /* state of JSON lexer */
|
||||||
{
|
{
|
||||||
char *input;
|
char *input; /* whole string being parsed */
|
||||||
char *token_start;
|
char *token_start; /* start of current token within input */
|
||||||
char *token_terminator;
|
char *token_terminator; /* end of previous or current token */
|
||||||
JsonValueType token_type;
|
JsonValueType token_type; /* type of current token, once it's known */
|
||||||
int line_number;
|
int line_number; /* current line number (counting from 1) */
|
||||||
char *line_start;
|
char *line_start; /* start of current line within input (BROKEN!!) */
|
||||||
} JsonLexContext;
|
} JsonLexContext;
|
||||||
|
|
||||||
typedef enum
|
typedef enum /* states of JSON parser */
|
||||||
{
|
{
|
||||||
JSON_PARSE_VALUE, /* expecting a value */
|
JSON_PARSE_VALUE, /* expecting a value */
|
||||||
JSON_PARSE_ARRAY_START, /* saw '[', expecting value or ']' */
|
JSON_PARSE_ARRAY_START, /* saw '[', expecting value or ']' */
|
||||||
|
@ -58,17 +58,18 @@ typedef enum
|
||||||
JSON_PARSE_OBJECT_COMMA /* saw object ',', expecting next label */
|
JSON_PARSE_OBJECT_COMMA /* saw object ',', expecting next label */
|
||||||
} JsonParseState;
|
} JsonParseState;
|
||||||
|
|
||||||
typedef struct JsonParseStack
|
typedef struct JsonParseStack /* the parser state has to be stackable */
|
||||||
{
|
{
|
||||||
JsonParseState state;
|
JsonParseState state;
|
||||||
|
/* currently only need the state enum, but maybe someday more stuff */
|
||||||
} JsonParseStack;
|
} JsonParseStack;
|
||||||
|
|
||||||
typedef enum
|
typedef enum /* required operations on state stack */
|
||||||
{
|
{
|
||||||
JSON_STACKOP_NONE,
|
JSON_STACKOP_NONE, /* no-op */
|
||||||
JSON_STACKOP_PUSH,
|
JSON_STACKOP_PUSH, /* push new JSON_PARSE_VALUE stack item */
|
||||||
JSON_STACKOP_PUSH_WITH_PUSHBACK,
|
JSON_STACKOP_PUSH_WITH_PUSHBACK, /* push, then rescan current token */
|
||||||
JSON_STACKOP_POP
|
JSON_STACKOP_POP /* pop, or expect end of input if no stack */
|
||||||
} JsonStackOp;
|
} JsonStackOp;
|
||||||
|
|
||||||
static void json_validate_cstring(char *input);
|
static void json_validate_cstring(char *input);
|
||||||
|
@ -78,17 +79,28 @@ static void json_lex_number(JsonLexContext *lex, char *s);
|
||||||
static void report_parse_error(JsonParseStack *stack, JsonLexContext *lex);
|
static void report_parse_error(JsonParseStack *stack, JsonLexContext *lex);
|
||||||
static void report_invalid_token(JsonLexContext *lex);
|
static void report_invalid_token(JsonLexContext *lex);
|
||||||
static char *extract_mb_char(char *s);
|
static char *extract_mb_char(char *s);
|
||||||
static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds);
|
static void composite_to_json(Datum composite, StringInfo result,
|
||||||
|
bool use_line_feeds);
|
||||||
static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
|
static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
|
||||||
Datum *vals, bool *nulls, int *valcount,
|
Datum *vals, bool *nulls, int *valcount,
|
||||||
TYPCATEGORY tcategory, Oid typoutputfunc,
|
TYPCATEGORY tcategory, Oid typoutputfunc,
|
||||||
bool use_line_feeds);
|
bool use_line_feeds);
|
||||||
static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds);
|
static void array_to_json_internal(Datum array, StringInfo result,
|
||||||
|
bool use_line_feeds);
|
||||||
|
|
||||||
/* fake type category for JSON so we can distinguish it in datum_to_json */
|
/* fake type category for JSON so we can distinguish it in datum_to_json */
|
||||||
#define TYPCATEGORY_JSON 'j'
|
#define TYPCATEGORY_JSON 'j'
|
||||||
/* letters appearing in numeric output that aren't valid in a JSON number */
|
/* letters appearing in numeric output that aren't valid in a JSON number */
|
||||||
#define NON_NUMERIC_LETTER "NnAaIiFfTtYy"
|
#define NON_NUMERIC_LETTER "NnAaIiFfTtYy"
|
||||||
|
/* chars to consider as part of an alphanumeric token */
|
||||||
|
#define JSON_ALPHANUMERIC_CHAR(c) \
|
||||||
|
(((c) >= 'a' && (c) <= 'z') || \
|
||||||
|
((c) >= 'A' && (c) <= 'Z') || \
|
||||||
|
((c) >= '0' && (c) <= '9') || \
|
||||||
|
(c) == '_' || \
|
||||||
|
IS_HIGHBIT_SET(c))
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Input.
|
* Input.
|
||||||
*/
|
*/
|
||||||
|
@ -99,6 +111,7 @@ json_in(PG_FUNCTION_ARGS)
|
||||||
|
|
||||||
json_validate_cstring(text);
|
json_validate_cstring(text);
|
||||||
|
|
||||||
|
/* Internal representation is the same as text, for now */
|
||||||
PG_RETURN_TEXT_P(cstring_to_text(text));
|
PG_RETURN_TEXT_P(cstring_to_text(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +121,7 @@ json_in(PG_FUNCTION_ARGS)
|
||||||
Datum
|
Datum
|
||||||
json_out(PG_FUNCTION_ARGS)
|
json_out(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
/* we needn't detoast because text_to_cstring will handle that */
|
||||||
Datum txt = PG_GETARG_DATUM(0);
|
Datum txt = PG_GETARG_DATUM(0);
|
||||||
|
|
||||||
PG_RETURN_CSTRING(TextDatumGetCString(txt));
|
PG_RETURN_CSTRING(TextDatumGetCString(txt));
|
||||||
|
@ -119,8 +133,8 @@ json_out(PG_FUNCTION_ARGS)
|
||||||
Datum
|
Datum
|
||||||
json_send(PG_FUNCTION_ARGS)
|
json_send(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
StringInfoData buf;
|
|
||||||
text *t = PG_GETARG_TEXT_PP(0);
|
text *t = PG_GETARG_TEXT_PP(0);
|
||||||
|
StringInfoData buf;
|
||||||
|
|
||||||
pq_begintypsend(&buf);
|
pq_begintypsend(&buf);
|
||||||
pq_sendtext(&buf, VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
|
pq_sendtext(&buf, VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
|
||||||
|
@ -176,7 +190,7 @@ json_validate_cstring(char *input)
|
||||||
|
|
||||||
/* Set up parse stack. */
|
/* Set up parse stack. */
|
||||||
stacksize = 32;
|
stacksize = 32;
|
||||||
stacktop = palloc(sizeof(JsonParseStack) * stacksize);
|
stacktop = (JsonParseStack *) palloc(sizeof(JsonParseStack) * stacksize);
|
||||||
stack = stacktop;
|
stack = stacktop;
|
||||||
stack->state = JSON_PARSE_VALUE;
|
stack->state = JSON_PARSE_VALUE;
|
||||||
|
|
||||||
|
@ -212,8 +226,8 @@ redo:
|
||||||
stack->state = JSON_PARSE_ARRAY_NEXT;
|
stack->state = JSON_PARSE_ARRAY_NEXT;
|
||||||
else if (lex.token_start[0] == ']')
|
else if (lex.token_start[0] == ']')
|
||||||
op = JSON_STACKOP_POP;
|
op = JSON_STACKOP_POP;
|
||||||
else if (lex.token_start[0] == '['
|
else if (lex.token_start[0] == '[' ||
|
||||||
|| lex.token_start[0] == '{')
|
lex.token_start[0] == '{')
|
||||||
{
|
{
|
||||||
stack->state = JSON_PARSE_ARRAY_NEXT;
|
stack->state = JSON_PARSE_ARRAY_NEXT;
|
||||||
op = JSON_STACKOP_PUSH_WITH_PUSHBACK;
|
op = JSON_STACKOP_PUSH_WITH_PUSHBACK;
|
||||||
|
@ -234,15 +248,15 @@ redo:
|
||||||
case JSON_PARSE_OBJECT_START:
|
case JSON_PARSE_OBJECT_START:
|
||||||
if (lex.token_type == JSON_VALUE_STRING)
|
if (lex.token_type == JSON_VALUE_STRING)
|
||||||
stack->state = JSON_PARSE_OBJECT_LABEL;
|
stack->state = JSON_PARSE_OBJECT_LABEL;
|
||||||
else if (lex.token_type == JSON_VALUE_INVALID
|
else if (lex.token_type == JSON_VALUE_INVALID &&
|
||||||
&& lex.token_start[0] == '}')
|
lex.token_start[0] == '}')
|
||||||
op = JSON_STACKOP_POP;
|
op = JSON_STACKOP_POP;
|
||||||
else
|
else
|
||||||
report_parse_error(stack, &lex);
|
report_parse_error(stack, &lex);
|
||||||
break;
|
break;
|
||||||
case JSON_PARSE_OBJECT_LABEL:
|
case JSON_PARSE_OBJECT_LABEL:
|
||||||
if (lex.token_type == JSON_VALUE_INVALID
|
if (lex.token_type == JSON_VALUE_INVALID &&
|
||||||
&& lex.token_start[0] == ':')
|
lex.token_start[0] == ':')
|
||||||
{
|
{
|
||||||
stack->state = JSON_PARSE_OBJECT_NEXT;
|
stack->state = JSON_PARSE_OBJECT_NEXT;
|
||||||
op = JSON_STACKOP_PUSH;
|
op = JSON_STACKOP_PUSH;
|
||||||
|
@ -271,19 +285,21 @@ redo:
|
||||||
(int) stack->state);
|
(int) stack->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push or pop the stack, if needed. */
|
/* Push or pop the state stack, if needed. */
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case JSON_STACKOP_PUSH:
|
case JSON_STACKOP_PUSH:
|
||||||
case JSON_STACKOP_PUSH_WITH_PUSHBACK:
|
case JSON_STACKOP_PUSH_WITH_PUSHBACK:
|
||||||
++stack;
|
stack++;
|
||||||
if (stack >= &stacktop[stacksize])
|
if (stack >= &stacktop[stacksize])
|
||||||
{
|
{
|
||||||
|
/* Need to enlarge the stack. */
|
||||||
int stackoffset = stack - stacktop;
|
int stackoffset = stack - stacktop;
|
||||||
|
|
||||||
stacksize = stacksize + 32;
|
stacksize += 32;
|
||||||
stacktop = repalloc(stacktop,
|
stacktop = (JsonParseStack *)
|
||||||
sizeof(JsonParseStack) * stacksize);
|
repalloc(stacktop,
|
||||||
|
sizeof(JsonParseStack) * stacksize);
|
||||||
stack = stacktop + stackoffset;
|
stack = stacktop + stackoffset;
|
||||||
}
|
}
|
||||||
stack->state = JSON_PARSE_VALUE;
|
stack->state = JSON_PARSE_VALUE;
|
||||||
|
@ -299,7 +315,7 @@ redo:
|
||||||
report_parse_error(NULL, &lex);
|
report_parse_error(NULL, &lex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
--stack;
|
stack--;
|
||||||
break;
|
break;
|
||||||
case JSON_STACKOP_NONE:
|
case JSON_STACKOP_NONE:
|
||||||
/* nothing to do */
|
/* nothing to do */
|
||||||
|
@ -321,15 +337,15 @@ json_lex(JsonLexContext *lex)
|
||||||
while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
|
while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
|
||||||
{
|
{
|
||||||
if (*s == '\n')
|
if (*s == '\n')
|
||||||
++lex->line_number;
|
lex->line_number++;
|
||||||
++s;
|
s++;
|
||||||
}
|
}
|
||||||
lex->token_start = s;
|
lex->token_start = s;
|
||||||
|
|
||||||
/* Determine token type. */
|
/* Determine token type. */
|
||||||
if (strchr("{}[],:", s[0]))
|
if (strchr("{}[],:", s[0]) != NULL)
|
||||||
{
|
{
|
||||||
/* strchr() doesn't return false on a NUL input. */
|
/* strchr() is willing to match a zero byte, so test for that. */
|
||||||
if (s[0] == '\0')
|
if (s[0] == '\0')
|
||||||
{
|
{
|
||||||
/* End of string. */
|
/* End of string. */
|
||||||
|
@ -373,17 +389,16 @@ json_lex(JsonLexContext *lex)
|
||||||
* whole word as an unexpected token, rather than just some
|
* whole word as an unexpected token, rather than just some
|
||||||
* unintuitive prefix thereof.
|
* unintuitive prefix thereof.
|
||||||
*/
|
*/
|
||||||
for (p = s; (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')
|
for (p = s; JSON_ALPHANUMERIC_CHAR(*p); p++)
|
||||||
|| (*p >= '0' && *p <= '9') || *p == '_' || IS_HIGHBIT_SET(*p);
|
/* skip */ ;
|
||||||
++p)
|
|
||||||
;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We got some sort of unexpected punctuation or an otherwise
|
|
||||||
* unexpected character, so just complain about that one character.
|
|
||||||
*/
|
|
||||||
if (p == s)
|
if (p == s)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* We got some sort of unexpected punctuation or an otherwise
|
||||||
|
* unexpected character, so just complain about that one
|
||||||
|
* character.
|
||||||
|
*/
|
||||||
lex->token_terminator = s + 1;
|
lex->token_terminator = s + 1;
|
||||||
report_invalid_token(lex);
|
report_invalid_token(lex);
|
||||||
}
|
}
|
||||||
|
@ -415,9 +430,9 @@ json_lex(JsonLexContext *lex)
|
||||||
static void
|
static void
|
||||||
json_lex_string(JsonLexContext *lex)
|
json_lex_string(JsonLexContext *lex)
|
||||||
{
|
{
|
||||||
char *s = lex->token_start + 1;
|
char *s;
|
||||||
|
|
||||||
for (s = lex->token_start + 1; *s != '"'; ++s)
|
for (s = lex->token_start + 1; *s != '"'; s++)
|
||||||
{
|
{
|
||||||
/* Per RFC4627, these characters MUST be escaped. */
|
/* Per RFC4627, these characters MUST be escaped. */
|
||||||
if ((unsigned char) *s < 32)
|
if ((unsigned char) *s < 32)
|
||||||
|
@ -437,7 +452,7 @@ json_lex_string(JsonLexContext *lex)
|
||||||
else if (*s == '\\')
|
else if (*s == '\\')
|
||||||
{
|
{
|
||||||
/* OK, we have an escape character. */
|
/* OK, we have an escape character. */
|
||||||
++s;
|
s++;
|
||||||
if (*s == '\0')
|
if (*s == '\0')
|
||||||
{
|
{
|
||||||
lex->token_terminator = s;
|
lex->token_terminator = s;
|
||||||
|
@ -448,7 +463,7 @@ json_lex_string(JsonLexContext *lex)
|
||||||
int i;
|
int i;
|
||||||
int ch = 0;
|
int ch = 0;
|
||||||
|
|
||||||
for (i = 1; i <= 4; ++i)
|
for (i = 1; i <= 4; i++)
|
||||||
{
|
{
|
||||||
if (s[i] == '\0')
|
if (s[i] == '\0')
|
||||||
{
|
{
|
||||||
|
@ -474,9 +489,9 @@ json_lex_string(JsonLexContext *lex)
|
||||||
/* Account for the four additional bytes we just parsed. */
|
/* Account for the four additional bytes we just parsed. */
|
||||||
s += 4;
|
s += 4;
|
||||||
}
|
}
|
||||||
else if (!strchr("\"\\/bfnrt", *s))
|
else if (strchr("\"\\/bfnrt", *s) == NULL)
|
||||||
{
|
{
|
||||||
/* Error out. */
|
/* Not a valid string escape, so error out. */
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type json"),
|
errmsg("invalid input syntax for type json"),
|
||||||
|
@ -527,12 +542,12 @@ json_lex_number(JsonLexContext *lex, char *s)
|
||||||
|
|
||||||
/* Part (2): parse main digit string. */
|
/* Part (2): parse main digit string. */
|
||||||
if (*s == '0')
|
if (*s == '0')
|
||||||
++s;
|
s++;
|
||||||
else if (*s >= '1' && *s <= '9')
|
else if (*s >= '1' && *s <= '9')
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
++s;
|
s++;
|
||||||
} while (*s >= '0' && *s <= '9');
|
} while (*s >= '0' && *s <= '9');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -541,14 +556,14 @@ json_lex_number(JsonLexContext *lex, char *s)
|
||||||
/* Part (3): parse optional decimal portion. */
|
/* Part (3): parse optional decimal portion. */
|
||||||
if (*s == '.')
|
if (*s == '.')
|
||||||
{
|
{
|
||||||
++s;
|
s++;
|
||||||
if (*s < '0' || *s > '9')
|
if (*s < '0' || *s > '9')
|
||||||
error = true;
|
error = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
++s;
|
s++;
|
||||||
} while (*s >= '0' && *s <= '9');
|
} while (*s >= '0' && *s <= '9');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -556,26 +571,29 @@ json_lex_number(JsonLexContext *lex, char *s)
|
||||||
/* Part (4): parse optional exponent. */
|
/* Part (4): parse optional exponent. */
|
||||||
if (*s == 'e' || *s == 'E')
|
if (*s == 'e' || *s == 'E')
|
||||||
{
|
{
|
||||||
++s;
|
s++;
|
||||||
if (*s == '+' || *s == '-')
|
if (*s == '+' || *s == '-')
|
||||||
++s;
|
s++;
|
||||||
if (*s < '0' || *s > '9')
|
if (*s < '0' || *s > '9')
|
||||||
error = true;
|
error = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
++s;
|
s++;
|
||||||
} while (*s >= '0' && *s <= '9');
|
} while (*s >= '0' && *s <= '9');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for trailing garbage. */
|
/*
|
||||||
for (p = s; (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')
|
* Check for trailing garbage. As in json_lex(), any alphanumeric stuff
|
||||||
|| (*p >= '0' && *p <= '9') || *p == '_' || IS_HIGHBIT_SET(*p); ++p)
|
* here should be considered part of the token for error-reporting
|
||||||
;
|
* purposes.
|
||||||
|
*/
|
||||||
|
for (p = s; JSON_ALPHANUMERIC_CHAR(*p); p++)
|
||||||
|
error = true;
|
||||||
lex->token_terminator = p;
|
lex->token_terminator = p;
|
||||||
if (p > s || error)
|
if (error)
|
||||||
report_invalid_token(lex);
|
report_invalid_token(lex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +615,7 @@ report_parse_error(JsonParseStack *stack, JsonLexContext *lex)
|
||||||
lex->input),
|
lex->input),
|
||||||
errdetail("The input string ended unexpectedly.")));
|
errdetail("The input string ended unexpectedly.")));
|
||||||
|
|
||||||
/* Work out the offending token. */
|
/* Separate out the offending token. */
|
||||||
toklen = lex->token_terminator - lex->token_start;
|
toklen = lex->token_terminator - lex->token_start;
|
||||||
token = palloc(toklen + 1);
|
token = palloc(toklen + 1);
|
||||||
memcpy(token, lex->token_start, toklen);
|
memcpy(token, lex->token_start, toklen);
|
||||||
|
@ -680,14 +698,15 @@ extract_mb_char(char *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn a scalar Datum into JSON. Hand off a non-scalar datum to
|
* Turn a scalar Datum into JSON, appending the string to "result".
|
||||||
* composite_to_json or array_to_json_internal as appropriate.
|
*
|
||||||
|
* Hand off a non-scalar datum to composite_to_json or array_to_json_internal
|
||||||
|
* as appropriate.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static void
|
||||||
datum_to_json(Datum val, bool is_null, StringInfo result, TYPCATEGORY tcategory,
|
datum_to_json(Datum val, bool is_null, StringInfo result,
|
||||||
Oid typoutputfunc)
|
TYPCATEGORY tcategory, Oid typoutputfunc)
|
||||||
{
|
{
|
||||||
|
|
||||||
char *outputstr;
|
char *outputstr;
|
||||||
|
|
||||||
if (is_null)
|
if (is_null)
|
||||||
|
@ -735,6 +754,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result, TYPCATEGORY tcategory,
|
||||||
outputstr = OidOutputFunctionCall(typoutputfunc, val);
|
outputstr = OidOutputFunctionCall(typoutputfunc, val);
|
||||||
escape_json(result, outputstr);
|
escape_json(result, outputstr);
|
||||||
pfree(outputstr);
|
pfree(outputstr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,9 +768,8 @@ array_dim_to_json(StringInfo result, int dim, int ndims, int *dims, Datum *vals,
|
||||||
bool *nulls, int *valcount, TYPCATEGORY tcategory,
|
bool *nulls, int *valcount, TYPCATEGORY tcategory,
|
||||||
Oid typoutputfunc, bool use_line_feeds)
|
Oid typoutputfunc, bool use_line_feeds)
|
||||||
{
|
{
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
char *sep;
|
const char *sep;
|
||||||
|
|
||||||
Assert(dim < ndims);
|
Assert(dim < ndims);
|
||||||
|
|
||||||
|
@ -797,7 +816,6 @@ array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
|
||||||
int count = 0;
|
int count = 0;
|
||||||
Datum *elements;
|
Datum *elements;
|
||||||
bool *nulls;
|
bool *nulls;
|
||||||
|
|
||||||
int16 typlen;
|
int16 typlen;
|
||||||
bool typbyval;
|
bool typbyval;
|
||||||
char typalign,
|
char typalign,
|
||||||
|
@ -852,7 +870,7 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
|
||||||
*tuple;
|
*tuple;
|
||||||
int i;
|
int i;
|
||||||
bool needsep = false;
|
bool needsep = false;
|
||||||
char *sep;
|
const char *sep;
|
||||||
|
|
||||||
sep = use_line_feeds ? ",\n " : ",";
|
sep = use_line_feeds ? ",\n " : ",";
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue