Coverage Report

Created: 2026-11-12 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/include/utils/jsonpath.h
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * jsonpath.h
4
 *  Definitions for jsonpath datatype
5
 *
6
 * Copyright (c) 2019-2026, PostgreSQL Global Development Group
7
 *
8
 * IDENTIFICATION
9
 *  src/include/utils/jsonpath.h
10
 *
11
 *-------------------------------------------------------------------------
12
 */
13
14
#ifndef JSONPATH_H
15
#define JSONPATH_H
16
17
#include "executor/tablefunc.h"
18
#include "fmgr.h"
19
#include "nodes/pg_list.h"
20
#include "nodes/primnodes.h"
21
#include "utils/jsonb.h"
22
23
typedef struct
24
{
25
  int32   vl_len_;    /* varlena header (do not touch directly!) */
26
  uint32    header;     /* version and flags (see below) */
27
  char    data[FLEXIBLE_ARRAY_MEMBER];
28
} JsonPath;
29
30
0
#define JSONPATH_VERSION  (0x01)
31
0
#define JSONPATH_LAX    (0x80000000)
32
0
#define JSONPATH_HDRSZ    (offsetof(JsonPath, data))
33
34
static inline JsonPath *
35
DatumGetJsonPathP(Datum d)
36
0
{
37
0
  return (JsonPath *) PG_DETOAST_DATUM(d);
38
0
}
Unexecuted instantiation: execExpr.c:DatumGetJsonPathP
Unexecuted instantiation: execExprInterp.c:DatumGetJsonPathP
Unexecuted instantiation: nodeTableFuncscan.c:DatumGetJsonPathP
Unexecuted instantiation: clauses.c:DatumGetJsonPathP
Unexecuted instantiation: jsonb_gin.c:DatumGetJsonPathP
Unexecuted instantiation: jsonpath.c:DatumGetJsonPathP
Unexecuted instantiation: jsonpath_exec.c:DatumGetJsonPathP
Unexecuted instantiation: jsonpath_gram.c:DatumGetJsonPathP
Unexecuted instantiation: jsonpath_scan.c:DatumGetJsonPathP
39
40
static inline JsonPath *
41
DatumGetJsonPathPCopy(Datum d)
42
0
{
43
0
  return (JsonPath *) PG_DETOAST_DATUM_COPY(d);
44
0
}
Unexecuted instantiation: execExpr.c:DatumGetJsonPathPCopy
Unexecuted instantiation: execExprInterp.c:DatumGetJsonPathPCopy
Unexecuted instantiation: nodeTableFuncscan.c:DatumGetJsonPathPCopy
Unexecuted instantiation: clauses.c:DatumGetJsonPathPCopy
Unexecuted instantiation: jsonb_gin.c:DatumGetJsonPathPCopy
Unexecuted instantiation: jsonpath.c:DatumGetJsonPathPCopy
Unexecuted instantiation: jsonpath_exec.c:DatumGetJsonPathPCopy
Unexecuted instantiation: jsonpath_gram.c:DatumGetJsonPathPCopy
Unexecuted instantiation: jsonpath_scan.c:DatumGetJsonPathPCopy
45
46
0
#define PG_GETARG_JSONPATH_P(x)     DatumGetJsonPathP(PG_GETARG_DATUM(x))
47
0
#define PG_GETARG_JSONPATH_P_COPY(x)  DatumGetJsonPathPCopy(PG_GETARG_DATUM(x))
48
0
#define PG_RETURN_JSONPATH_P(p)     PG_RETURN_POINTER(p)
49
50
0
#define jspIsScalar(type) ((type) >= jpiNull && (type) <= jpiBool)
51
52
/*
53
 * All node's type of jsonpath expression
54
 *
55
 * These become part of the on-disk representation of the jsonpath type.
56
 * Therefore, to preserve pg_upgradability, the order must not be changed, and
57
 * new values must be added at the end.
58
 *
59
 * It is recommended that switch cases etc. in other parts of the code also
60
 * use this order, to maintain some consistency.
61
 */
62
typedef enum JsonPathItemType
63
{
64
  jpiNull = jbvNull,      /* NULL literal */
65
  jpiString = jbvString,    /* string literal */
66
  jpiNumeric = jbvNumeric,  /* numeric literal */
67
  jpiBool = jbvBool,      /* boolean literal: TRUE or FALSE */
68
  jpiAnd,           /* predicate && predicate */
69
  jpiOr,            /* predicate || predicate */
70
  jpiNot,           /* ! predicate */
71
  jpiIsUnknown,       /* (predicate) IS UNKNOWN */
72
  jpiEqual,         /* expr == expr */
73
  jpiNotEqual,        /* expr != expr */
74
  jpiLess,          /* expr < expr */
75
  jpiGreater,         /* expr > expr */
76
  jpiLessOrEqual,       /* expr <= expr */
77
  jpiGreaterOrEqual,      /* expr >= expr */
78
  jpiAdd,           /* expr + expr */
79
  jpiSub,           /* expr - expr */
80
  jpiMul,           /* expr * expr */
81
  jpiDiv,           /* expr / expr */
82
  jpiMod,           /* expr % expr */
83
  jpiPlus,          /* + expr */
84
  jpiMinus,         /* - expr */
85
  jpiAnyArray,        /* [*] */
86
  jpiAnyKey,          /* .* */
87
  jpiIndexArray,        /* [subscript, ...] */
88
  jpiAny,           /* .** */
89
  jpiKey,           /* .key */
90
  jpiCurrent,         /* @ */
91
  jpiRoot,          /* $ */
92
  jpiVariable,        /* $variable */
93
  jpiFilter,          /* ? (predicate) */
94
  jpiExists,          /* EXISTS (expr) predicate */
95
  jpiType,          /* .type() item method */
96
  jpiSize,          /* .size() item method */
97
  jpiAbs,           /* .abs() item method */
98
  jpiFloor,         /* .floor() item method */
99
  jpiCeiling,         /* .ceiling() item method */
100
  jpiDouble,          /* .double() item method */
101
  jpiDatetime,        /* .datetime() item method */
102
  jpiKeyValue,        /* .keyvalue() item method */
103
  jpiSubscript,       /* array subscript: 'expr' or 'expr TO expr' */
104
  jpiLast,          /* LAST array subscript */
105
  jpiStartsWith,        /* STARTS WITH predicate */
106
  jpiLikeRegex,       /* LIKE_REGEX predicate */
107
  jpiBigint,          /* .bigint() item method */
108
  jpiBoolean,         /* .boolean() item method */
109
  jpiDate,          /* .date() item method */
110
  jpiDecimal,         /* .decimal() item method */
111
  jpiInteger,         /* .integer() item method */
112
  jpiNumber,          /* .number() item method */
113
  jpiStringFunc,        /* .string() item method */
114
  jpiTime,          /* .time() item method */
115
  jpiTimeTz,          /* .time_tz() item method */
116
  jpiTimestamp,       /* .timestamp() item method */
117
  jpiTimestampTz,       /* .timestamp_tz() item method */
118
  jpiStrReplace,        /* .replace() item method */
119
  jpiStrLower,        /* .lower() item method */
120
  jpiStrUpper,        /* .upper() item method */
121
  jpiStrLtrim,        /* .ltrim() item method */
122
  jpiStrRtrim,        /* .rtrim() item method */
123
  jpiStrBtrim,        /* .btrim() item method */
124
  jpiStrInitcap,        /* .initcap() item method */
125
  jpiStrSplitPart,      /* .split_part() item method */
126
} JsonPathItemType;
127
128
/* XQuery regex mode flags for LIKE_REGEX predicate */
129
0
#define JSP_REGEX_ICASE   0x01  /* i flag, case insensitive */
130
0
#define JSP_REGEX_DOTALL  0x02  /* s flag, dot matches newline */
131
0
#define JSP_REGEX_MLINE   0x04  /* m flag, ^/$ match at newlines */
132
0
#define JSP_REGEX_WSPACE  0x08  /* x flag, ignore whitespace in pattern */
133
0
#define JSP_REGEX_QUOTE   0x10  /* q flag, no special characters */
134
135
/*
136
 * Support functions to parse/construct binary value.
137
 * Unlike many other representation of expression the first/main
138
 * node is not an operation but left operand of expression. That
139
 * allows to implement cheap follow-path descending in jsonb
140
 * structure and then execute operator with right operand
141
 */
142
143
typedef struct JsonPathItem
144
{
145
  JsonPathItemType type;
146
147
  /* position form base to next node */
148
  int32   nextPos;
149
150
  /*
151
   * pointer into JsonPath value to current node, all positions of current
152
   * are relative to this base
153
   */
154
  char     *base;
155
156
  union
157
  {
158
    /* classic operator with two operands: and, or etc */
159
    struct
160
    {
161
      int32   left;
162
      int32   right;
163
    }     args;
164
165
    /* any unary operation */
166
    int32   arg;
167
168
    /* storage for jpiIndexArray: indexes of array */
169
    struct
170
    {
171
      int32   nelems;
172
      struct
173
      {
174
        int32   from;
175
        int32   to;
176
      }      *elems;
177
    }     array;
178
179
    /* jpiAny: levels */
180
    struct
181
    {
182
      uint32    first;
183
      uint32    last;
184
    }     anybounds;
185
186
    struct
187
    {
188
      char     *data; /* for bool, numeric and string/key */
189
      int32   datalen;  /* filled only for string/key */
190
    }     value;
191
192
    struct
193
    {
194
      int32   expr;
195
      char     *pattern;
196
      int32   patternlen;
197
      uint32    flags;
198
    }     like_regex;
199
  }     content;
200
} JsonPathItem;
201
202
0
#define jspHasNext(jsp) ((jsp)->nextPos > 0)
203
204
extern void jspInit(JsonPathItem *v, JsonPath *js);
205
extern void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos);
206
extern bool jspGetNext(JsonPathItem *v, JsonPathItem *a);
207
extern void jspGetArg(JsonPathItem *v, JsonPathItem *a);
208
extern void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a);
209
extern void jspGetRightArg(JsonPathItem *v, JsonPathItem *a);
210
extern Numeric jspGetNumeric(JsonPathItem *v);
211
extern bool jspGetBool(JsonPathItem *v);
212
extern char *jspGetString(JsonPathItem *v, int32 *len);
213
extern bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from,
214
                 JsonPathItem *to, int i);
215
extern bool jspIsMutable(JsonPath *path, List *varnames, List *varexprs);
216
217
extern const char *jspOperationName(JsonPathItemType type);
218
219
/*
220
 * Parsing support data structures.
221
 */
222
223
typedef struct JsonPathParseItem JsonPathParseItem;
224
225
struct JsonPathParseItem
226
{
227
  JsonPathItemType type;
228
  JsonPathParseItem *next;  /* next in path */
229
230
  union
231
  {
232
233
    /* classic operator with two operands: and, or etc */
234
    struct
235
    {
236
      JsonPathParseItem *left;
237
      JsonPathParseItem *right;
238
    }     args;
239
240
    /* any unary operation */
241
    JsonPathParseItem *arg;
242
243
    /* storage for jpiIndexArray: indexes of array */
244
    struct
245
    {
246
      int     nelems;
247
      struct
248
      {
249
        JsonPathParseItem *from;
250
        JsonPathParseItem *to;
251
      }      *elems;
252
    }     array;
253
254
    /* jpiAny: levels */
255
    struct
256
    {
257
      uint32    first;
258
      uint32    last;
259
    }     anybounds;
260
261
    struct
262
    {
263
      JsonPathParseItem *expr;
264
      char     *pattern;  /* could not be not null-terminated */
265
      uint32    patternlen;
266
      uint32    flags;
267
    }     like_regex;
268
269
    /* scalars */
270
    Numeric numeric;
271
    bool    boolean;
272
    struct
273
    {
274
      uint32    len;
275
      char     *val;  /* could not be not null-terminated */
276
    }     string;
277
  }     value;
278
};
279
280
typedef struct JsonPathParseResult
281
{
282
  JsonPathParseItem *expr;
283
  bool    lax;
284
} JsonPathParseResult;
285
286
extern JsonPathParseResult *parsejsonpath(const char *str, int len,
287
                      struct Node *escontext);
288
289
extern bool jspConvertRegexFlags(uint32 xflags, int *result,
290
                 struct Node *escontext);
291
292
/*
293
 * Struct for details about external variables passed into jsonpath executor
294
 */
295
typedef struct JsonPathVariable
296
{
297
  char     *name;
298
  int     namelen;    /* strlen(name) as cache for GetJsonPathVar() */
299
  Oid     typid;
300
  int32   typmod;
301
  Datum   value;
302
  bool    isnull;
303
} JsonPathVariable;
304
305
306
/* SQL/JSON query functions */
307
extern bool JsonPathExists(Datum jb, JsonPath *jp, bool *error, List *vars);
308
extern Datum JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper,
309
               bool *empty, bool *error, List *vars,
310
               const char *column_name);
311
extern JsonbValue *JsonPathValue(Datum jb, JsonPath *jp, bool *empty,
312
                 bool *error, List *vars,
313
                 const char *column_name);
314
315
/* For JSON_TABLE() */
316
extern PGDLLIMPORT const TableFuncRoutine JsonbTableRoutine;
317
318
#endif