Changeset: 639c163bd823 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/639c163bd823
Added Files:
        monetdb5/modules/atoms/pg_jsonpath/jsonpath_exec.c
        monetdb5/modules/atoms/pg_jsonpath/yyjson.c
        monetdb5/modules/atoms/pg_jsonpath/yyjson.h
Modified Files:
        monetdb5/modules/atoms/pg_jsonpath/CMakeLists.txt
Branch: json-extend
Log Message:

import yyjson jsonpath_exec as is


diffs (truncated from 22878 to 300 lines):

diff --git a/monetdb5/modules/atoms/pg_jsonpath/CMakeLists.txt 
b/monetdb5/modules/atoms/pg_jsonpath/CMakeLists.txt
--- a/monetdb5/modules/atoms/pg_jsonpath/CMakeLists.txt
+++ b/monetdb5/modules/atoms/pg_jsonpath/CMakeLists.txt
@@ -26,7 +26,10 @@ BISON_TARGET(jsonpath_parser
 target_sources(pg_jsonpath
   PRIVATE
   ${FLEX_jsonpath_scanner_OUTPUTS}
-  ${BISON_jsonpath_parser_OUTPUT_SOURCE})
+  ${BISON_jsonpath_parser_OUTPUT_SOURCE}
+  yyjson.c # for now just build yyjson directly into pg_jsonpath
+  jsonpath.c
+  jsonpath_exec.c)
 
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/jsonpath_scan.l
   ${CMAKE_CURRENT_BINARY_DIR}/jsonpath_scan.l
@@ -41,7 +44,8 @@ target_link_libraries(pg_jsonpath
   monetdb_config_header
   bat
   sqlinclude
-  sqlcommon)
+  sqlcommon
+  mal)
 
 target_include_directories(pg_jsonpath
   PRIVATE
diff --git a/monetdb5/modules/atoms/pg_jsonpath/jsonpath_exec.c 
b/monetdb5/modules/atoms/pg_jsonpath/jsonpath_exec.c
new file mode 100644
--- /dev/null
+++ b/monetdb5/modules/atoms/pg_jsonpath/jsonpath_exec.c
@@ -0,0 +1,4494 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonpath_exec.c
+ *      Routines for SQL/JSON path execution.
+ *
+ * Jsonpath is executed in the global context stored in JsonPathExecContext,
+ * which is passed to almost every function involved into execution.  Entry
+ * point for jsonpath execution is executeJsonPath() function, which
+ * initializes execution context including initial JsonPathItem and JsonbValue,
+ * flags, stack for calculation of @ in filters.
+ *
+ * The result of jsonpath query execution is enum JsonPathExecResult and
+ * if succeeded sequence of JsonbValue, written to JsonValueList *found, which
+ * is passed through the jsonpath items.  When found == NULL, we're inside
+ * exists-query and we're interested only in whether result is empty.  In this
+ * case execution is stopped once first result item is found, and the only
+ * execution result is JsonPathExecResult.  The values of JsonPathExecResult
+ * are following:
+ * - jperOk                    -- result sequence is not empty
+ * - jperNotFound      -- result sequence is empty
+ * - jperError         -- error occurred during execution
+ *
+ * Jsonpath is executed recursively (see executeItem()) starting form the
+ * first path item (which in turn might be, for instance, an arithmetic
+ * expression evaluated separately).  On each step single JsonbValue obtained
+ * from previous path item is processed.  The result of processing is a
+ * sequence of JsonbValue (probably empty), which is passed to the next path
+ * item one by one.  When there is no next path item, then JsonbValue is added
+ * to the 'found' list.  When found == NULL, then execution functions just
+ * return jperOk (see executeNextItem()).
+ *
+ * Many of jsonpath operations require automatic unwrapping of arrays in lax
+ * mode.  So, if input value is array, then corresponding operation is
+ * processed not on array itself, but on all of its members one by one.
+ * executeItemOptUnwrapTarget() function have 'unwrap' argument, which 
indicates
+ * whether unwrapping of array is needed.  When unwrap == true, each of array
+ * members is passed to executeItemOptUnwrapTarget() again but with unwrap == 
false
+ * in order to avoid subsequent array unwrapping.
+ *
+ * All boolean expressions (predicates) are evaluated by executeBoolItem()
+ * function, which returns tri-state JsonPathBool.  When error is occurred
+ * during predicate execution, it returns jpbUnknown.  According to standard
+ * predicates can be only inside filters.  But we support their usage as
+ * jsonpath expression.  This helps us to implement @@ operator.  In this case
+ * resulting JsonPathBool is transformed into jsonb bool or null.
+ *
+ * Arithmetic and boolean expression are evaluated recursively from expression
+ * tree top down to the leaves.  Therefore, for binary arithmetic expressions
+ * we calculate operands first.  Then we check that results are numeric
+ * singleton lists, calculate the result and pass it to the next path item.
+ *
+ * Copyright (c) 2019-2024, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *     src/backend/utils/adt/jsonpath_exec.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "catalog/pg_collation.h"
+#include "catalog/pg_type.h"
+#include "executor/execExpr.h"
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "nodes/miscnodes.h"
+#include "nodes/nodeFuncs.h"
+#include "regex/regex.h"
+#include "utils/builtins.h"
+#include "utils/date.h"
+#include "utils/datetime.h"
+#include "utils/float.h"
+#include "utils/formatting.h"
+#include "utils/json.h"
+#include "utils/jsonpath.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/timestamp.h"
+
+/*
+ * Represents "base object" and it's "id" for .keyvalue() evaluation.
+ */
+typedef struct JsonBaseObjectInfo
+{
+       JsonbContainer *jbc;
+       int                     id;
+} JsonBaseObjectInfo;
+
+/* Callbacks for executeJsonPath() */
+typedef JsonbValue *(*JsonPathGetVarCallback) (void *vars, char *varName, int 
varNameLen,
+                                                                               
           JsonbValue *baseObject, int *baseObjectId);
+typedef int (*JsonPathCountVarsCallback) (void *vars);
+
+/*
+ * Context of jsonpath execution.
+ */
+typedef struct JsonPathExecContext
+{
+       void       *vars;                       /* variables to substitute into 
jsonpath */
+       JsonPathGetVarCallback getVar;  /* callback to extract a given variable
+                                                                        * from 
'vars' */
+       JsonbValue *root;                       /* for $ evaluation */
+       JsonbValue *current;            /* for @ evaluation */
+       JsonBaseObjectInfo baseObject;  /* "base object" for .keyvalue()
+                                                                        * 
evaluation */
+       int                     lastGeneratedObjectId;  /* "id" counter for 
.keyvalue()
+                                                                               
 * evaluation */
+       int                     innermostArraySize; /* for LAST array index 
evaluation */
+       bool            laxMode;                /* true for "lax" mode, false 
for "strict"
+                                                                * mode */
+       bool            ignoreStructuralErrors; /* with "true" structural 
errors such
+                                                                               
 * as absence of required json item or
+                                                                               
 * unexpected json item type are
+                                                                               
 * ignored */
+       bool            throwErrors;    /* with "false" all suppressible errors 
are
+                                                                * suppressed */
+       bool            useTz;
+} JsonPathExecContext;
+
+/* Context for LIKE_REGEX execution. */
+typedef struct JsonLikeRegexContext
+{
+       text       *regex;
+       int                     cflags;
+} JsonLikeRegexContext;
+
+/* Result of jsonpath predicate evaluation */
+typedef enum JsonPathBool
+{
+       jpbFalse = 0,
+       jpbTrue = 1,
+       jpbUnknown = 2
+} JsonPathBool;
+
+/* Result of jsonpath expression evaluation */
+typedef enum JsonPathExecResult
+{
+       jperOk = 0,
+       jperNotFound = 1,
+       jperError = 2
+} JsonPathExecResult;
+
+#define jperIsError(jper)                      ((jper) == jperError)
+
+/*
+ * List of jsonb values with shortcut for single-value list.
+ */
+typedef struct JsonValueList
+{
+       JsonbValue *singleton;
+       List       *list;
+} JsonValueList;
+
+typedef struct JsonValueListIterator
+{
+       JsonbValue *value;
+       List       *list;
+       ListCell   *next;
+} JsonValueListIterator;
+
+/* Structures for JSON_TABLE execution  */
+
+/*
+ * Struct holding the result of jsonpath evaluation, to be used as source row
+ * for JsonTableGetValue() which in turn computes the values of individual
+ * JSON_TABLE columns.
+ */
+typedef struct JsonTablePlanRowSource
+{
+       Datum           value;
+       bool            isnull;
+} JsonTablePlanRowSource;
+
+/*
+ * State of evaluation of row pattern derived by applying jsonpath given in
+ * a JsonTablePlan to an input document given in the parent TableFunc.
+ */
+typedef struct JsonTablePlanState
+{
+       /* Original plan */
+       JsonTablePlan *plan;
+
+       /* The following fields are only valid for JsonTablePathScan plans */
+
+       /* jsonpath to evaluate against the input doc to get the row pattern */
+       JsonPath   *path;
+
+       /*
+        * Memory context to use when evaluating the row pattern from the 
jsonpath
+        */
+       MemoryContext mcxt;
+
+       /* PASSING arguments passed to jsonpath executor */
+       List       *args;
+
+       /* List and iterator of jsonpath result values */
+       JsonValueList found;
+       JsonValueListIterator iter;
+
+       /* Currently selected row for JsonTableGetValue() to use */
+       JsonTablePlanRowSource current;
+
+       /* Counter for ORDINAL columns */
+       int                     ordinal;
+
+       /* Nested plan, if any */
+       struct JsonTablePlanState *nested;
+
+       /* Left sibling, if any */
+       struct JsonTablePlanState *left;
+
+       /* Right sibling, if any */
+       struct JsonTablePlanState *right;
+
+       /* Parent plan, if this is a nested plan */
+       struct JsonTablePlanState *parent;
+} JsonTablePlanState;
+
+/* Random number to identify JsonTableExecContext for sanity checking */
+#define JSON_TABLE_EXEC_CONTEXT_MAGIC          418352867
+
+typedef struct JsonTableExecContext
+{
+       int                     magic;
+
+       /* State of the plan providing a row evaluated from "root" jsonpath */
+       JsonTablePlanState *rootplanstate;
+
+       /*
+        * Per-column JsonTablePlanStates for all columns including the nested
+        * ones.
+        */
+       JsonTablePlanState **colplanstates;
+} JsonTableExecContext;
+
+/* strict/lax flags is decomposed into four [un]wrap/error flags */
+#define jspStrictAbsenceOfErrors(cxt)  (!(cxt)->laxMode)
+#define jspAutoUnwrap(cxt)                             ((cxt)->laxMode)
+#define jspAutoWrap(cxt)                               ((cxt)->laxMode)
+#define jspIgnoreStructuralErrors(cxt) ((cxt)->ignoreStructuralErrors)
+#define jspThrowErrors(cxt)                            ((cxt)->throwErrors)
+
+/* Convenience macro: return or throw error depending on context */
+#define RETURN_ERROR(throw_error) \
+do { \
+       if (jspThrowErrors(cxt)) \
+               throw_error; \
+       else \
+               return jperError; \
+} while (0)
+
+typedef JsonPathBool (*JsonPathPredicateCallback) (JsonPathItem *jsp,
+                                                                               
                   JsonbValue *larg,
+                                                                               
                   JsonbValue *rarg,
+                                                                               
                   void *param);
+typedef Numeric (*BinaryArithmFunc) (Numeric num1, Numeric num2, bool *error);
+
+static JsonPathExecResult executeJsonPath(JsonPath *path, void *vars,
+                                                                               
  JsonPathGetVarCallback getVar,
+                                                                               
  JsonPathCountVarsCallback countVars,
+                                                                               
  Jsonb *json, bool throwErrors,
+                                                                               
  JsonValueList *result, bool useTz);
+static JsonPathExecResult executeItem(JsonPathExecContext *cxt,
+                                                                         
JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found);
+static JsonPathExecResult executeItemOptUnwrapTarget(JsonPathExecContext *cxt,
+                                                                               
                         JsonPathItem *jsp, JsonbValue *jb,
+                                                                               
                         JsonValueList *found, bool unwrap);
+static JsonPathExecResult executeItemUnwrapTargetArray(JsonPathExecContext 
*cxt,
+                                                                               
                           JsonPathItem *jsp, JsonbValue *jb,
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to