Changeset: 65505e1974b0 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/65505e1974b0
Added Files:
        monetdb5/modules/atoms/pg_jsonpath/jsonpath.c
        monetdb5/modules/atoms/pg_jsonpath/jsonpath.h
        monetdb5/modules/atoms/pg_jsonpath/jsonpath_gram.y
        monetdb5/modules/atoms/pg_jsonpath/jsonpath_internal.h
        monetdb5/modules/atoms/pg_jsonpath/jsonpath_scan.l
Branch: json-extend
Log Message:

copy in postgres jsonpath source files


diffs (truncated from 3345 to 300 lines):

diff --git a/monetdb5/modules/atoms/pg_jsonpath/jsonpath.c 
b/monetdb5/modules/atoms/pg_jsonpath/jsonpath.c
new file mode 100644
--- /dev/null
+++ b/monetdb5/modules/atoms/pg_jsonpath/jsonpath.c
@@ -0,0 +1,1529 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonpath.c
+ *      Input/output and supporting routines for jsonpath
+ *
+ * jsonpath expression is a chain of path items.  First path item is $, $var,
+ * literal or arithmetic expression.  Subsequent path items are accessors
+ * (.key, .*, [subscripts], [*]), filters (? (predicate)) and methods (.type(),
+ * .size() etc).
+ *
+ * For instance, structure of path items for simple expression:
+ *
+ *             $.a[*].type()
+ *
+ * is pretty evident:
+ *
+ *             $ => .a => [*] => .type()
+ *
+ * Some path items such as arithmetic operations, predicates or array
+ * subscripts may comprise subtrees.  For instance, more complex expression
+ *
+ *             ($.a + $[1 to 5, 7] ? (@ > 3).double()).type()
+ *
+ * have following structure of path items:
+ *
+ *                       +  =>  .type()
+ *               ___/ \___
+ *              /                 \
+ *             $ => .a         $  =>  []  =>   ?  =>  .double()
+ *                                               _||_          |
+ *                                              /        \     >
+ *                                             to        to   / \
+ *                                        / \    /   @   3
+ *                                       1   5  7
+ *
+ * Binary encoding of jsonpath constitutes a sequence of 4-bytes aligned
+ * variable-length path items connected by links.  Every item has a header
+ * consisting of item type (enum JsonPathItemType) and offset of next item
+ * (zero means no next item).  After the header, item may have payload
+ * depending on item type.  For instance, payload of '.key' accessor item is
+ * length of key name and key name itself.  Payload of '>' arithmetic operator
+ * item is offsets of right and left operands.
+ *
+ * So, binary representation of sample expression above is:
+ * (bottom arrows are next links, top lines are argument links)
+ *
+ *                                                               _____
+ *              _____                            ___/____ \                    
        __
+ *       _ /_    \             _____/__/____ \ \          __    _ /_ \
+ *      / /  \    \       /    /  /     \ \ \    /  \  / /  \ \
+ * +(LR)  $ .a $  [](* to *, * to *) 1 5 7 ?(A)  >(LR)   @ 3 .double() .type()
+ * |     |  ^  |  ^|                                            ^|             
                          ^                ^
+ * |     |__|  |__||________________________||___________________|             
   |
+ * |_______________________________________________________________________|
+ *
+ * Copyright (c) 2019-2024, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *     src/backend/utils/adt/jsonpath.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "catalog/pg_type.h"
+#include "lib/stringinfo.h"
+#include "libpq/pqformat.h"
+#include "miscadmin.h"
+#include "nodes/miscnodes.h"
+#include "nodes/nodeFuncs.h"
+#include "utils/fmgrprotos.h"
+#include "utils/formatting.h"
+#include "utils/json.h"
+#include "utils/jsonpath.h"
+
+
+static Datum jsonPathFromCstring(char *in, int len, struct Node *escontext);
+static char *jsonPathToCstring(StringInfo out, JsonPath *in,
+                                                          int estimated_len);
+static bool flattenJsonPathParseItem(StringInfo buf, int *result,
+                                                                        struct 
Node *escontext,
+                                                                        
JsonPathParseItem *item,
+                                                                        int 
nestingLevel, bool insideArraySubscript);
+static void alignStringInfoInt(StringInfo buf);
+static int32 reserveSpaceForItemPointer(StringInfo buf);
+static void printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
+                                                         bool printBracketes);
+static int     operationPriority(JsonPathItemType op);
+
+
+/**************************** INPUT/OUTPUT ********************************/
+
+/*
+ * jsonpath type input function
+ */
+Datum
+jsonpath_in(PG_FUNCTION_ARGS)
+{
+       char       *in = PG_GETARG_CSTRING(0);
+       int                     len = strlen(in);
+
+       return jsonPathFromCstring(in, len, fcinfo->context);
+}
+
+/*
+ * jsonpath type recv function
+ *
+ * The type is sent as text in binary mode, so this is almost the same
+ * as the input function, but it's prefixed with a version number so we
+ * can change the binary format sent in future if necessary. For now,
+ * only version 1 is supported.
+ */
+Datum
+jsonpath_recv(PG_FUNCTION_ARGS)
+{
+       StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+       int                     version = pq_getmsgint(buf, 1);
+       char       *str;
+       int                     nbytes;
+
+       if (version == JSONPATH_VERSION)
+               str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+       else
+               elog(ERROR, "unsupported jsonpath version number: %d", version);
+
+       return jsonPathFromCstring(str, nbytes, NULL);
+}
+
+/*
+ * jsonpath type output function
+ */
+Datum
+jsonpath_out(PG_FUNCTION_ARGS)
+{
+       JsonPath   *in = PG_GETARG_JSONPATH_P(0);
+
+       PG_RETURN_CSTRING(jsonPathToCstring(NULL, in, VARSIZE(in)));
+}
+
+/*
+ * jsonpath type send function
+ *
+ * Just send jsonpath as a version number, then a string of text
+ */
+Datum
+jsonpath_send(PG_FUNCTION_ARGS)
+{
+       JsonPath   *in = PG_GETARG_JSONPATH_P(0);
+       StringInfoData buf;
+       StringInfoData jtext;
+       int                     version = JSONPATH_VERSION;
+
+       initStringInfo(&jtext);
+       (void) jsonPathToCstring(&jtext, in, VARSIZE(in));
+
+       pq_begintypsend(&buf);
+       pq_sendint8(&buf, version);
+       pq_sendtext(&buf, jtext.data, jtext.len);
+       pfree(jtext.data);
+
+       PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+/*
+ * Converts C-string to a jsonpath value.
+ *
+ * Uses jsonpath parser to turn string into an AST, then
+ * flattenJsonPathParseItem() does second pass turning AST into binary
+ * representation of jsonpath.
+ */
+static Datum
+jsonPathFromCstring(char *in, int len, struct Node *escontext)
+{
+       JsonPathParseResult *jsonpath = parsejsonpath(in, len, escontext);
+       JsonPath   *res;
+       StringInfoData buf;
+
+       if (SOFT_ERROR_OCCURRED(escontext))
+               return (Datum) 0;
+
+       if (!jsonpath)
+               ereturn(escontext, (Datum) 0,
+                               (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                                errmsg("invalid input syntax for type %s: 
\"%s\"", "jsonpath",
+                                               in)));
+
+       initStringInfo(&buf);
+       enlargeStringInfo(&buf, 4 * len /* estimation */ );
+
+       appendStringInfoSpaces(&buf, JSONPATH_HDRSZ);
+
+       if (!flattenJsonPathParseItem(&buf, NULL, escontext,
+                                                                 
jsonpath->expr, 0, false))
+               return (Datum) 0;
+
+       res = (JsonPath *) buf.data;
+       SET_VARSIZE(res, buf.len);
+       res->header = JSONPATH_VERSION;
+       if (jsonpath->lax)
+               res->header |= JSONPATH_LAX;
+
+       PG_RETURN_JSONPATH_P(res);
+}
+
+/*
+ * Converts jsonpath value to a C-string.
+ *
+ * If 'out' argument is non-null, the resulting C-string is stored inside the
+ * StringBuffer.  The resulting string is always returned.
+ */
+static char *
+jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
+{
+       StringInfoData buf;
+       JsonPathItem v;
+
+       if (!out)
+       {
+               out = &buf;
+               initStringInfo(out);
+       }
+       enlargeStringInfo(out, estimated_len);
+
+       if (!(in->header & JSONPATH_LAX))
+               appendStringInfoString(out, "strict ");
+
+       jspInit(&v, in);
+       printJsonPathItem(out, &v, false, true);
+
+       return out->data;
+}
+
+/*
+ * Recursive function converting given jsonpath parse item and all its
+ * children into a binary representation.
+ */
+static bool
+flattenJsonPathParseItem(StringInfo buf, int *result, struct Node *escontext,
+                                                JsonPathParseItem *item, int 
nestingLevel,
+                                                bool insideArraySubscript)
+{
+       /* position from beginning of jsonpath data */
+       int32           pos = buf->len - JSONPATH_HDRSZ;
+       int32           chld;
+       int32           next;
+       int                     argNestingLevel = 0;
+
+       check_stack_depth();
+       CHECK_FOR_INTERRUPTS();
+
+       appendStringInfoChar(buf, (char) (item->type));
+
+       /*
+        * We align buffer to int32 because a series of int32 values often goes
+        * after the header, and we want to read them directly by dereferencing
+        * int32 pointer (see jspInitByBuffer()).
+        */
+       alignStringInfoInt(buf);
+
+       /*
+        * Reserve space for next item pointer.  Actual value will be recorded
+        * later, after next and children items processing.
+        */
+       next = reserveSpaceForItemPointer(buf);
+
+       switch (item->type)
+       {
+               case jpiString:
+               case jpiVariable:
+               case jpiKey:
+                       appendBinaryStringInfo(buf, &item->value.string.len,
+                                                                  
sizeof(item->value.string.len));
+                       appendBinaryStringInfo(buf, item->value.string.val,
+                                                                  
item->value.string.len);
+                       appendStringInfoChar(buf, '\0');
+                       break;
+               case jpiNumeric:
+                       appendBinaryStringInfo(buf, item->value.numeric,
+                                                                  
VARSIZE(item->value.numeric));
+                       break;
+               case jpiBool:
+                       appendBinaryStringInfo(buf, &item->value.boolean,
+                                                                  
sizeof(item->value.boolean));
+                       break;
+               case jpiAnd:
+               case jpiOr:
+               case jpiEqual:
+               case jpiNotEqual:
+               case jpiLess:
+               case jpiGreater:
+               case jpiLessOrEqual:
+               case jpiGreaterOrEqual:
+               case jpiAdd:
+               case jpiSub:
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to