Changeset: 378cd3d91d93 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/378cd3d91d93
Modified Files:
monetdb5/modules/atoms/json.c
monetdb5/modules/atoms/pg_jsonpath/jsonpath.c
monetdb5/modules/atoms/pg_jsonpath/jsonpath.h
monetdb5/modules/atoms/pg_jsonpath/jsonpath_exec.c
monetdb5/modules/atoms/pg_jsonpath/jsonpath_scan.l
monetdb5/modules/atoms/pg_jsonpath/postgres_defines_internal.h
Branch: json-extend
Log Message:
do error handling
diffs (truncated from 594 to 300 lines):
diff --git a/monetdb5/modules/atoms/json.c b/monetdb5/modules/atoms/json.c
--- a/monetdb5/modules/atoms/json.c
+++ b/monetdb5/modules/atoms/json.c
@@ -1653,12 +1653,16 @@ JSONfilter(json *ret, const json *js, co
return MAL_SUCCEED;
}
- struct Node* escontext = init_escontext();
+ char errmsg[1024] = {0};
+ struct Node* escontext = init_escontext(errmsg); // TODO: can be a
implementation detail of lex and parse. Pass on allocator as parameter
if (!escontext)
throw(MAL, "json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
JsonPathParseResult* path = parsejsonpath(*expr, strlen(*expr),
escontext);
-
+ if (errmsg[0]) {
+ return createException(MAL, SQLSTATE(HY013), "JsonPathQuery
iternal error: %s", errmsg);
+ }
+ assert(path);
yyjson_alc* alc = yyjson_alc_dyn_new(); // TODO initialize this with
gdk memory functions.
yyjson_read_err* read_error = NULL;
@@ -1668,14 +1672,16 @@ JSONfilter(json *ret, const json *js, co
bool error;
List* vars = NULL;
const char *column_name = NULL;
- // TODO pass the result as yyjson document
- yyjson_val *res = JsonPathQuery((Datum) root, path, JSW_UNCONDITIONAL,
&empty, &error, vars, column_name, alc);
+ yyjson_val *res = JsonPathQuery((Datum) root, path, JSW_UNCONDITIONAL,
&empty, &error, vars, column_name, alc, errmsg);
+ if (!res && errmsg[0])
+ return createException(MAL, SQLSTATE(HY013), "JsonPathQuery
iternal error: %s", errmsg);
+
if (!res)
- throw(MAL, "json.unfold", SQLSTATE(HY013) "JsonPathQuery
error");
+ throw(MAL, "json.filter", SQLSTATE(HY013) "JsonPathQuery
error");
size_t* len = NULL;
yyjson_write_err* write_error = NULL;
- char* tmp_res = yyjson_val_write_opts(res, 0, alc, len, write_error);
// TODO use different allocation or doc write
+ char* tmp_res = yyjson_val_write_opts(res, 0, alc, len, write_error);
// TODO use different allocator for result
*ret = GDKstrdup(tmp_res);
yyjson_alc_dyn_free(alc);
diff --git a/monetdb5/modules/atoms/pg_jsonpath/jsonpath.c
b/monetdb5/modules/atoms/pg_jsonpath/jsonpath.c
--- a/monetdb5/modules/atoms/pg_jsonpath/jsonpath.c
+++ b/monetdb5/modules/atoms/pg_jsonpath/jsonpath.c
@@ -140,7 +140,7 @@ jspOperationName(JsonPathItemType type)
case jpiTimestampTz:
return "timestamp_tz";
default:
- elog(ERROR, "unrecognized jsonpath item type: %d",
type);
+ // elog(ERROR, "unrecognized jsonpath item type: %d",
type); TODO error handling
return NULL;
}
}
diff --git a/monetdb5/modules/atoms/pg_jsonpath/jsonpath.h
b/monetdb5/modules/atoms/pg_jsonpath/jsonpath.h
--- a/monetdb5/modules/atoms/pg_jsonpath/jsonpath.h
+++ b/monetdb5/modules/atoms/pg_jsonpath/jsonpath.h
@@ -174,7 +174,7 @@ extern const char *jspOperationName(Json
* Parsing support data structures.
*/
-extern struct Node * init_escontext(void);
+extern struct Node * init_escontext(char* errmsg);
extern JsonPathParseResult *parsejsonpath(const char *str, int len,
struct Node *escontext);
@@ -197,12 +197,12 @@ typedef struct JsonPathVariable
/* SQL/JSON query functions */
-extern bool JsonPathExists(Datum jb, JsonPath *jp, bool *error, List *vars,
yyjson_alc* alc);
+extern bool JsonPathExists(Datum jb, JsonPath *jp, bool *error, List *vars,
yyjson_alc* alc, char* errmsg);
extern JsonbValue *JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper,
bool *empty, bool *error,
List *vars,
- const char *column_name,
yyjson_alc* alc);
+ const char *column_name,
yyjson_alc* alc, char* errmsg);
extern JsonbValue *JsonPathValue(Datum jb, JsonPath *jp, bool *empty,
bool *error,
List *vars,
- const char
*column_name, yyjson_alc* alc);
+ const char
*column_name, yyjson_alc* alc, char* errmsg);
#endif
diff --git a/monetdb5/modules/atoms/pg_jsonpath/jsonpath_exec.c
b/monetdb5/modules/atoms/pg_jsonpath/jsonpath_exec.c
--- a/monetdb5/modules/atoms/pg_jsonpath/jsonpath_exec.c
+++ b/monetdb5/modules/atoms/pg_jsonpath/jsonpath_exec.c
@@ -101,6 +101,7 @@ typedef struct JsonPathExecContext
bool throwErrors; /* with "false" all suppressible errors
are
* suppressed */
bool useTz;
+ char* _errmsg;
} JsonPathExecContext;
/* Context for LIKE_REGEX execution. */
@@ -169,8 +170,7 @@ typedef struct JsonTablePlanRowSource
do { \
if (jspThrowErrors(cxt)) \
throw_error; \
- else \
- return jperError; \
+ return jperError; \
} while (0)
typedef JsonPathBool (*JsonPathPredicateCallback) (JsonPathItem *jsp,
@@ -183,7 +183,7 @@ static JsonPathExecResult executeJsonPat
JsonPathGetVarCallback getVar_,
JsonPathCountVarsCallback countVars,
Jsonb *json, bool throwErrors,
-
JsonValueList *result, bool useTz, yyjson_alc* alc);
+
JsonValueList *result, bool useTz, JsonPathExecContext* cxt);
static JsonPathExecResult executeItem(JsonPathExecContext *cxt,
JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found);
static JsonPathExecResult executeItemOptUnwrapTarget(JsonPathExecContext *cxt,
@@ -237,7 +237,7 @@ JsonItemFromDatum(Datum val, Oid typid,
static int JsonbArraySize(JsonbValue *jb);
static JsonPathBool executeComparison(JsonPathItem *cmp, JsonbValue *lv,
JsonbValue *rv, void *p);
-static JsonPathBool compareItems(int32 op, JsonbValue *jb1, JsonbValue *jb2,
+static JsonPathBool compareItems(JsonPathExecContext *cxt, int32 op,
JsonbValue *jb1, JsonbValue *jb2,
bool useTz);
static int compareNumeric(Numeric a, Numeric b);
static JsonPathExecResult getArrayIndex(JsonPathExecContext *cxt,
@@ -288,9 +288,8 @@ static JsonPathExecResult
executeJsonPath(JsonPath *path, void *vars, JsonPathGetVarCallback getVar_,
JsonPathCountVarsCallback countVars,
Jsonb *json, bool throwErrors, JsonValueList
*result,
- bool useTz, yyjson_alc* alc)
+ bool useTz, JsonPathExecContext* cxt)
{
- JsonPathExecContext cxt;
JsonPathExecResult res;
JsonPathItem* jsp;
JsonbValue* jbv;
@@ -300,22 +299,21 @@ executeJsonPath(JsonPath *path, void *va
jbv = json;
- cxt.vars = vars;
- cxt.getVar_ = getVar_;
- cxt.laxMode = (path->lax);
- cxt.ignoreStructuralErrors = cxt.laxMode;
- cxt.root = cxt.current = jbv;
- cxt.baseObject.jbc = NULL;
- cxt.baseObject.id = 0;
+ cxt->vars = vars;
+ cxt->getVar_ = getVar_;
+ cxt->laxMode = (path->lax);
+ cxt->ignoreStructuralErrors = cxt->laxMode;
+ cxt->root = cxt->current = jbv;
+ cxt->baseObject.jbc = NULL;
+ cxt->baseObject.id = 0;
/* 1 + number of base objects in vars */
- cxt.lastGeneratedObjectId = 1 + countVars(vars);
- cxt.innermostArraySize = -1;
- cxt.throwErrors = throwErrors;
- cxt.useTz = useTz;
- cxt.alc = alc;
- cxt.mutable_doc = yyjson_mut_doc_new(alc);
+ cxt->lastGeneratedObjectId = 1 + countVars(vars);
+ cxt->innermostArraySize = -1;
+ cxt->throwErrors = throwErrors;
+ cxt->useTz = useTz;
+ cxt->mutable_doc = yyjson_mut_doc_new(cxt->alc);
- if (jspStrictAbsenceOfErrors(&cxt) && !result)
+ if (jspStrictAbsenceOfErrors(cxt) && !result)
{
/*
* In strict mode we must get a complete list of values to
check that
@@ -323,7 +321,7 @@ executeJsonPath(JsonPath *path, void *va
*/
JsonValueList vals = {0};
- res = executeItem(&cxt, jsp, jbv, &vals);
+ res = executeItem(cxt, jsp, jbv, &vals);
if (jperIsError(res))
return res;
@@ -331,7 +329,7 @@ executeJsonPath(JsonPath *path, void *va
return JsonValueListIsEmpty(&vals) ? jperNotFound : jperOk;
}
- res = executeItem(&cxt, jsp, jbv, result);
+ res = executeItem(cxt, jsp, jbv, result);
Assert(!throwErrors || !jperIsError(res));
@@ -415,11 +413,12 @@ executeItemOptUnwrapTarget(JsonPathExecC
if (cxt->vars == NULL ||
(v =
cxt->getVar_(cxt->vars, cxt->alc , varName, varNameLength,
-
&baseObject, &baseObjectId)) == NULL)
+
&baseObject, &baseObjectId)) == NULL) {
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
-
errmsg("could not find jsonpath variable \"%s\"",
-
pnstrdup(varName, varNameLength))));
+
errmsg("could not find jsonpath variable \"%s\"", varName)));
+ return
jperError;
+
}
if (baseObjectId > 0)
{
@@ -430,6 +429,7 @@ executeItemOptUnwrapTarget(JsonPathExecC
break;
default:
elog(ERROR, "unexpected
jsonpath item type");
+ return jperError;
}
yyjson_doc* doc =
yyjson_mut_val_imut_copy(mut_val, cxt->alc);
v = yyjson_doc_get_root(doc);
@@ -510,8 +510,10 @@ executeItemOptUnwrapTarget(JsonPathExecC
{
bool hasNext = (elem = jsp->next);
- if (JsonbType(jb) != jbvBinary)
+ if (JsonbType(jb) != jbvBinary) {
elog(ERROR, "invalid jsonb object type:
%d", JsonbType(jb));
+ return jperError;
+ }
return executeAnyItem
(cxt, hasNext ? elem : NULL,
@@ -687,15 +689,9 @@ executeItemOptUnwrapTarget(JsonPathExecC
else if (!jspIgnoreStructuralErrors(cxt))
{
Assert(found);
-
- if (!jspThrowErrors(cxt))
- return jperError;
-
- ereport(ERROR,
+ RETURN_ERROR(ereport(ERROR,
(errcode(ERRCODE_SQL_JSON_MEMBER_NOT_FOUND), \
- errmsg("JSON object
does not contain key \"%s\"",
-
pnstrdup(key.val.string.val,
-
key.val.string.len))));
+ errmsg("JSON object
does not contain key \"%s\"", key))));
}
}
else if (unwrap && JsonbType(jb) == jbvArray)
@@ -856,8 +852,10 @@ executeItemOptUnwrapTarget(JsonPathExecC
int last;
bool hasNext = (elem = jsp->next);
- if (cxt->innermostArraySize < 0)
+ if (cxt->innermostArraySize < 0) {
elog(ERROR, "evaluating jsonpath LAST
outside of array subscript");
+ return jperError;
+ }
if (!hasNext && !found)
{
@@ -1047,10 +1045,6 @@ executeItemOptUnwrapTarget(JsonPathExecC
{
case jbvString:
- /*
- * Value is not necessarily
null-terminated, so we do
- * pnstrdup() here.
- */
tmp = (char*)
yyjson_get_str(jb);
break;
case jbvNumeric:
@@ -1089,6 +1083,7 @@ executeItemOptUnwrapTarget(JsonPathExecC
default:
elog(ERROR, "unrecognized jsonpath item type: %d",
jsp->type);
+ return jperError;
}
return res;
@@ -1205,8 +1200,10 @@ executeBoolItem(JsonPathExecContext *cxt
/* since this function recurses, it could be driven to stack overflow */
check_stack_depth();
- if (!canHaveNext && jspHasNext(jsp))
+ if (!canHaveNext && jspHasNext(jsp)) {
elog(ERROR, "boolean jsonpath item cannot have next item");
+ assert(0); // cannot happen
+ }
switch (jsp->type)
{
@@ -1318,6 +1315,7 @@ executeBoolItem(JsonPathExecContext *cxt
default:
elog(ERROR, "invalid boolean jsonpath item type: %d",
jsp->type);
+ assert(0); // cannot happen
return jpbUnknown;
}
}
@@ -1967,7 +1965,7 @@ executeComparison(JsonPathItem *cmp, Jso
{
JsonPathExecContext *cxt = (JsonPathExecContext *) p;
- return compareItems(cmp->type, lv, rv, cxt->useTz);
+ return compareItems(cxt, cmp->type, lv, rv, cxt->useTz);
}
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]