/*------------------------------------------------------------------------- * * jsquery.h * Definitions of jsquery datatype * * Copyright (c) 2014, PostgreSQL Global Development Group * Author: Teodor Sigaev * * IDENTIFICATION * contrib/jsquery/jsquery.h * *------------------------------------------------------------------------- */ #ifndef __JSQUERY_H__ #define __JSQUERY_H__ #include "access/gin.h" #include "fmgr.h" #include "utils/numeric.h" #include "utils/jsonb.h" typedef struct { int32 vl_len_; /* varlena header (do not touch directly!) */ } JsQuery; #define DatumGetJsQueryP(d) ((JsQuery*)DatumGetPointer(PG_DETOAST_DATUM(d))) #define PG_GETARG_JSQUERY(x) DatumGetJsQueryP(PG_GETARG_DATUM(x)) #define PG_RETURN_JSQUERY(p) PG_RETURN_POINTER(p) typedef enum JsQueryItemType { jqiNull = jbvNull, jqiString = jbvString, jqiNumeric = jbvNumeric, jqiBool = jbvBool, jqiArray = jbvArray, jqiAnd, jqiOr, jqiNot, jqiEqual, jqiLess, jqiGreater, jqiLessOrEqual, jqiGreaterOrEqual, jqiContains, jqiContained, jqiOverlap, jqiAny, jqiAnyArray, jqiAnyKey, jqiAll, jqiAllArray, jqiAllKey, jqiKey, jqiCurrent, jqiLength, jqiIn, jqiIs } JsQueryItemType; /* * JsQueryHint is stored in the same byte as JsQueryItemType so * JsQueryItemType should not use two high bits */ typedef enum JsQueryHint { jsqIndexDefault = 0x00, jsqForceIndex = 0x80, jsqNoIndex = 0x40 } JsQueryHint; #define JSQ_HINT_MASK (jsqIndexDefault | jsqForceIndex | jsqNoIndex) /* * Support functions to parse/construct binary value. * Unlike many other representation of expression the first/main * node is not an operation but left operand of expression. That * allows to implement cheep follow-path descending in jsonb * structure and then execute operator with right operand which * is always a constant. */ typedef struct JsQueryItem { JsQueryItemType type; JsQueryHint hint; int32 nextPos; char *base; union { struct { char *data; /* for bool, numeric and string/key */ int datalen; /* filled only for string/key */ } value; struct { int32 left; int32 right; } args; int32 arg; struct { int nelems; int current; int32 *arrayPtr; } array; }; } JsQueryItem; extern void jsqInit(JsQueryItem *v, JsQuery *js); extern void jsqInitByBuffer(JsQueryItem *v, char *base, int32 pos); extern bool jsqGetNext(JsQueryItem *v, JsQueryItem *a); extern void jsqGetArg(JsQueryItem *v, JsQueryItem *a); extern void jsqGetLeftArg(JsQueryItem *v, JsQueryItem *a); extern void jsqGetRightArg(JsQueryItem *v, JsQueryItem *a); extern Numeric jsqGetNumeric(JsQueryItem *v); extern bool jsqGetBool(JsQueryItem *v); extern int32 jsqGetIsType(JsQueryItem *v); extern char * jsqGetString(JsQueryItem *v, int32 *len); extern void jsqIterateInit(JsQueryItem *v); extern bool jsqIterateArray(JsQueryItem *v, JsQueryItem *e); void alignStringInfoInt(StringInfo buf); /* * Parsing */ typedef struct JsQueryParseItem JsQueryParseItem; struct JsQueryParseItem { JsQueryItemType type; JsQueryHint hint; JsQueryParseItem *next; /* next in path */ union { struct { JsQueryParseItem *left; JsQueryParseItem *right; } args; JsQueryParseItem *arg; int8 isType; /* jbv* values */ Numeric numeric; bool boolean; struct { uint32 len; char *val; /* could not be not null-terminated */ } string; struct { int nelems; JsQueryParseItem **elems; } array; }; }; extern JsQueryParseItem* parsejsquery(const char *str, int len); /* jsquery_extract.c */ typedef enum { iAny = jqiAny, iAnyArray = jqiAnyArray, iKey = jqiKey, iAnyKey = jqiAnyKey } PathItemType; typedef struct PathItem PathItem; struct PathItem { PathItemType type; int len; char *s; PathItem *parent; }; typedef enum { eExactValue = 1, eEmptyArray, eInequality, eIs, eAny, eAnd = jqiAnd, eOr = jqiOr, } ExtractedNodeType; typedef enum { sEqual = 1, sRange, sInequal, sIs, sAny } SelectivityClass; typedef struct ExtractedNode ExtractedNode; struct ExtractedNode { ExtractedNodeType type; JsQueryHint hint; PathItem *path; bool indirect; SelectivityClass sClass; bool forceIndex; int number; int entryNum; union { struct { ExtractedNode **items; int count; } args; struct { bool leftInclusive; bool rightInclusive; JsQueryItem *leftBound; JsQueryItem *rightBound; } bounds; JsQueryItem *exactValue; int32 isType; }; }; typedef int (*MakeEntryHandler)(ExtractedNode *node, Pointer extra); typedef bool (*CheckEntryHandler)(ExtractedNode *node, Pointer extra); bool isLogicalNodeType(ExtractedNodeType type); ExtractedNode *extractJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, CheckEntryHandler checkHandler, Pointer extra); char *debugJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, CheckEntryHandler checkHandler, Pointer extra); bool queryNeedRecheck(ExtractedNode *node); bool execRecursive(ExtractedNode *node, bool *check); bool execRecursiveTristate(ExtractedNode *node, GinTernaryValue *check); #endif