#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/json.h"
-#include "utils/jsonapi.h"
+#include "utils/jsonfuncs.h"
#include "utils/lsyscache.h"
#include "utils/typcache.h"
static JsonParseErrorType parse_array_element(JsonLexContext *lex, JsonSemAction *sem);
static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem);
static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex);
-static int report_json_context(JsonLexContext *lex);
static char *extract_token(JsonLexContext *lex);
/* the null action object used for pure validation */
}
/*
- * makeJsonLexContext
+ * makeJsonLexContextCstringLen
*
- * lex constructor, with or without StringInfo object
- * for de-escaped lexemes.
+ * lex constructor, with or without StringInfo object for de-escaped lexemes.
*
* Without is better as it makes the processing faster, so only make one
* if really required.
- *
- * If you already have the json as a text* value, use the first of these
- * functions, otherwise use makeJsonLexContextCstringLen().
*/
-JsonLexContext *
-makeJsonLexContext(text *json, bool need_escapes)
-{
- return makeJsonLexContextCstringLen(VARDATA_ANY(json),
- VARSIZE_ANY_EXHDR(json),
- need_escapes);
-}
-
JsonLexContext *
makeJsonLexContextCstringLen(char *json, int len, bool need_escapes)
{
return result;
}
-/*
- * pg_parse_json_or_ereport
- *
- * This fuction is like pg_parse_json, except that it does not return a
- * JsonParseErrorType. Instead, in case of any failure, this function will
- * ereport(ERROR).
- */
-void
-pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
-{
- JsonParseErrorType result;
-
- result = pg_parse_json(lex, sem);
- if (result != JSON_SUCCESS)
- json_ereport_error(result, lex);
-}
-
/*
* json_count_array_elements
*
}
}
-/*
- * Report a JSON error.
- */
-void
-json_ereport_error(JsonParseErrorType error, JsonLexContext *lex)
-{
- if (error == JSON_UNICODE_HIGH_ESCAPE ||
- error == JSON_UNICODE_CODE_POINT_ZERO)
- ereport(ERROR,
- (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
- errmsg("unsupported Unicode escape sequence"),
- errdetail("%s", json_errdetail(error, lex)),
- report_json_context(lex)));
- else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s", "json"),
- errdetail("%s", json_errdetail(error, lex)),
- report_json_context(lex)));
-}
-
/*
* Construct a detail message for a JSON error.
*/
}
}
-/*
- * Report a CONTEXT line for bogus JSON input.
- *
- * lex->token_terminator must be set to identify the spot where we detected
- * the error. Note that lex->token_start might be NULL, in case we recognized
- * error at EOF.
- *
- * The return value isn't meaningful, but we make it non-void so that this
- * can be invoked inside ereport().
- */
-static int
-report_json_context(JsonLexContext *lex)
-{
- const char *context_start;
- const char *context_end;
- const char *line_start;
- int line_number;
- char *ctxt;
- int ctxtlen;
- const char *prefix;
- const char *suffix;
-
- /* Choose boundaries for the part of the input we will display */
- context_start = lex->input;
- context_end = lex->token_terminator;
- line_start = context_start;
- line_number = 1;
- for (;;)
- {
- /* Always advance over newlines */
- if (context_start < context_end && *context_start == '\n')
- {
- context_start++;
- line_start = context_start;
- line_number++;
- continue;
- }
- /* Otherwise, done as soon as we are close enough to context_end */
- if (context_end - context_start < 50)
- break;
- /* Advance to next multibyte character */
- if (IS_HIGHBIT_SET(*context_start))
- context_start += pg_mblen(context_start);
- else
- context_start++;
- }
-
- /*
- * We add "..." to indicate that the excerpt doesn't start at the
- * beginning of the line ... but if we're within 3 characters of the
- * beginning of the line, we might as well just show the whole line.
- */
- if (context_start - line_start <= 3)
- context_start = line_start;
-
- /* Get a null-terminated copy of the data to present */
- ctxtlen = context_end - context_start;
- ctxt = palloc(ctxtlen + 1);
- memcpy(ctxt, context_start, ctxtlen);
- ctxt[ctxtlen] = '\0';
-
- /*
- * Show the context, prefixing "..." if not starting at start of line, and
- * suffixing "..." if not ending at end of line.
- */
- prefix = (context_start > line_start) ? "..." : "";
- suffix = (lex->token_type != JSON_TOKEN_END && context_end - lex->input < lex->input_length && *context_end != '\n' && *context_end != '\r') ? "..." : "";
-
- return errcontext("JSON data, line %d: %s%s%s",
- line_number, prefix, ctxt, suffix);
-}
-
/*
* Extract the current token from a lexing context, for error reporting.
*/
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/json.h"
-#include "utils/jsonapi.h"
#include "utils/jsonb.h"
+#include "utils/jsonfuncs.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
hash_destroy((jso)->val.json_hash); \
} while (0)
+static int report_json_context(JsonLexContext *lex);
+
/* semantic action functions for json_object_keys */
static void okeys_object_field_start(void *state, char *fname, bool isnull);
static void okeys_array_start(void *state);
static void transform_string_values_array_element_start(void *state, bool isnull);
static void transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype);
+/*
+ * pg_parse_json_or_ereport
+ *
+ * This fuction is like pg_parse_json, except that it does not return a
+ * JsonParseErrorType. Instead, in case of any failure, this function will
+ * ereport(ERROR).
+ */
+void
+pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
+{
+ JsonParseErrorType result;
+
+ result = pg_parse_json(lex, sem);
+ if (result != JSON_SUCCESS)
+ json_ereport_error(result, lex);
+}
+
+/*
+ * makeJsonLexContext
+ *
+ * This is like makeJsonLexContextCstringLen, but it accepts a text value
+ * directly.
+ */
+JsonLexContext *
+makeJsonLexContext(text *json, bool need_escapes)
+{
+ return makeJsonLexContextCstringLen(VARDATA_ANY(json),
+ VARSIZE_ANY_EXHDR(json),
+ need_escapes);
+}
+
/*
* SQL function json_object_keys
*
SRF_RETURN_DONE(funcctx);
}
+/*
+ * Report a JSON error.
+ */
+void
+json_ereport_error(JsonParseErrorType error, JsonLexContext *lex)
+{
+ if (error == JSON_UNICODE_HIGH_ESCAPE ||
+ error == JSON_UNICODE_CODE_POINT_ZERO)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
+ errmsg("unsupported Unicode escape sequence"),
+ errdetail("%s", json_errdetail(error, lex)),
+ report_json_context(lex)));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s", "json"),
+ errdetail("%s", json_errdetail(error, lex)),
+ report_json_context(lex)));
+}
+
+/*
+ * Report a CONTEXT line for bogus JSON input.
+ *
+ * lex->token_terminator must be set to identify the spot where we detected
+ * the error. Note that lex->token_start might be NULL, in case we recognized
+ * error at EOF.
+ *
+ * The return value isn't meaningful, but we make it non-void so that this
+ * can be invoked inside ereport().
+ */
+static int
+report_json_context(JsonLexContext *lex)
+{
+ const char *context_start;
+ const char *context_end;
+ const char *line_start;
+ int line_number;
+ char *ctxt;
+ int ctxtlen;
+ const char *prefix;
+ const char *suffix;
+
+ /* Choose boundaries for the part of the input we will display */
+ context_start = lex->input;
+ context_end = lex->token_terminator;
+ line_start = context_start;
+ line_number = 1;
+ for (;;)
+ {
+ /* Always advance over newlines */
+ if (context_start < context_end && *context_start == '\n')
+ {
+ context_start++;
+ line_start = context_start;
+ line_number++;
+ continue;
+ }
+ /* Otherwise, done as soon as we are close enough to context_end */
+ if (context_end - context_start < 50)
+ break;
+ /* Advance to next multibyte character */
+ if (IS_HIGHBIT_SET(*context_start))
+ context_start += pg_mblen(context_start);
+ else
+ context_start++;
+ }
+
+ /*
+ * We add "..." to indicate that the excerpt doesn't start at the
+ * beginning of the line ... but if we're within 3 characters of the
+ * beginning of the line, we might as well just show the whole line.
+ */
+ if (context_start - line_start <= 3)
+ context_start = line_start;
+
+ /* Get a null-terminated copy of the data to present */
+ ctxtlen = context_end - context_start;
+ ctxt = palloc(ctxtlen + 1);
+ memcpy(ctxt, context_start, ctxtlen);
+ ctxt[ctxtlen] = '\0';
+
+ /*
+ * Show the context, prefixing "..." if not starting at start of line, and
+ * suffixing "..." if not ending at end of line.
+ */
+ prefix = (context_start > line_start) ? "..." : "";
+ suffix = (lex->token_type != JSON_TOKEN_END && context_end - lex->input < lex->input_length && *context_end != '\n' && *context_end != '\r') ? "..." : "";
+
+ return errcontext("JSON data, line %d: %s%s%s",
+ line_number, prefix, ctxt, suffix);
+}
+
Datum
json_object_keys(PG_FUNCTION_ARGS)
extern JsonParseErrorType pg_parse_json(JsonLexContext *lex,
JsonSemAction *sem);
-/*
- * Same thing, but signal errors via ereport(ERROR) instead of returning
- * a result code.
- */
-extern void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem);
-
/* the null action object used for pure validation */
extern JsonSemAction nullSemAction;
int *elements);
/*
- * constructors for JsonLexContext, with or without strval element.
+ * constructor for JsonLexContext, with or without strval element.
* If supplied, the strval element will contain a de-escaped version of
* the lexeme. However, doing this imposes a performance penalty, so
* it should be avoided if the de-escaped lexeme is not required.
- *
- * If you already have the json as a text* value, use the first of these
- * functions, otherwise use makeJsonLexContextCstringLen().
*/
-extern JsonLexContext *makeJsonLexContext(text *json, bool need_escapes);
extern JsonLexContext *makeJsonLexContextCstringLen(char *json,
int len,
bool need_escapes);
/* lex one token */
extern JsonParseErrorType json_lex(JsonLexContext *lex);
-/* report an error during json lexing or parsing */
-extern void json_ereport_error(JsonParseErrorType error, JsonLexContext *lex);
-
/* construct an error detail string for a json error */
extern char *json_errdetail(JsonParseErrorType error, JsonLexContext *lex);
/* an action that will be applied to each value in transform_json(b)_values functions */
typedef text *(*JsonTransformStringValuesAction) (void *state, char *elem_value, int elem_len);
+/* build a JsonLexContext from a text datum */
+extern JsonLexContext *makeJsonLexContext(text *json, bool need_escapes);
+
+/* try to parse json, and ereport(ERROR) on failure */
+extern void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem);
+
+/* report an error during json lexing or parsing */
+extern void json_ereport_error(JsonParseErrorType error, JsonLexContext *lex);
+
extern uint32 parse_jsonb_index_flags(Jsonb *jb);
extern void iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state,
JsonIterateStringValuesAction action);