PostgreSQL Source Code  git master
jsonb_gin.c File Reference
#include "postgres.h"
#include "access/gin.h"
#include "access/stratnum.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/hashutils.h"
#include "utils/jsonb.h"
#include "utils/jsonpath.h"
#include "utils/varlena.h"
Include dependency graph for jsonb_gin.c:

Go to the source code of this file.

Data Structures

struct  PathHashStack
 
struct  GinEntries
 
struct  JsonPathGinNode
 
struct  JsonPathGinPathItem
 
union  JsonPathGinPath
 
struct  JsonPathGinContext
 

Typedefs

typedef struct PathHashStack PathHashStack
 
typedef struct GinEntries GinEntries
 
typedef enum JsonPathGinNodeType JsonPathGinNodeType
 
typedef struct JsonPathGinNode JsonPathGinNode
 
typedef struct JsonPathGinPathItem JsonPathGinPathItem
 
typedef union JsonPathGinPath JsonPathGinPath
 
typedef struct JsonPathGinContext JsonPathGinContext
 
typedef bool(* JsonPathGinAddPathItemFunc) (JsonPathGinPath *path, JsonPathItem *jsp)
 
typedef List *(* JsonPathGinExtractNodesFunc) (JsonPathGinContext *cxt, JsonPathGinPath path, JsonbValue *scalar, List *nodes)
 

Enumerations

enum  JsonPathGinNodeType { JSP_GIN_OR, JSP_GIN_AND, JSP_GIN_ENTRY }
 

Functions

static Datum make_text_key (char flag, const char *str, int len)
 
static Datum make_scalar_key (const JsonbValue *scalarVal, bool is_key)
 
static JsonPathGinNodeextract_jsp_bool_expr (JsonPathGinContext *cxt, JsonPathGinPath path, JsonPathItem *jsp, bool not)
 
static void init_gin_entries (GinEntries *entries, int preallocated)
 
static int add_gin_entry (GinEntries *entries, Datum entry)
 
Datum gin_compare_jsonb (PG_FUNCTION_ARGS)
 
Datum gin_extract_jsonb (PG_FUNCTION_ARGS)
 
static bool jsonb_ops__add_path_item (JsonPathGinPath *path, JsonPathItem *jsp)
 
static bool jsonb_path_ops__add_path_item (JsonPathGinPath *path, JsonPathItem *jsp)
 
static JsonPathGinNodemake_jsp_entry_node (Datum entry)
 
static JsonPathGinNodemake_jsp_entry_node_scalar (JsonbValue *scalar, bool iskey)
 
static JsonPathGinNodemake_jsp_expr_node (JsonPathGinNodeType type, int nargs)
 
static JsonPathGinNodemake_jsp_expr_node_args (JsonPathGinNodeType type, List *args)
 
static JsonPathGinNodemake_jsp_expr_node_binary (JsonPathGinNodeType type, JsonPathGinNode *arg1, JsonPathGinNode *arg2)
 
static Listjsonb_ops__extract_nodes (JsonPathGinContext *cxt, JsonPathGinPath path, JsonbValue *scalar, List *nodes)
 
static Listjsonb_path_ops__extract_nodes (JsonPathGinContext *cxt, JsonPathGinPath path, JsonbValue *scalar, List *nodes)
 
static Listextract_jsp_path_expr_nodes (JsonPathGinContext *cxt, JsonPathGinPath path, JsonPathItem *jsp, JsonbValue *scalar)
 
static JsonPathGinNodeextract_jsp_path_expr (JsonPathGinContext *cxt, JsonPathGinPath path, JsonPathItem *jsp, JsonbValue *scalar)
 
static void emit_jsp_gin_entries (JsonPathGinNode *node, GinEntries *entries)
 
static Datumextract_jsp_query (JsonPath *jp, StrategyNumber strat, bool pathOps, int32 *nentries, Pointer **extra_data)
 
static GinTernaryValue execute_jsp_gin_node (JsonPathGinNode *node, void *check, bool ternary)
 
Datum gin_extract_jsonb_query (PG_FUNCTION_ARGS)
 
Datum gin_consistent_jsonb (PG_FUNCTION_ARGS)
 
Datum gin_triconsistent_jsonb (PG_FUNCTION_ARGS)
 
Datum gin_extract_jsonb_path (PG_FUNCTION_ARGS)
 
Datum gin_extract_jsonb_query_path (PG_FUNCTION_ARGS)
 
Datum gin_consistent_jsonb_path (PG_FUNCTION_ARGS)
 
Datum gin_triconsistent_jsonb_path (PG_FUNCTION_ARGS)
 

Typedef Documentation

◆ GinEntries

typedef struct GinEntries GinEntries

◆ JsonPathGinAddPathItemFunc

typedef bool(* JsonPathGinAddPathItemFunc) (JsonPathGinPath *path, JsonPathItem *jsp)

Definition at line 134 of file jsonb_gin.c.

◆ JsonPathGinContext

Definition at line 131 of file jsonb_gin.c.

◆ JsonPathGinExtractNodesFunc

typedef List*(* JsonPathGinExtractNodesFunc) (JsonPathGinContext *cxt, JsonPathGinPath path, JsonbValue *scalar, List *nodes)

Definition at line 141 of file jsonb_gin.c.

◆ JsonPathGinNode

Definition at line 94 of file jsonb_gin.c.

◆ JsonPathGinNodeType

◆ JsonPathGinPath

◆ JsonPathGinPathItem

◆ PathHashStack

typedef struct PathHashStack PathHashStack

Enumeration Type Documentation

◆ JsonPathGinNodeType

Enumerator
JSP_GIN_OR 
JSP_GIN_AND 
JSP_GIN_ENTRY 

Definition at line 87 of file jsonb_gin.c.

Function Documentation

◆ add_gin_entry()

static int add_gin_entry ( GinEntries entries,
Datum  entry 
)
static

Definition at line 172 of file jsonb_gin.c.

References GinEntries::allocated, GinEntries::buf, GinEntries::count, palloc(), and repalloc().

Referenced by emit_jsp_gin_entries(), gin_extract_jsonb(), and gin_extract_jsonb_path().

173 {
174  int id = entries->count;
175 
176  if (entries->count >= entries->allocated)
177  {
178  if (entries->allocated)
179  {
180  entries->allocated *= 2;
181  entries->buf = repalloc(entries->buf,
182  sizeof(Datum) * entries->allocated);
183  }
184  else
185  {
186  entries->allocated = 8;
187  entries->buf = palloc(sizeof(Datum) * entries->allocated);
188  }
189  }
190 
191  entries->buf[entries->count++] = entry;
192 
193  return id;
194 }
int count
Definition: jsonb_gin.c:83
Datum * buf
Definition: jsonb_gin.c:82
uintptr_t Datum
Definition: postgres.h:367
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
int allocated
Definition: jsonb_gin.c:84
void * palloc(Size size)
Definition: mcxt.c:949

◆ emit_jsp_gin_entries()

static void emit_jsp_gin_entries ( JsonPathGinNode node,
GinEntries entries 
)
static

Definition at line 719 of file jsonb_gin.c.

References add_gin_entry(), JsonPathGinNode::args, check_stack_depth(), JsonPathGinNode::entryDatum, JsonPathGinNode::entryIndex, i, JSP_GIN_AND, JSP_GIN_ENTRY, JSP_GIN_OR, JsonPathGinNode::nargs, JsonPathGinNode::type, and JsonPathGinNode::val.

Referenced by extract_jsp_query().

720 {
722 
723  switch (node->type)
724  {
725  case JSP_GIN_ENTRY:
726  /* replace datum with its index in the array */
727  node->val.entryIndex = add_gin_entry(entries, node->val.entryDatum);
728  break;
729 
730  case JSP_GIN_OR:
731  case JSP_GIN_AND:
732  {
733  int i;
734 
735  for (i = 0; i < node->val.nargs; i++)
736  emit_jsp_gin_entries(node->args[i], entries);
737 
738  break;
739  }
740  }
741 }
JsonPathGinNode * args[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb_gin.c:108
static int add_gin_entry(GinEntries *entries, Datum entry)
Definition: jsonb_gin.c:172
Datum entryDatum
Definition: jsonb_gin.c:105
static void emit_jsp_gin_entries(JsonPathGinNode *node, GinEntries *entries)
Definition: jsonb_gin.c:719
void check_stack_depth(void)
Definition: postgres.c:3262
union JsonPathGinNode::@28 val
JsonPathGinNodeType type
Definition: jsonb_gin.c:99
int i

◆ execute_jsp_gin_node()

static GinTernaryValue execute_jsp_gin_node ( JsonPathGinNode node,
void *  check,
bool  ternary 
)
static

Definition at line 799 of file jsonb_gin.c.

References JsonPathGinNode::args, elog, JsonPathGinNode::entryIndex, ERROR, GIN_FALSE, GIN_MAYBE, GIN_TRUE, i, JSP_GIN_AND, JSP_GIN_ENTRY, JSP_GIN_OR, JsonPathGinNode::nargs, JsonPathGinNode::type, and JsonPathGinNode::val.

Referenced by gin_consistent_jsonb(), gin_consistent_jsonb_path(), gin_triconsistent_jsonb(), and gin_triconsistent_jsonb_path().

800 {
801  GinTernaryValue res;
802  GinTernaryValue v;
803  int i;
804 
805  switch (node->type)
806  {
807  case JSP_GIN_AND:
808  res = GIN_TRUE;
809  for (i = 0; i < node->val.nargs; i++)
810  {
811  v = execute_jsp_gin_node(node->args[i], check, ternary);
812  if (v == GIN_FALSE)
813  return GIN_FALSE;
814  else if (v == GIN_MAYBE)
815  res = GIN_MAYBE;
816  }
817  return res;
818 
819  case JSP_GIN_OR:
820  res = GIN_FALSE;
821  for (i = 0; i < node->val.nargs; i++)
822  {
823  v = execute_jsp_gin_node(node->args[i], check, ternary);
824  if (v == GIN_TRUE)
825  return GIN_TRUE;
826  else if (v == GIN_MAYBE)
827  res = GIN_MAYBE;
828  }
829  return res;
830 
831  case JSP_GIN_ENTRY:
832  {
833  int index = node->val.entryIndex;
834 
835  if (ternary)
836  return ((GinTernaryValue *) check)[index];
837  else
838  return ((bool *) check)[index] ? GIN_TRUE : GIN_FALSE;
839  }
840 
841  default:
842  elog(ERROR, "invalid jsonpath gin node type: %d", node->type);
843  return GIN_FALSE; /* keep compiler quiet */
844  }
845 }
#define GIN_TRUE
Definition: gin.h:60
JsonPathGinNode * args[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb_gin.c:108
#define GIN_MAYBE
Definition: gin.h:61
Definition: type.h:89
#define ERROR
Definition: elog.h:43
char GinTernaryValue
Definition: gin.h:57
static GinTernaryValue execute_jsp_gin_node(JsonPathGinNode *node, void *check, bool ternary)
Definition: jsonb_gin.c:799
union JsonPathGinNode::@28 val
JsonPathGinNodeType type
Definition: jsonb_gin.c:99
#define GIN_FALSE
Definition: gin.h:59
#define elog(elevel,...)
Definition: elog.h:226
int i

◆ extract_jsp_bool_expr()

static JsonPathGinNode * extract_jsp_bool_expr ( JsonPathGinContext cxt,
JsonPathGinPath  path,
JsonPathItem jsp,
bool  not 
)
static

Definition at line 583 of file jsonb_gin.c.

References arg, check_stack_depth(), JsonPathItem::content, elog, ERROR, extract_jsp_path_expr(), jbvBool, jbvNull, jbvNumeric, jbvString, jpiAnd, jpiBool, jpiEqual, jpiExists, jpiNot, jpiNotEqual, jpiNull, jpiNumeric, jpiOr, jpiString, JSP_GIN_AND, JSP_GIN_OR, jspGetArg(), jspGetLeftArg(), jspGetRightArg(), jspIsScalar, make_jsp_expr_node_binary(), JsonPathItem::type, JsonbValue::type, generate_unaccent_rules::type, JsonbValue::val, and JsonPathItem::value.

Referenced by extract_jsp_path_expr_nodes(), and extract_jsp_query().

585 {
587 
588  switch (jsp->type)
589  {
590  case jpiAnd: /* expr && expr */
591  case jpiOr: /* expr || expr */
592  {
594  JsonPathGinNode *larg;
595  JsonPathGinNode *rarg;
597 
598  jspGetLeftArg(jsp, &arg);
599  larg = extract_jsp_bool_expr(cxt, path, &arg, not);
600 
601  jspGetRightArg(jsp, &arg);
602  rarg = extract_jsp_bool_expr(cxt, path, &arg, not);
603 
604  if (!larg || !rarg)
605  {
606  if (jsp->type == jpiOr)
607  return NULL;
608 
609  return larg ? larg : rarg;
610  }
611 
612  type = not ^ (jsp->type == jpiAnd) ? JSP_GIN_AND : JSP_GIN_OR;
613 
614  return make_jsp_expr_node_binary(type, larg, rarg);
615  }
616 
617  case jpiNot: /* !expr */
618  {
620 
621  jspGetArg(jsp, &arg);
622 
623  /* extract child expression inverting 'not' flag */
624  return extract_jsp_bool_expr(cxt, path, &arg, !not);
625  }
626 
627  case jpiExists: /* EXISTS(path) */
628  {
630 
631  if (not)
632  return NULL; /* NOT EXISTS is not supported */
633 
634  jspGetArg(jsp, &arg);
635 
636  return extract_jsp_path_expr(cxt, path, &arg, NULL);
637  }
638 
639  case jpiNotEqual:
640 
641  /*
642  * 'not' == true case is not supported here because '!(path !=
643  * scalar)' is not equivalent to 'path == scalar' in the general
644  * case because of sequence comparison semantics: 'path == scalar'
645  * === 'EXISTS (path, @ == scalar)', '!(path != scalar)' ===
646  * 'FOR_ALL(path, @ == scalar)'. So, we should translate '!(path
647  * != scalar)' into GIN query 'path == scalar || EMPTY(path)', but
648  * 'EMPTY(path)' queries are not supported by the both jsonb
649  * opclasses. However in strict mode we could omit 'EMPTY(path)'
650  * part if the path can return exactly one item (it does not
651  * contain wildcard accessors or item methods like .keyvalue()
652  * etc.).
653  */
654  return NULL;
655 
656  case jpiEqual: /* path == scalar */
657  {
658  JsonPathItem left_item;
659  JsonPathItem right_item;
660  JsonPathItem *path_item;
661  JsonPathItem *scalar_item;
662  JsonbValue scalar;
663 
664  if (not)
665  return NULL;
666 
667  jspGetLeftArg(jsp, &left_item);
668  jspGetRightArg(jsp, &right_item);
669 
670  if (jspIsScalar(left_item.type))
671  {
672  scalar_item = &left_item;
673  path_item = &right_item;
674  }
675  else if (jspIsScalar(right_item.type))
676  {
677  scalar_item = &right_item;
678  path_item = &left_item;
679  }
680  else
681  return NULL; /* at least one operand should be a scalar */
682 
683  switch (scalar_item->type)
684  {
685  case jpiNull:
686  scalar.type = jbvNull;
687  break;
688  case jpiBool:
689  scalar.type = jbvBool;
690  scalar.val.boolean = !!*scalar_item->content.value.data;
691  break;
692  case jpiNumeric:
693  scalar.type = jbvNumeric;
694  scalar.val.numeric =
695  (Numeric) scalar_item->content.value.data;
696  break;
697  case jpiString:
698  scalar.type = jbvString;
699  scalar.val.string.val = scalar_item->content.value.data;
700  scalar.val.string.len =
701  scalar_item->content.value.datalen;
702  break;
703  default:
704  elog(ERROR, "invalid scalar jsonpath item type: %d",
705  scalar_item->type);
706  return NULL;
707  }
708 
709  return extract_jsp_path_expr(cxt, path, path_item, &scalar);
710  }
711 
712  default:
713  return NULL; /* not a boolean expression */
714  }
715 }
struct JsonPathItem::@130::@134 value
#define jspIsScalar(type)
Definition: jsonpath.h:38
Definition: jsonpath.h:50
static JsonPathGinNode * extract_jsp_bool_expr(JsonPathGinContext *cxt, JsonPathGinPath path, JsonPathItem *jsp, bool not)
Definition: jsonb_gin.c:583
char * val
Definition: jsonb.h:272
Definition: jsonb.h:239
Definition: jsonb.h:236
struct NumericData * Numeric
Definition: numeric.h:43
static JsonPathGinNode * make_jsp_expr_node_binary(JsonPathGinNodeType type, JsonPathGinNode *arg1, JsonPathGinNode *arg2)
Definition: jsonb_gin.c:395
#define ERROR
Definition: elog.h:43
void check_stack_depth(void)
Definition: postgres.c:3262
union JsonPathItem::@130 content
void jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1013
static JsonPathGinNode * extract_jsp_path_expr(JsonPathGinContext *cxt, JsonPathGinPath path, JsonPathItem *jsp, JsonbValue *scalar)
Definition: jsonb_gin.c:564
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:992
JsonPathItemType type
Definition: jsonpath.h:107
enum jbvType type
Definition: jsonb.h:263
#define elog(elevel,...)
Definition: elog.h:226
void * arg
JsonPathGinNodeType
Definition: jsonb_gin.c:87
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:923

◆ extract_jsp_path_expr()

static JsonPathGinNode* extract_jsp_path_expr ( JsonPathGinContext cxt,
JsonPathGinPath  path,
JsonPathItem jsp,
JsonbValue scalar 
)
static

Definition at line 564 of file jsonb_gin.c.

References extract_jsp_path_expr_nodes(), JSP_GIN_AND, linitial, list_length(), and make_jsp_expr_node_args().

Referenced by extract_jsp_bool_expr(), and extract_jsp_query().

566 {
567  /* extract a list of nodes to be AND-ed */
568  List *nodes = extract_jsp_path_expr_nodes(cxt, path, jsp, scalar);
569 
570  if (list_length(nodes) <= 0)
571  /* no nodes were extracted => full scan is needed for this path */
572  return NULL;
573 
574  if (list_length(nodes) == 1)
575  return linitial(nodes); /* avoid extra AND-node */
576 
577  /* construct AND-node for path with filters */
578  return make_jsp_expr_node_args(JSP_GIN_AND, nodes);
579 }
static JsonPathGinNode * make_jsp_expr_node_args(JsonPathGinNodeType type, List *args)
Definition: jsonb_gin.c:382
#define linitial(l)
Definition: pg_list.h:195
static List * extract_jsp_path_expr_nodes(JsonPathGinContext *cxt, JsonPathGinPath path, JsonPathItem *jsp, JsonbValue *scalar)
Definition: jsonb_gin.c:504
static int list_length(const List *l)
Definition: pg_list.h:169
Definition: pg_list.h:50

◆ extract_jsp_path_expr_nodes()

static List* extract_jsp_path_expr_nodes ( JsonPathGinContext cxt,
JsonPathGinPath  path,
JsonPathItem jsp,
JsonbValue scalar 
)
static

Definition at line 504 of file jsonb_gin.c.

References JsonPathGinContext::add_path_item, arg, extract_jsp_bool_expr(), JsonPathGinContext::extract_nodes, jpiCurrent, jpiFilter, jspGetArg(), jspGetNext(), lappend(), next, NIL, and JsonPathItem::type.

Referenced by extract_jsp_path_expr().

506 {
508  List *nodes = NIL;
509 
510  for (;;)
511  {
512  switch (jsp->type)
513  {
514  case jpiCurrent:
515  break;
516 
517  case jpiFilter:
518  {
520  JsonPathGinNode *filter;
521 
522  jspGetArg(jsp, &arg);
523 
524  filter = extract_jsp_bool_expr(cxt, path, &arg, false);
525 
526  if (filter)
527  nodes = lappend(nodes, filter);
528 
529  break;
530  }
531 
532  default:
533  if (!cxt->add_path_item(&path, jsp))
534 
535  /*
536  * Path is not supported by the index opclass, return only
537  * the extracted filter nodes.
538  */
539  return nodes;
540  break;
541  }
542 
543  if (!jspGetNext(jsp, &next))
544  break;
545 
546  jsp = &next;
547  }
548 
549  /*
550  * Append nodes from the path expression itself to the already extracted
551  * list of filter nodes.
552  */
553  return cxt->extract_nodes(cxt, path, scalar, nodes);
554 }
JsonPathGinExtractNodesFunc extract_nodes
Definition: jsonb_gin.c:150
#define NIL
Definition: pg_list.h:65
static int32 next
Definition: blutils.c:215
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:937
static JsonPathGinNode * extract_jsp_bool_expr(JsonPathGinContext *cxt, JsonPathGinPath path, JsonPathItem *jsp, bool not)
Definition: jsonb_gin.c:583
List * lappend(List *list, void *datum)
Definition: list.c:322
JsonPathItemType type
Definition: jsonpath.h:107
JsonPathGinAddPathItemFunc add_path_item
Definition: jsonb_gin.c:149
void * arg
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:923
Definition: pg_list.h:50

◆ extract_jsp_query()

static Datum* extract_jsp_query ( JsonPath jp,
StrategyNumber  strat,
bool  pathOps,
int32 nentries,
Pointer **  extra_data 
)
static

Definition at line 748 of file jsonb_gin.c.

References JsonPathGinContext::add_path_item, GinEntries::buf, GinEntries::count, emit_jsp_gin_entries(), extract_jsp_bool_expr(), extract_jsp_path_expr(), JsonPathGinContext::extract_nodes, JsonPath::header, jsonb_ops__add_path_item(), jsonb_ops__extract_nodes(), jsonb_path_ops__add_path_item(), jsonb_path_ops__extract_nodes(), JsonbJsonpathExistsStrategyNumber, JSONPATH_LAX, jspInit(), JsonPathGinContext::lax, and palloc0().

Referenced by gin_extract_jsonb_query(), and gin_extract_jsonb_query_path().

750 {
751  JsonPathGinContext cxt;
752  JsonPathItem root;
753  JsonPathGinNode *node;
754  JsonPathGinPath path = {0};
755  GinEntries entries = {0};
756 
757  cxt.lax = (jp->header & JSONPATH_LAX) != 0;
758 
759  if (pathOps)
760  {
763  }
764  else
765  {
768  }
769 
770  jspInit(&root, jp);
771 
772  node = strat == JsonbJsonpathExistsStrategyNumber
773  ? extract_jsp_path_expr(&cxt, path, &root, NULL)
774  : extract_jsp_bool_expr(&cxt, path, &root, false);
775 
776  if (!node)
777  {
778  *nentries = 0;
779  return NULL;
780  }
781 
782  emit_jsp_gin_entries(node, &entries);
783 
784  *nentries = entries.count;
785  if (!*nentries)
786  return NULL;
787 
788  *extra_data = palloc0(sizeof(**extra_data) * entries.count);
789  **extra_data = (Pointer) node;
790 
791  return entries.buf;
792 }
JsonPathGinExtractNodesFunc extract_nodes
Definition: jsonb_gin.c:150
static bool jsonb_path_ops__add_path_item(JsonPathGinPath *path, JsonPathItem *jsp)
Definition: jsonb_gin.c:323
static List * jsonb_path_ops__extract_nodes(JsonPathGinContext *cxt, JsonPathGinPath path, JsonbValue *scalar, List *nodes)
Definition: jsonb_gin.c:478
static JsonPathGinNode * extract_jsp_bool_expr(JsonPathGinContext *cxt, JsonPathGinPath path, JsonPathItem *jsp, bool not)
Definition: jsonb_gin.c:583
#define false
Definition: c.h:316
#define JSONPATH_LAX
Definition: jsonpath.h:29
char * Pointer
Definition: c.h:335
int count
Definition: jsonb_gin.c:83
static void emit_jsp_gin_entries(JsonPathGinNode *node, GinEntries *entries)
Definition: jsonb_gin.c:719
#define JsonbJsonpathExistsStrategyNumber
Definition: jsonb.h:37
static List * jsonb_ops__extract_nodes(JsonPathGinContext *cxt, JsonPathGinPath path, JsonbValue *scalar, List *nodes)
Definition: jsonb_gin.c:408
Datum * buf
Definition: jsonb_gin.c:82
void * palloc0(Size size)
Definition: mcxt.c:980
static JsonPathGinNode * extract_jsp_path_expr(JsonPathGinContext *cxt, JsonPathGinPath path, JsonPathItem *jsp, JsonbValue *scalar)
Definition: jsonb_gin.c:564
static bool jsonb_ops__add_path_item(JsonPathGinPath *path, JsonPathItem *jsp)
Definition: jsonb_gin.c:278
JsonPathGinAddPathItemFunc add_path_item
Definition: jsonb_gin.c:149
void jspInit(JsonPathItem *v, JsonPath *js)
Definition: jsonpath.c:833
uint32 header
Definition: jsonpath.h:24

◆ gin_compare_jsonb()

Datum gin_compare_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 203 of file jsonb_gin.c.

References PG_FREE_IF_COPY, PG_GETARG_TEXT_PP, PG_RETURN_INT32, VARDATA_ANY, VARSIZE_ANY_EXHDR, and varstr_cmp().

204 {
205  text *arg1 = PG_GETARG_TEXT_PP(0);
206  text *arg2 = PG_GETARG_TEXT_PP(1);
207  int32 result;
208  char *a1p,
209  *a2p;
210  int len1,
211  len2;
212 
213  a1p = VARDATA_ANY(arg1);
214  a2p = VARDATA_ANY(arg2);
215 
216  len1 = VARSIZE_ANY_EXHDR(arg1);
217  len2 = VARSIZE_ANY_EXHDR(arg2);
218 
219  /* Compare text as bttextcmp does, but always using C collation */
220  result = varstr_cmp(a1p, len1, a2p, len2, C_COLLATION_OID);
221 
222  PG_FREE_IF_COPY(arg1, 0);
223  PG_FREE_IF_COPY(arg2, 1);
224 
225  PG_RETURN_INT32(result);
226 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
#define PG_RETURN_INT32(x)
Definition: fmgr.h:344
signed int int32
Definition: c.h:346
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid)
Definition: varlena.c:1474
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:255
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
Definition: c.h:549

◆ gin_consistent_jsonb()

Datum gin_consistent_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 930 of file jsonb_gin.c.

References Assert, elog, ERROR, execute_jsp_gin_node(), GIN_FALSE, i, JsonbContainsStrategyNumber, JsonbExistsAllStrategyNumber, JsonbExistsAnyStrategyNumber, JsonbExistsStrategyNumber, JsonbJsonpathExistsStrategyNumber, JsonbJsonpathPredicateStrategyNumber, PG_GETARG_INT32, PG_GETARG_POINTER, PG_GETARG_UINT16, and PG_RETURN_BOOL.

931 {
932  bool *check = (bool *) PG_GETARG_POINTER(0);
933  StrategyNumber strategy = PG_GETARG_UINT16(1);
934 
935  /* Jsonb *query = PG_GETARG_JSONB_P(2); */
936  int32 nkeys = PG_GETARG_INT32(3);
937 
938  Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
939  bool *recheck = (bool *) PG_GETARG_POINTER(5);
940  bool res = true;
941  int32 i;
942 
943  if (strategy == JsonbContainsStrategyNumber)
944  {
945  /*
946  * We must always recheck, since we can't tell from the index whether
947  * the positions of the matched items match the structure of the query
948  * object. (Even if we could, we'd also have to worry about hashed
949  * keys and the index's failure to distinguish keys from string array
950  * elements.) However, the tuple certainly doesn't match unless it
951  * contains all the query keys.
952  */
953  *recheck = true;
954  for (i = 0; i < nkeys; i++)
955  {
956  if (!check[i])
957  {
958  res = false;
959  break;
960  }
961  }
962  }
963  else if (strategy == JsonbExistsStrategyNumber)
964  {
965  /*
966  * Although the key is certainly present in the index, we must recheck
967  * because (1) the key might be hashed, and (2) the index match might
968  * be for a key that's not at top level of the JSON object. For (1),
969  * we could look at the query key to see if it's hashed and not
970  * recheck if not, but the index lacks enough info to tell about (2).
971  */
972  *recheck = true;
973  res = true;
974  }
975  else if (strategy == JsonbExistsAnyStrategyNumber)
976  {
977  /* As for plain exists, we must recheck */
978  *recheck = true;
979  res = true;
980  }
981  else if (strategy == JsonbExistsAllStrategyNumber)
982  {
983  /* As for plain exists, we must recheck */
984  *recheck = true;
985  /* ... but unless all the keys are present, we can say "false" */
986  for (i = 0; i < nkeys; i++)
987  {
988  if (!check[i])
989  {
990  res = false;
991  break;
992  }
993  }
994  }
995  else if (strategy == JsonbJsonpathPredicateStrategyNumber ||
997  {
998  *recheck = true;
999 
1000  if (nkeys > 0)
1001  {
1002  Assert(extra_data && extra_data[0]);
1003  res = execute_jsp_gin_node((JsonPathGinNode *) extra_data[0], check,
1004  false) != GIN_FALSE;
1005  }
1006  }
1007  else
1008  elog(ERROR, "unrecognized strategy number: %d", strategy);
1009 
1010  PG_RETURN_BOOL(res);
1011 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define JsonbExistsAnyStrategyNumber
Definition: jsonb.h:35
#define JsonbExistsAllStrategyNumber
Definition: jsonb.h:36
signed int int32
Definition: c.h:346
char * Pointer
Definition: c.h:335
#define ERROR
Definition: elog.h:43
static GinTernaryValue execute_jsp_gin_node(JsonPathGinNode *node, void *check, bool ternary)
Definition: jsonb_gin.c:799
#define JsonbJsonpathExistsStrategyNumber
Definition: jsonb.h:37
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define Assert(condition)
Definition: c.h:732
#define JsonbExistsStrategyNumber
Definition: jsonb.h:34
#define GIN_FALSE
Definition: gin.h:59
#define JsonbContainsStrategyNumber
Definition: jsonb.h:33
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267
#define elog(elevel,...)
Definition: elog.h:226
int i
#define JsonbJsonpathPredicateStrategyNumber
Definition: jsonb.h:38

◆ gin_consistent_jsonb_path()

Datum gin_consistent_jsonb_path ( PG_FUNCTION_ARGS  )

Definition at line 1221 of file jsonb_gin.c.

References Assert, elog, ERROR, execute_jsp_gin_node(), GIN_FALSE, i, JsonbContainsStrategyNumber, JsonbJsonpathExistsStrategyNumber, JsonbJsonpathPredicateStrategyNumber, PG_GETARG_INT32, PG_GETARG_POINTER, PG_GETARG_UINT16, and PG_RETURN_BOOL.

1222 {
1223  bool *check = (bool *) PG_GETARG_POINTER(0);
1224  StrategyNumber strategy = PG_GETARG_UINT16(1);
1225 
1226  /* Jsonb *query = PG_GETARG_JSONB_P(2); */
1227  int32 nkeys = PG_GETARG_INT32(3);
1228  Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
1229  bool *recheck = (bool *) PG_GETARG_POINTER(5);
1230  bool res = true;
1231  int32 i;
1232 
1233  if (strategy == JsonbContainsStrategyNumber)
1234  {
1235  /*
1236  * jsonb_path_ops is necessarily lossy, not only because of hash
1237  * collisions but also because it doesn't preserve complete
1238  * information about the structure of the JSON object. Besides, there
1239  * are some special rules around the containment of raw scalars in
1240  * arrays that are not handled here. So we must always recheck a
1241  * match. However, if not all of the keys are present, the tuple
1242  * certainly doesn't match.
1243  */
1244  *recheck = true;
1245  for (i = 0; i < nkeys; i++)
1246  {
1247  if (!check[i])
1248  {
1249  res = false;
1250  break;
1251  }
1252  }
1253  }
1254  else if (strategy == JsonbJsonpathPredicateStrategyNumber ||
1256  {
1257  *recheck = true;
1258 
1259  if (nkeys > 0)
1260  {
1261  Assert(extra_data && extra_data[0]);
1262  res = execute_jsp_gin_node((JsonPathGinNode *) extra_data[0], check,
1263  false) != GIN_FALSE;
1264  }
1265  }
1266  else
1267  elog(ERROR, "unrecognized strategy number: %d", strategy);
1268 
1269  PG_RETURN_BOOL(res);
1270 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
signed int int32
Definition: c.h:346
char * Pointer
Definition: c.h:335
#define ERROR
Definition: elog.h:43
static GinTernaryValue execute_jsp_gin_node(JsonPathGinNode *node, void *check, bool ternary)
Definition: jsonb_gin.c:799
#define JsonbJsonpathExistsStrategyNumber
Definition: jsonb.h:37
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define Assert(condition)
Definition: c.h:732
#define GIN_FALSE
Definition: gin.h:59
#define JsonbContainsStrategyNumber
Definition: jsonb.h:33
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267
#define elog(elevel,...)
Definition: elog.h:226
int i
#define JsonbJsonpathPredicateStrategyNumber
Definition: jsonb.h:38

◆ gin_extract_jsonb()

Datum gin_extract_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 229 of file jsonb_gin.c.

References add_gin_entry(), GinEntries::buf, GinEntries::count, init_gin_entries(), JB_ROOT_COUNT, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), make_scalar_key(), PG_GETARG_JSONB_P, PG_GETARG_POINTER, PG_RETURN_POINTER, Jsonb::root, JsonbValue::type, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

Referenced by gin_extract_jsonb_query().

230 {
231  Jsonb *jb = (Jsonb *) PG_GETARG_JSONB_P(0);
232  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
233  int total = JB_ROOT_COUNT(jb);
234  JsonbIterator *it;
235  JsonbValue v;
237  GinEntries entries;
238 
239  /* If the root level is empty, we certainly have no keys */
240  if (total == 0)
241  {
242  *nentries = 0;
243  PG_RETURN_POINTER(NULL);
244  }
245 
246  /* Otherwise, use 2 * root count as initial estimate of result size */
247  init_gin_entries(&entries, 2 * total);
248 
249  it = JsonbIteratorInit(&jb->root);
250 
251  while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
252  {
253  switch (r)
254  {
255  case WJB_KEY:
256  add_gin_entry(&entries, make_scalar_key(&v, true));
257  break;
258  case WJB_ELEM:
259  /* Pretend string array elements are keys, see jsonb.h */
260  add_gin_entry(&entries, make_scalar_key(&v, v.type == jbvString));
261  break;
262  case WJB_VALUE:
263  add_gin_entry(&entries, make_scalar_key(&v, false));
264  break;
265  default:
266  /* we can ignore structural items */
267  break;
268  }
269  }
270 
271  *nentries = entries.count;
272 
273  PG_RETURN_POINTER(entries.buf);
274 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: jsonb.h:220
static void init_gin_entries(GinEntries *entries, int preallocated)
Definition: jsonb_gin.c:163
static int add_gin_entry(GinEntries *entries, Datum entry)
Definition: jsonb_gin.c:172
Definition: jsonb.h:22
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
signed int int32
Definition: c.h:346
int count
Definition: jsonb_gin.c:83
Definition: jsonb.h:23
Datum * buf
Definition: jsonb_gin.c:82
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
static Datum make_scalar_key(const JsonbValue *scalarVal, bool is_key)
Definition: jsonb_gin.c:1365
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:759
enum jbvType type
Definition: jsonb.h:263
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:795
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ gin_extract_jsonb_path()

Datum gin_extract_jsonb_path ( PG_FUNCTION_ARGS  )

Definition at line 1091 of file jsonb_gin.c.

References add_gin_entry(), GinEntries::buf, GinEntries::count, elog, ERROR, PathHashStack::hash, init_gin_entries(), JB_ROOT_COUNT, JsonbHashScalarValue(), JsonbIteratorInit(), JsonbIteratorNext(), palloc(), PathHashStack::parent, pfree(), PG_GETARG_JSONB_P, PG_GETARG_POINTER, PG_RETURN_POINTER, Jsonb::root, UInt32GetDatum, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by gin_extract_jsonb_query_path().

1092 {
1093  Jsonb *jb = PG_GETARG_JSONB_P(0);
1094  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
1095  int total = JB_ROOT_COUNT(jb);
1096  JsonbIterator *it;
1097  JsonbValue v;
1099  PathHashStack tail;
1100  PathHashStack *stack;
1101  GinEntries entries;
1102 
1103  /* If the root level is empty, we certainly have no keys */
1104  if (total == 0)
1105  {
1106  *nentries = 0;
1107  PG_RETURN_POINTER(NULL);
1108  }
1109 
1110  /* Otherwise, use 2 * root count as initial estimate of result size */
1111  init_gin_entries(&entries, 2 * total);
1112 
1113  /* We keep a stack of partial hashes corresponding to parent key levels */
1114  tail.parent = NULL;
1115  tail.hash = 0;
1116  stack = &tail;
1117 
1118  it = JsonbIteratorInit(&jb->root);
1119 
1120  while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1121  {
1122  PathHashStack *parent;
1123 
1124  switch (r)
1125  {
1126  case WJB_BEGIN_ARRAY:
1127  case WJB_BEGIN_OBJECT:
1128  /* Push a stack level for this object */
1129  parent = stack;
1130  stack = (PathHashStack *) palloc(sizeof(PathHashStack));
1131 
1132  /*
1133  * We pass forward hashes from outer nesting levels so that
1134  * the hashes for nested values will include outer keys as
1135  * well as their own keys.
1136  *
1137  * Nesting an array within another array will not alter
1138  * innermost scalar element hash values, but that seems
1139  * inconsequential.
1140  */
1141  stack->hash = parent->hash;
1142  stack->parent = parent;
1143  break;
1144  case WJB_KEY:
1145  /* mix this key into the current outer hash */
1146  JsonbHashScalarValue(&v, &stack->hash);
1147  /* hash is now ready to incorporate the value */
1148  break;
1149  case WJB_ELEM:
1150  case WJB_VALUE:
1151  /* mix the element or value's hash into the prepared hash */
1152  JsonbHashScalarValue(&v, &stack->hash);
1153  /* and emit an index entry */
1154  add_gin_entry(&entries, UInt32GetDatum(stack->hash));
1155  /* reset hash for next key, value, or sub-object */
1156  stack->hash = stack->parent->hash;
1157  break;
1158  case WJB_END_ARRAY:
1159  case WJB_END_OBJECT:
1160  /* Pop the stack */
1161  parent = stack->parent;
1162  pfree(stack);
1163  stack = parent;
1164  /* reset hash for next key, value, or sub-object */
1165  if (stack->parent)
1166  stack->hash = stack->parent->hash;
1167  else
1168  stack->hash = 0;
1169  break;
1170  default:
1171  elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
1172  }
1173  }
1174 
1175  *nentries = entries.count;
1176 
1177  PG_RETURN_POINTER(entries.buf);
1178 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
struct PathHashStack * parent
Definition: jsonb_gin.c:76
Definition: jsonb.h:220
static void init_gin_entries(GinEntries *entries, int preallocated)
Definition: jsonb_gin.c:163
static int add_gin_entry(GinEntries *entries, Datum entry)
Definition: jsonb_gin.c:172
Definition: jsonb.h:22
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
signed int int32
Definition: c.h:346
void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
Definition: jsonb_util.c:1258
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
int count
Definition: jsonb_gin.c:83
#define UInt32GetDatum(X)
Definition: postgres.h:493
Definition: jsonb.h:23
Datum * buf
Definition: jsonb_gin.c:82
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
uint32 hash
Definition: jsonb_gin.c:75
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:759
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:226
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:795
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ gin_extract_jsonb_query()

Datum gin_extract_jsonb_query ( PG_FUNCTION_ARGS  )

Definition at line 848 of file jsonb_gin.c.

References DatumGetPointer, deconstruct_array(), DirectFunctionCall2, elog, ERROR, extract_jsp_query(), gin_extract_jsonb(), GIN_SEARCH_MODE_ALL, i, JGINFLAG_KEY, JsonbContainsStrategyNumber, JsonbExistsAllStrategyNumber, JsonbExistsAnyStrategyNumber, JsonbExistsStrategyNumber, JsonbJsonpathExistsStrategyNumber, JsonbJsonpathPredicateStrategyNumber, make_text_key(), palloc(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_GETARG_JSONPATH_P, PG_GETARG_POINTER, PG_GETARG_TEXT_PP, PG_GETARG_UINT16, PG_RETURN_POINTER, PointerGetDatum, VARDATA, VARDATA_ANY, VARHDRSZ, VARSIZE, and VARSIZE_ANY_EXHDR.

849 {
850  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
851  StrategyNumber strategy = PG_GETARG_UINT16(2);
852  int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
853  Datum *entries;
854 
855  if (strategy == JsonbContainsStrategyNumber)
856  {
857  /* Query is a jsonb, so just apply gin_extract_jsonb... */
858  entries = (Datum *)
860  PG_GETARG_DATUM(0),
861  PointerGetDatum(nentries)));
862  /* ...although "contains {}" requires a full index scan */
863  if (*nentries == 0)
864  *searchMode = GIN_SEARCH_MODE_ALL;
865  }
866  else if (strategy == JsonbExistsStrategyNumber)
867  {
868  /* Query is a text string, which we treat as a key */
869  text *query = PG_GETARG_TEXT_PP(0);
870 
871  *nentries = 1;
872  entries = (Datum *) palloc(sizeof(Datum));
873  entries[0] = make_text_key(JGINFLAG_KEY,
874  VARDATA_ANY(query),
875  VARSIZE_ANY_EXHDR(query));
876  }
877  else if (strategy == JsonbExistsAnyStrategyNumber ||
878  strategy == JsonbExistsAllStrategyNumber)
879  {
880  /* Query is a text array; each element is treated as a key */
881  ArrayType *query = PG_GETARG_ARRAYTYPE_P(0);
882  Datum *key_datums;
883  bool *key_nulls;
884  int key_count;
885  int i,
886  j;
887 
888  deconstruct_array(query,
889  TEXTOID, -1, false, 'i',
890  &key_datums, &key_nulls, &key_count);
891 
892  entries = (Datum *) palloc(sizeof(Datum) * key_count);
893 
894  for (i = 0, j = 0; i < key_count; i++)
895  {
896  /* Nulls in the array are ignored */
897  if (key_nulls[i])
898  continue;
899  entries[j++] = make_text_key(JGINFLAG_KEY,
900  VARDATA(key_datums[i]),
901  VARSIZE(key_datums[i]) - VARHDRSZ);
902  }
903 
904  *nentries = j;
905  /* ExistsAll with no keys should match everything */
906  if (j == 0 && strategy == JsonbExistsAllStrategyNumber)
907  *searchMode = GIN_SEARCH_MODE_ALL;
908  }
909  else if (strategy == JsonbJsonpathPredicateStrategyNumber ||
911  {
913  Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
914 
915  entries = extract_jsp_query(jp, strategy, false, nentries, extra_data);
916 
917  if (!entries)
918  *searchMode = GIN_SEARCH_MODE_ALL;
919  }
920  else
921  {
922  elog(ERROR, "unrecognized strategy number: %d", strategy);
923  entries = NULL; /* keep compiler quiet */
924  }
925 
926  PG_RETURN_POINTER(entries);
927 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARSIZE(PTR)
Definition: postgres.h:303
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define VARHDRSZ
Definition: c.h:555
#define JGINFLAG_KEY
Definition: jsonb.h:62
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define JsonbExistsAnyStrategyNumber
Definition: jsonb.h:35
#define JsonbExistsAllStrategyNumber
Definition: jsonb.h:36
signed int int32
Definition: c.h:346
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define GIN_SEARCH_MODE_ALL
Definition: gin.h:35
char * Pointer
Definition: c.h:335
#define ERROR
Definition: elog.h:43
#define JsonbJsonpathExistsStrategyNumber
Definition: jsonb.h:37
#define PG_GETARG_JSONPATH_P(x)
Definition: jsonpath.h:34
uintptr_t Datum
Definition: postgres.h:367
#define JsonbExistsStrategyNumber
Definition: jsonb.h:34
#define JsonbContainsStrategyNumber
Definition: jsonb.h:33
static Datum * extract_jsp_query(JsonPath *jp, StrategyNumber strat, bool pathOps, int32 *nentries, Pointer **extra_data)
Definition: jsonb_gin.c:748
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267
#define DatumGetPointer(X)
Definition: postgres.h:549
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
Datum gin_extract_jsonb(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:229
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:226
int i
Definition: c.h:549
static Datum make_text_key(char flag, const char *str, int len)
Definition: jsonb_gin.c:1327
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619
#define JsonbJsonpathPredicateStrategyNumber
Definition: jsonb.h:38

◆ gin_extract_jsonb_query_path()

Datum gin_extract_jsonb_query_path ( PG_FUNCTION_ARGS  )

Definition at line 1181 of file jsonb_gin.c.

References DatumGetPointer, DirectFunctionCall2, elog, ERROR, extract_jsp_query(), gin_extract_jsonb_path(), GIN_SEARCH_MODE_ALL, JsonbContainsStrategyNumber, JsonbJsonpathExistsStrategyNumber, JsonbJsonpathPredicateStrategyNumber, PG_GETARG_DATUM, PG_GETARG_JSONPATH_P, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_POINTER, and PointerGetDatum.

1182 {
1183  int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
1184  StrategyNumber strategy = PG_GETARG_UINT16(2);
1185  int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
1186  Datum *entries;
1187 
1188  if (strategy == JsonbContainsStrategyNumber)
1189  {
1190  /* Query is a jsonb, so just apply gin_extract_jsonb_path ... */
1191  entries = (Datum *)
1193  PG_GETARG_DATUM(0),
1194  PointerGetDatum(nentries)));
1195 
1196  /* ... although "contains {}" requires a full index scan */
1197  if (*nentries == 0)
1198  *searchMode = GIN_SEARCH_MODE_ALL;
1199  }
1200  else if (strategy == JsonbJsonpathPredicateStrategyNumber ||
1202  {
1203  JsonPath *jp = PG_GETARG_JSONPATH_P(0);
1204  Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
1205 
1206  entries = extract_jsp_query(jp, strategy, true, nentries, extra_data);
1207 
1208  if (!entries)
1209  *searchMode = GIN_SEARCH_MODE_ALL;
1210  }
1211  else
1212  {
1213  elog(ERROR, "unrecognized strategy number: %d", strategy);
1214  entries = NULL;
1215  }
1216 
1217  PG_RETURN_POINTER(entries);
1218 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum gin_extract_jsonb_path(PG_FUNCTION_ARGS)
Definition: jsonb_gin.c:1091
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
signed int int32
Definition: c.h:346
#define GIN_SEARCH_MODE_ALL
Definition: gin.h:35
char * Pointer
Definition: c.h:335
#define ERROR
Definition: elog.h:43
#define JsonbJsonpathExistsStrategyNumber
Definition: jsonb.h:37
#define PG_GETARG_JSONPATH_P(x)
Definition: jsonpath.h:34
uintptr_t Datum
Definition: postgres.h:367
#define JsonbContainsStrategyNumber
Definition: jsonb.h:33
static Datum * extract_jsp_query(JsonPath *jp, StrategyNumber strat, bool pathOps, int32 *nentries, Pointer **extra_data)
Definition: jsonb_gin.c:748
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267
#define DatumGetPointer(X)
Definition: postgres.h:549
#define elog(elevel,...)
Definition: elog.h:226
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619
#define JsonbJsonpathPredicateStrategyNumber
Definition: jsonb.h:38

◆ gin_triconsistent_jsonb()

Datum gin_triconsistent_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 1014 of file jsonb_gin.c.

References Assert, elog, ERROR, execute_jsp_gin_node(), GIN_FALSE, GIN_MAYBE, GIN_TRUE, i, JsonbContainsStrategyNumber, JsonbExistsAllStrategyNumber, JsonbExistsAnyStrategyNumber, JsonbExistsStrategyNumber, JsonbJsonpathExistsStrategyNumber, JsonbJsonpathPredicateStrategyNumber, PG_GETARG_INT32, PG_GETARG_POINTER, PG_GETARG_UINT16, and PG_RETURN_GIN_TERNARY_VALUE.

1015 {
1017  StrategyNumber strategy = PG_GETARG_UINT16(1);
1018 
1019  /* Jsonb *query = PG_GETARG_JSONB_P(2); */
1020  int32 nkeys = PG_GETARG_INT32(3);
1021  Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
1022  GinTernaryValue res = GIN_MAYBE;
1023  int32 i;
1024 
1025  /*
1026  * Note that we never return GIN_TRUE, only GIN_MAYBE or GIN_FALSE; this
1027  * corresponds to always forcing recheck in the regular consistent
1028  * function, for the reasons listed there.
1029  */
1030  if (strategy == JsonbContainsStrategyNumber ||
1031  strategy == JsonbExistsAllStrategyNumber)
1032  {
1033  /* All extracted keys must be present */
1034  for (i = 0; i < nkeys; i++)
1035  {
1036  if (check[i] == GIN_FALSE)
1037  {
1038  res = GIN_FALSE;
1039  break;
1040  }
1041  }
1042  }
1043  else if (strategy == JsonbExistsStrategyNumber ||
1044  strategy == JsonbExistsAnyStrategyNumber)
1045  {
1046  /* At least one extracted key must be present */
1047  res = GIN_FALSE;
1048  for (i = 0; i < nkeys; i++)
1049  {
1050  if (check[i] == GIN_TRUE ||
1051  check[i] == GIN_MAYBE)
1052  {
1053  res = GIN_MAYBE;
1054  break;
1055  }
1056  }
1057  }
1058  else if (strategy == JsonbJsonpathPredicateStrategyNumber ||
1060  {
1061  if (nkeys > 0)
1062  {
1063  Assert(extra_data && extra_data[0]);
1064  res = execute_jsp_gin_node((JsonPathGinNode *) extra_data[0], check,
1065  true);
1066 
1067  /* Should always recheck the result */
1068  if (res == GIN_TRUE)
1069  res = GIN_MAYBE;
1070  }
1071  }
1072  else
1073  elog(ERROR, "unrecognized strategy number: %d", strategy);
1074 
1076 }
#define GIN_TRUE
Definition: gin.h:60
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define GIN_MAYBE
Definition: gin.h:61
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define JsonbExistsAnyStrategyNumber
Definition: jsonb.h:35
#define JsonbExistsAllStrategyNumber
Definition: jsonb.h:36
signed int int32
Definition: c.h:346
#define PG_RETURN_GIN_TERNARY_VALUE(x)
Definition: gin.h:66
char * Pointer
Definition: c.h:335
#define ERROR
Definition: elog.h:43
char GinTernaryValue
Definition: gin.h:57
static GinTernaryValue execute_jsp_gin_node(JsonPathGinNode *node, void *check, bool ternary)
Definition: jsonb_gin.c:799
#define JsonbJsonpathExistsStrategyNumber
Definition: jsonb.h:37
#define Assert(condition)
Definition: c.h:732
#define JsonbExistsStrategyNumber
Definition: jsonb.h:34
#define GIN_FALSE
Definition: gin.h:59
#define JsonbContainsStrategyNumber
Definition: jsonb.h:33
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267
#define elog(elevel,...)
Definition: elog.h:226
int i
#define JsonbJsonpathPredicateStrategyNumber
Definition: jsonb.h:38

◆ gin_triconsistent_jsonb_path()

Datum gin_triconsistent_jsonb_path ( PG_FUNCTION_ARGS  )

Definition at line 1273 of file jsonb_gin.c.

References Assert, elog, ERROR, execute_jsp_gin_node(), GIN_FALSE, GIN_MAYBE, GIN_TRUE, i, JsonbContainsStrategyNumber, JsonbJsonpathExistsStrategyNumber, JsonbJsonpathPredicateStrategyNumber, PG_GETARG_INT32, PG_GETARG_POINTER, PG_GETARG_UINT16, and PG_RETURN_GIN_TERNARY_VALUE.

1274 {
1276  StrategyNumber strategy = PG_GETARG_UINT16(1);
1277 
1278  /* Jsonb *query = PG_GETARG_JSONB_P(2); */
1279  int32 nkeys = PG_GETARG_INT32(3);
1280  Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
1281  GinTernaryValue res = GIN_MAYBE;
1282  int32 i;
1283 
1284  if (strategy == JsonbContainsStrategyNumber)
1285  {
1286  /*
1287  * Note that we never return GIN_TRUE, only GIN_MAYBE or GIN_FALSE;
1288  * this corresponds to always forcing recheck in the regular
1289  * consistent function, for the reasons listed there.
1290  */
1291  for (i = 0; i < nkeys; i++)
1292  {
1293  if (check[i] == GIN_FALSE)
1294  {
1295  res = GIN_FALSE;
1296  break;
1297  }
1298  }
1299  }
1300  else if (strategy == JsonbJsonpathPredicateStrategyNumber ||
1302  {
1303  if (nkeys > 0)
1304  {
1305  Assert(extra_data && extra_data[0]);
1306  res = execute_jsp_gin_node((JsonPathGinNode *) extra_data[0], check,
1307  true);
1308 
1309  /* Should always recheck the result */
1310  if (res == GIN_TRUE)
1311  res = GIN_MAYBE;
1312  }
1313  }
1314  else
1315  elog(ERROR, "unrecognized strategy number: %d", strategy);
1316 
1318 }
#define GIN_TRUE
Definition: gin.h:60
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define GIN_MAYBE
Definition: gin.h:61
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
signed int int32
Definition: c.h:346
#define PG_RETURN_GIN_TERNARY_VALUE(x)
Definition: gin.h:66
char * Pointer
Definition: c.h:335
#define ERROR
Definition: elog.h:43
char GinTernaryValue
Definition: gin.h:57
static GinTernaryValue execute_jsp_gin_node(JsonPathGinNode *node, void *check, bool ternary)
Definition: jsonb_gin.c:799
#define JsonbJsonpathExistsStrategyNumber
Definition: jsonb.h:37
#define Assert(condition)
Definition: c.h:732
#define GIN_FALSE
Definition: gin.h:59
#define JsonbContainsStrategyNumber
Definition: jsonb.h:33
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267
#define elog(elevel,...)
Definition: elog.h:226
int i
#define JsonbJsonpathPredicateStrategyNumber
Definition: jsonb.h:38

◆ init_gin_entries()

static void init_gin_entries ( GinEntries entries,
int  preallocated 
)
static

Definition at line 163 of file jsonb_gin.c.

References GinEntries::allocated, GinEntries::buf, GinEntries::count, and palloc().

Referenced by gin_extract_jsonb(), and gin_extract_jsonb_path().

164 {
165  entries->allocated = preallocated;
166  entries->buf = preallocated ? palloc(sizeof(Datum) * preallocated) : NULL;
167  entries->count = 0;
168 }
int count
Definition: jsonb_gin.c:83
Datum * buf
Definition: jsonb_gin.c:82
uintptr_t Datum
Definition: postgres.h:367
int allocated
Definition: jsonb_gin.c:84
void * palloc(Size size)
Definition: mcxt.c:949

◆ jsonb_ops__add_path_item()

static bool jsonb_ops__add_path_item ( JsonPathGinPath path,
JsonPathItem jsp 
)
static

Definition at line 278 of file jsonb_gin.c.

References JsonPathGinPath::items, JGINFLAG_KEY, jpiAny, jpiAnyArray, jpiAnyKey, jpiIndexArray, jpiKey, jpiRoot, jspGetString(), sort-test::key, JsonPathGinPathItem::keyName, make_text_key(), palloc(), JsonPathGinPathItem::parent, PointerGetDatum, JsonPathItem::type, and JsonPathGinPathItem::type.

Referenced by extract_jsp_query().

279 {
280  JsonPathGinPathItem *pentry;
281  Datum keyName;
282 
283  switch (jsp->type)
284  {
285  case jpiRoot:
286  path->items = NULL; /* reset path */
287  return true;
288 
289  case jpiKey:
290  {
291  int len;
292  char *key = jspGetString(jsp, &len);
293 
294  keyName = make_text_key(JGINFLAG_KEY, key, len);
295  break;
296  }
297 
298  case jpiAny:
299  case jpiAnyKey:
300  case jpiAnyArray:
301  case jpiIndexArray:
302  keyName = PointerGetDatum(NULL);
303  break;
304 
305  default:
306  /* other path items like item methods are not supported */
307  return false;
308  }
309 
310  pentry = palloc(sizeof(*pentry));
311 
312  pentry->type = jsp->type;
313  pentry->keyName = keyName;
314  pentry->parent = path->items;
315 
316  path->items = pentry;
317 
318  return true;
319 }
JsonPathItemType type
Definition: jsonb_gin.c:121
#define PointerGetDatum(X)
Definition: postgres.h:556
#define JGINFLAG_KEY
Definition: jsonb.h:62
struct JsonPathGinPathItem * parent
Definition: jsonb_gin.c:119
uintptr_t Datum
Definition: postgres.h:367
JsonPathItemType type
Definition: jsonpath.h:107
JsonPathGinPathItem * items
Definition: jsonb_gin.c:127
void * palloc(Size size)
Definition: mcxt.c:949
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1050
static Datum make_text_key(char flag, const char *str, int len)
Definition: jsonb_gin.c:1327

◆ jsonb_ops__extract_nodes()

static List* jsonb_ops__extract_nodes ( JsonPathGinContext cxt,
JsonPathGinPath  path,
JsonbValue scalar,
List nodes 
)
static

Definition at line 408 of file jsonb_gin.c.

References GIN_FALSE, GIN_MAYBE, GIN_TRUE, JsonPathGinPath::items, jbvString, jpiAny, jpiAnyArray, jpiIndexArray, jpiKey, JSP_GIN_OR, JsonPathGinPathItem::keyName, lappend(), JsonPathGinContext::lax, make_jsp_entry_node(), make_jsp_entry_node_scalar(), make_jsp_expr_node_binary(), JsonPathGinPathItem::parent, JsonPathGinPathItem::type, and JsonbValue::type.

Referenced by extract_jsp_query().

410 {
411  JsonPathGinPathItem *pentry;
412 
413  if (scalar)
414  {
415  JsonPathGinNode *node;
416 
417  /*
418  * Append path entry nodes only if scalar is provided. See header
419  * comment for details.
420  */
421  for (pentry = path.items; pentry; pentry = pentry->parent)
422  {
423  if (pentry->type == jpiKey) /* only keys are indexed */
424  nodes = lappend(nodes, make_jsp_entry_node(pentry->keyName));
425  }
426 
427  /* Append scalar node for equality queries. */
428  if (scalar->type == jbvString)
429  {
430  JsonPathGinPathItem *last = path.items;
431  GinTernaryValue key_entry;
432 
433  /*
434  * Assuming that jsonb_ops interprets string array elements as
435  * keys, we may extract key or non-key entry or even both. In the
436  * latter case we create OR-node. It is possible in lax mode
437  * where arrays are automatically unwrapped, or in strict mode for
438  * jpiAny items.
439  */
440 
441  if (cxt->lax)
442  key_entry = GIN_MAYBE;
443  else if (!last) /* root ($) */
444  key_entry = GIN_FALSE;
445  else if (last->type == jpiAnyArray || last->type == jpiIndexArray)
446  key_entry = GIN_TRUE;
447  else if (last->type == jpiAny)
448  key_entry = GIN_MAYBE;
449  else
450  key_entry = GIN_FALSE;
451 
452  if (key_entry == GIN_MAYBE)
453  {
454  JsonPathGinNode *n1 = make_jsp_entry_node_scalar(scalar, true);
455  JsonPathGinNode *n2 = make_jsp_entry_node_scalar(scalar, false);
456 
457  node = make_jsp_expr_node_binary(JSP_GIN_OR, n1, n2);
458  }
459  else
460  {
461  node = make_jsp_entry_node_scalar(scalar,
462  key_entry == GIN_TRUE);
463  }
464  }
465  else
466  {
467  node = make_jsp_entry_node_scalar(scalar, false);
468  }
469 
470  nodes = lappend(nodes, node);
471  }
472 
473  return nodes;
474 }
#define GIN_TRUE
Definition: gin.h:60
JsonPathItemType type
Definition: jsonb_gin.c:121
#define GIN_MAYBE
Definition: gin.h:61
static JsonPathGinNode * make_jsp_expr_node_binary(JsonPathGinNodeType type, JsonPathGinNode *arg1, JsonPathGinNode *arg2)
Definition: jsonb_gin.c:395
static JsonPathGinNode * make_jsp_entry_node_scalar(JsonbValue *scalar, bool iskey)
Definition: jsonb_gin.c:364
static JsonPathGinNode * make_jsp_entry_node(Datum entry)
Definition: jsonb_gin.c:353
char GinTernaryValue
Definition: gin.h:57
struct JsonPathGinPathItem * parent
Definition: jsonb_gin.c:119
List * lappend(List *list, void *datum)
Definition: list.c:322
#define GIN_FALSE
Definition: gin.h:59
enum jbvType type
Definition: jsonb.h:263
JsonPathGinPathItem * items
Definition: jsonb_gin.c:127

◆ jsonb_path_ops__add_path_item()

static bool jsonb_path_ops__add_path_item ( JsonPathGinPath path,
JsonPathItem jsp 
)
static

Definition at line 323 of file jsonb_gin.c.

References JsonPathGinPath::hash, jbvString, jpiAnyArray, jpiIndexArray, jpiKey, jpiRoot, JsonbHashScalarValue(), jspGetString(), JsonPathItem::type, JsonbValue::type, and JsonbValue::val.

Referenced by extract_jsp_query().

324 {
325  switch (jsp->type)
326  {
327  case jpiRoot:
328  path->hash = 0; /* reset path hash */
329  return true;
330 
331  case jpiKey:
332  {
333  JsonbValue jbv;
334 
335  jbv.type = jbvString;
336  jbv.val.string.val = jspGetString(jsp, &jbv.val.string.len);
337 
338  JsonbHashScalarValue(&jbv, &path->hash);
339  return true;
340  }
341 
342  case jpiIndexArray:
343  case jpiAnyArray:
344  return true; /* path hash is unchanged */
345 
346  default:
347  /* other items (wildcard paths, item methods) are not supported */
348  return false;
349  }
350 }
char * val
Definition: jsonb.h:272
void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
Definition: jsonb_util.c:1258
JsonPathItemType type
Definition: jsonpath.h:107
enum jbvType type
Definition: jsonb.h:263
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1050

◆ jsonb_path_ops__extract_nodes()

static List* jsonb_path_ops__extract_nodes ( JsonPathGinContext cxt,
JsonPathGinPath  path,
JsonbValue scalar,
List nodes 
)
static

Definition at line 478 of file jsonb_gin.c.

References PathHashStack::hash, JsonPathGinPath::hash, JsonbHashScalarValue(), lappend(), make_jsp_entry_node(), and UInt32GetDatum.

Referenced by extract_jsp_query().

480 {
481  if (scalar)
482  {
483  /* append path hash node for equality queries */
484  uint32 hash = path.hash;
485 
486  JsonbHashScalarValue(scalar, &hash);
487 
488  return lappend(nodes,
490  }
491  else
492  {
493  /* jsonb_path_ops doesn't support EXISTS queries => nothing to append */
494  return nodes;
495  }
496 }
static JsonPathGinNode * make_jsp_entry_node(Datum entry)
Definition: jsonb_gin.c:353
void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
Definition: jsonb_util.c:1258
unsigned int uint32
Definition: c.h:358
#define UInt32GetDatum(X)
Definition: postgres.h:493
List * lappend(List *list, void *datum)
Definition: list.c:322
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:541

◆ make_jsp_entry_node()

static JsonPathGinNode* make_jsp_entry_node ( Datum  entry)
static

Definition at line 353 of file jsonb_gin.c.

References generate_unaccent_rules::args, JsonPathGinNode::entryDatum, JSP_GIN_ENTRY, offsetof, palloc(), JsonPathGinNode::type, and JsonPathGinNode::val.

Referenced by jsonb_ops__extract_nodes(), jsonb_path_ops__extract_nodes(), and make_jsp_entry_node_scalar().

354 {
356 
357  node->type = JSP_GIN_ENTRY;
358  node->val.entryDatum = entry;
359 
360  return node;
361 }
Datum entryDatum
Definition: jsonb_gin.c:105
union JsonPathGinNode::@28 val
JsonPathGinNodeType type
Definition: jsonb_gin.c:99
void * palloc(Size size)
Definition: mcxt.c:949
#define offsetof(type, field)
Definition: c.h:655

◆ make_jsp_entry_node_scalar()

static JsonPathGinNode* make_jsp_entry_node_scalar ( JsonbValue scalar,
bool  iskey 
)
static

Definition at line 364 of file jsonb_gin.c.

References make_jsp_entry_node(), and make_scalar_key().

Referenced by jsonb_ops__extract_nodes().

365 {
366  return make_jsp_entry_node(make_scalar_key(scalar, iskey));
367 }
static JsonPathGinNode * make_jsp_entry_node(Datum entry)
Definition: jsonb_gin.c:353
static Datum make_scalar_key(const JsonbValue *scalarVal, bool is_key)
Definition: jsonb_gin.c:1365

◆ make_jsp_expr_node()

static JsonPathGinNode* make_jsp_expr_node ( JsonPathGinNodeType  type,
int  nargs 
)
static

Definition at line 370 of file jsonb_gin.c.

References JsonPathGinNode::args, generate_unaccent_rules::args, JsonPathGinNode::nargs, offsetof, palloc(), JsonPathGinNode::type, generate_unaccent_rules::type, and JsonPathGinNode::val.

Referenced by make_jsp_expr_node_args(), and make_jsp_expr_node_binary().

371 {
373  sizeof(node->args[0]) * nargs);
374 
375  node->type = type;
376  node->val.nargs = nargs;
377 
378  return node;
379 }
JsonPathGinNode * args[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb_gin.c:108
union JsonPathGinNode::@28 val
JsonPathGinNodeType type
Definition: jsonb_gin.c:99
void * palloc(Size size)
Definition: mcxt.c:949
#define offsetof(type, field)
Definition: c.h:655

◆ make_jsp_expr_node_args()

static JsonPathGinNode* make_jsp_expr_node_args ( JsonPathGinNodeType  type,
List args 
)
static

Definition at line 382 of file jsonb_gin.c.

References JsonPathGinNode::args, i, lfirst, list_length(), and make_jsp_expr_node().

Referenced by extract_jsp_path_expr().

383 {
385  ListCell *lc;
386  int i = 0;
387 
388  foreach(lc, args)
389  node->args[i++] = lfirst(lc);
390 
391  return node;
392 }
JsonPathGinNode * args[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb_gin.c:108
static JsonPathGinNode * make_jsp_expr_node(JsonPathGinNodeType type, int nargs)
Definition: jsonb_gin.c:370
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
int i

◆ make_jsp_expr_node_binary()

static JsonPathGinNode* make_jsp_expr_node_binary ( JsonPathGinNodeType  type,
JsonPathGinNode arg1,
JsonPathGinNode arg2 
)
static

Definition at line 395 of file jsonb_gin.c.

References JsonPathGinNode::args, and make_jsp_expr_node().

Referenced by extract_jsp_bool_expr(), and jsonb_ops__extract_nodes().

397 {
399 
400  node->args[0] = arg1;
401  node->args[1] = arg2;
402 
403  return node;
404 }
JsonPathGinNode * args[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb_gin.c:108
static JsonPathGinNode * make_jsp_expr_node(JsonPathGinNodeType type, int nargs)
Definition: jsonb_gin.c:370

◆ make_scalar_key()

static Datum make_scalar_key ( const JsonbValue scalarVal,
bool  is_key 
)
static

Definition at line 1365 of file jsonb_gin.c.

References Assert, elog, ERROR, jbvBool, jbvNull, jbvNumeric, jbvString, JGINFLAG_BOOL, JGINFLAG_KEY, JGINFLAG_NULL, JGINFLAG_NUM, JGINFLAG_STR, make_text_key(), numeric_normalize(), pfree(), JsonbValue::type, and JsonbValue::val.

Referenced by gin_extract_jsonb(), and make_jsp_entry_node_scalar().

1366 {
1367  Datum item;
1368  char *cstr;
1369 
1370  switch (scalarVal->type)
1371  {
1372  case jbvNull:
1373  Assert(!is_key);
1374  item = make_text_key(JGINFLAG_NULL, "", 0);
1375  break;
1376  case jbvBool:
1377  Assert(!is_key);
1379  scalarVal->val.boolean ? "t" : "f", 1);
1380  break;
1381  case jbvNumeric:
1382  Assert(!is_key);
1383 
1384  /*
1385  * A normalized textual representation, free of trailing zeroes,
1386  * is required so that numerically equal values will produce equal
1387  * strings.
1388  *
1389  * It isn't ideal that numerics are stored in a relatively bulky
1390  * textual format. However, it's a notationally convenient way of
1391  * storing a "union" type in the GIN B-Tree, and indexing Jsonb
1392  * strings takes precedence.
1393  */
1394  cstr = numeric_normalize(scalarVal->val.numeric);
1395  item = make_text_key(JGINFLAG_NUM, cstr, strlen(cstr));
1396  pfree(cstr);
1397  break;
1398  case jbvString:
1399  item = make_text_key(is_key ? JGINFLAG_KEY : JGINFLAG_STR,
1400  scalarVal->val.string.val,
1401  scalarVal->val.string.len);
1402  break;
1403  default:
1404  elog(ERROR, "unrecognized jsonb scalar type: %d", scalarVal->type);
1405  item = 0; /* keep compiler quiet */
1406  break;
1407  }
1408 
1409  return item;
1410 }
char * numeric_normalize(Numeric num)
Definition: numeric.c:760
char * val
Definition: jsonb.h:272
Definition: jsonb.h:239
#define JGINFLAG_KEY
Definition: jsonb.h:62
Definition: jsonb.h:236
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define JGINFLAG_NULL
Definition: jsonb.h:63
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:732
#define JGINFLAG_STR
Definition: jsonb.h:66
enum jbvType type
Definition: jsonb.h:263
#define elog(elevel,...)
Definition: elog.h:226
#define JGINFLAG_NUM
Definition: jsonb.h:65
static Datum make_text_key(char flag, const char *str, int len)
Definition: jsonb_gin.c:1327
#define JGINFLAG_BOOL
Definition: jsonb.h:64

◆ make_text_key()

static Datum make_text_key ( char  flag,
const char *  str,
int  len 
)
static

Definition at line 1327 of file jsonb_gin.c.

References DatumGetUInt32, flag(), hash_any(), JGIN_MAXLENGTH, JGINFLAG_HASHED, palloc(), PointerGetDatum, SET_VARSIZE, snprintf, VARDATA, and VARHDRSZ.

Referenced by gin_extract_jsonb_query(), jsonb_ops__add_path_item(), and make_scalar_key().

1328 {
1329  text *item;
1330  char hashbuf[10];
1331 
1332  if (len > JGIN_MAXLENGTH)
1333  {
1334  uint32 hashval;
1335 
1336  hashval = DatumGetUInt32(hash_any((const unsigned char *) str, len));
1337  snprintf(hashbuf, sizeof(hashbuf), "%08x", hashval);
1338  str = hashbuf;
1339  len = 8;
1340  flag |= JGINFLAG_HASHED;
1341  }
1342 
1343  /*
1344  * Now build the text Datum. For simplicity we build a 4-byte-header
1345  * varlena text Datum here, but we expect it will get converted to short
1346  * header format when stored in the index.
1347  */
1348  item = (text *) palloc(VARHDRSZ + len + 1);
1349  SET_VARSIZE(item, VARHDRSZ + len + 1);
1350 
1351  *VARDATA(item) = flag;
1352 
1353  memcpy(VARDATA(item) + 1, str, len);
1354 
1355  return PointerGetDatum(item);
1356 }
#define DatumGetUInt32(X)
Definition: postgres.h:486
#define JGINFLAG_HASHED
Definition: jsonb.h:67
#define VARDATA(PTR)
Definition: postgres.h:302
Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.c:148
#define PointerGetDatum(X)
Definition: postgres.h:556
#define VARHDRSZ
Definition: c.h:555
#define JGIN_MAXLENGTH
Definition: jsonb.h:68
char * flag(int b)
Definition: test-ctype.c:33
unsigned int uint32
Definition: c.h:358
void * palloc(Size size)
Definition: mcxt.c:949
Definition: c.h:549
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define snprintf
Definition: port.h:192