Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 87153d3

Browse filesBrowse files
committed
implement IS needed for schema check feature. Index doesnt support it yet
1 parent 7ddf618 commit 87153d3
Copy full SHA for 87153d3

File tree

8 files changed

+200
-18
lines changed
Filter options

8 files changed

+200
-18
lines changed

‎expected/jsquery.out

Copy file name to clipboardExpand all lines: expected/jsquery.out
+67Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,73 @@ ERROR: bad jsquery representation
958958
LINE 1: select 'a\r = x"\\abcd"'::jsquery AS err;
959959
^
960960
DETAIL: syntax error, unexpected STRING_P, expecting $end at or near """
961+
--IS
962+
select 'as IS boolean | as is ARRAY | as is ObJect | as is Number | as is string'::jsquery;
963+
jsquery
964+
--------------------------------------------------------------------------------------------
965+
(((("as" IS BOOLEAN | "as" IS ARRAY) | "as" IS OBJECT) | "as" IS NUMBER) | "as" IS STRING)
966+
(1 row)
967+
968+
select '{"as": "xxx"}' @@ 'as IS string'::jsquery;
969+
?column?
970+
----------
971+
t
972+
(1 row)
973+
974+
select '{"as": "xxx"}' @@ 'as IS boolean | as is ARRAY | as is ObJect | as is Number'::jsquery;
975+
?column?
976+
----------
977+
f
978+
(1 row)
979+
980+
select '{"as": 5}' @@ 'as is Number'::jsquery;
981+
?column?
982+
----------
983+
t
984+
(1 row)
985+
986+
select '{"as": true}' @@ 'as is boolean'::jsquery;
987+
?column?
988+
----------
989+
t
990+
(1 row)
991+
992+
select '{"as": false}' @@ 'as is boolean'::jsquery;
993+
?column?
994+
----------
995+
t
996+
(1 row)
997+
998+
select '{"as": "false"}' @@ 'as is boolean'::jsquery;
999+
?column?
1000+
----------
1001+
f
1002+
(1 row)
1003+
1004+
select '["xxx"]' @@ '$ IS array'::jsquery;
1005+
?column?
1006+
----------
1007+
t
1008+
(1 row)
1009+
1010+
select '{"as": false}' @@ '$ IS object'::jsquery;
1011+
?column?
1012+
----------
1013+
t
1014+
(1 row)
1015+
1016+
select '"xxx"' @@ '$ IS string'::jsquery;
1017+
?column?
1018+
----------
1019+
t
1020+
(1 row)
1021+
1022+
select '"xxx"' @@ '$ IS number'::jsquery;
1023+
?column?
1024+
----------
1025+
f
1026+
(1 row)
1027+
9611028
---table and index
9621029
select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 0;
9631030
count

‎jsquery.h

Copy file name to clipboardExpand all lines: jsquery.h
+4-3Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ typedef enum JsQueryItemType {
5151
jqiAnyKey = '%',
5252
jqiKey = 'K',
5353
jqiCurrent = '$',
54-
jqiIn = 'I'
54+
jqiIn = 'I',
55+
jqiIs = 'i'
5556
} JsQueryItemType;
5657

5758
/*
@@ -87,8 +88,6 @@ typedef struct JsQueryItem {
8788
int32 *arrayPtr;
8889
} array;
8990
};
90-
91-
9291
} JsQueryItem;
9392

9493
extern void jsqInit(JsQueryItem *v, JsQuery *js);
@@ -99,6 +98,7 @@ extern void jsqGetLeftArg(JsQueryItem *v, JsQueryItem *a);
9998
extern void jsqGetRightArg(JsQueryItem *v, JsQueryItem *a);
10099
extern Numeric jsqGetNumeric(JsQueryItem *v);
101100
extern bool jsqGetBool(JsQueryItem *v);
101+
extern int32 jsqGetIsType(JsQueryItem *v);
102102
extern char * jsqGetString(JsQueryItem *v, int32 *len);
103103
extern void jsqIterateInit(JsQueryItem *v);
104104
extern bool jsqIterateArray(JsQueryItem *v, JsQueryItem *e);
@@ -122,6 +122,7 @@ struct JsQueryParseItem {
122122
} args;
123123

124124
JsQueryParseItem *arg;
125+
int8 isType; /* jbv* values */
125126

126127
Numeric numeric;
127128
bool boolean;

‎jsquery_gram.y

Copy file name to clipboardExpand all lines: jsquery_gram.y
+40-11Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,16 @@ makeItemUnary(int type, JsQueryParseItem* a)
152152
return v;
153153
}
154154

155+
static JsQueryParseItem*
156+
makeItemIs(int isType)
157+
{
158+
JsQueryParseItem *v = makeItemType(jqiIs);
159+
160+
v->isType = isType;
161+
162+
return v;
163+
}
164+
155165
static JsQueryParseItem*
156166
makeItemList(List *list) {
157167
JsQueryParseItem *head, *end;
@@ -183,21 +193,23 @@ makeItemList(List *list) {
183193

184194
%union {
185195
string str;
186-
Numeric numeric;
187196
List *elems; /* list of JsQueryParseItem */
188197

189198
JsQueryParseItem *value;
190199
}
191200

192-
%token <str> NULL_P STRING_P TRUE_P FALSE_P
193-
NUMERIC_P IN_P
201+
%token <str> IN_P IS_P NULL_P TRUE_P ARRAY_P
202+
FALSE_P NUMBER_P OBJECT_P TEXT_P
203+
BOOLEAN_P
204+
205+
%token <str> STRING_P NUMERIC_P
194206

195-
%type <value> result scalar_value
196-
%type <str> key
207+
%type <value> result scalar_value
208+
%type <str> key
197209

198-
%type <elems> path value_list
210+
%type <elems> path value_list
199211

200-
%type <value> path_elem right_expr expr array
212+
%type <value> path_elem right_expr expr array
201213

202214
%left '|'
203215
%left '&'
@@ -216,11 +228,17 @@ array:
216228
;
217229

218230
scalar_value:
219-
NULL_P { $$ = makeItemString(NULL); }
220-
| STRING_P { $$ = makeItemString(&$1); }
231+
STRING_P { $$ = makeItemString(&$1); }
221232
| IN_P { $$ = makeItemString(&$1); }
233+
| IS_P { $$ = makeItemString(&$1); }
234+
| NULL_P { $$ = makeItemString(NULL); }
222235
| TRUE_P { $$ = makeItemBool(true); }
236+
| ARRAY_P { $$ = makeItemString(&$1); }
223237
| FALSE_P { $$ = makeItemBool(false); }
238+
| NUMBER_P { $$ = makeItemString(&$1); }
239+
| OBJECT_P { $$ = makeItemString(&$1); }
240+
| TEXT_P { $$ = makeItemString(&$1); }
241+
| BOOLEAN_P { $$ = makeItemString(&$1); }
224242
| NUMERIC_P { $$ = makeItemNumeric(&$1); }
225243
;
226244

@@ -241,6 +259,11 @@ right_expr:
241259
| '@' '>' array { $$ = makeItemUnary(jqiContains, $3); }
242260
| '<' '@' array { $$ = makeItemUnary(jqiContained, $3); }
243261
| '&' '&' array { $$ = makeItemUnary(jqiOverlap, $3); }
262+
| IS_P ARRAY_P { $$ = makeItemIs(jbvArray); }
263+
| IS_P NUMBER_P { $$ = makeItemIs(jbvNumeric); }
264+
| IS_P OBJECT_P { $$ = makeItemIs(jbvObject); }
265+
| IS_P TEXT_P { $$ = makeItemIs(jbvString); }
266+
| IS_P BOOLEAN_P { $$ = makeItemIs(jbvBool); }
244267
;
245268

246269
expr:
@@ -257,11 +280,17 @@ expr:
257280
*/
258281
key:
259282
STRING_P { $$ = $1; }
283+
| IN_P { $$ = $1; }
284+
| IS_P { $$ = $1; }
285+
| NULL_P { $$ = $1; }
260286
| TRUE_P { $$ = $1; }
287+
| ARRAY_P { $$ = $1; }
261288
| FALSE_P { $$ = $1; }
289+
| NUMBER_P { $$ = $1; }
290+
| OBJECT_P { $$ = $1; }
291+
| TEXT_P { $$ = $1; }
292+
| BOOLEAN_P { $$ = $1; }
262293
| NUMERIC_P { $$ = $1; }
263-
| NULL_P { $$ = $1; }
264-
| IN_P { $$ = $1; }
265294
;
266295

267296
path_elem:

‎jsquery_io.c

Copy file name to clipboardExpand all lines: jsquery_io.c
+28-1Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item)
5050
case jqiBool:
5151
appendBinaryStringInfo(buf, (char*)&item->boolean, sizeof(item->boolean));
5252
break;
53+
case jqiIs:
54+
appendBinaryStringInfo(buf, (char*)&item->isType, sizeof(item->isType));
55+
break;
5356
case jqiArray:
5457
{
5558
int32 i, arrayStart;
@@ -203,13 +206,37 @@ printJsQueryItem(StringInfo buf, JsQueryItem *v, bool inKey, bool printBracketes
203206
appendStringInfoString(buf,
204207
DatumGetCString(DirectFunctionCall1(numeric_out,
205208
PointerGetDatum(jsqGetNumeric(v)))));
206-
break;
209+
break;
207210
case jqiBool:
208211
if (jsqGetBool(v))
209212
appendBinaryStringInfo(buf, "true", 4);
210213
else
211214
appendBinaryStringInfo(buf, "false", 5);
212215
break;
216+
case jqiIs:
217+
appendBinaryStringInfo(buf, " IS ", 4);
218+
switch(jsqGetIsType(v))
219+
{
220+
case jbvString:
221+
appendBinaryStringInfo(buf, "STRING", 6);
222+
break;
223+
case jbvNumeric:
224+
appendBinaryStringInfo(buf, "NUMBER", 6);
225+
break;
226+
case jbvBool:
227+
appendBinaryStringInfo(buf, "BOOLEAN", 7);
228+
break;
229+
case jbvArray:
230+
appendBinaryStringInfo(buf, "ARRAY", 5);
231+
break;
232+
case jbvObject:
233+
appendBinaryStringInfo(buf, "OBJECT", 6);
234+
break;
235+
default:
236+
elog(ERROR, "Unknown type for IS: %d", jsqGetIsType(v));
237+
break;
238+
}
239+
break;
213240
case jqiArray:
214241
if (printBracketes)
215242
appendStringInfoChar(buf, '[');

‎jsquery_op.c

Copy file name to clipboardExpand all lines: jsquery_op.c
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,30 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb)
427427
jsqGetArg(jsq, &elem);
428428
res = executeExpr(&elem, jsq->type, jb);
429429
break;
430+
case jqiIs:
431+
if (JsonbType(jb) == jbvScalar)
432+
{
433+
JsonbIterator *it;
434+
int32 r;
435+
JsonbValue v;
436+
437+
it = JsonbIteratorInit(jb->val.binary.data);
438+
439+
r = JsonbIteratorNext(&it, &v, true);
440+
Assert(r == WJB_BEGIN_ARRAY);
441+
Assert(v.val.array.rawScalar == 1);
442+
Assert(v.val.array.nElems == 1);
443+
444+
r = JsonbIteratorNext(&it, &v, true);
445+
Assert(r == WJB_ELEM);
446+
447+
res = (jsqGetIsType(jsq) == JsonbType(&v));
448+
}
449+
else
450+
{
451+
res = (jsqGetIsType(jsq) == JsonbType(jb));
452+
}
453+
break;
430454
default:
431455
elog(ERROR,"Wrong state: %d", jsq->type);
432456
}

‎jsquery_scan.l

Copy file name to clipboardExpand all lines: jsquery_scan.l
+14-3Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,22 @@ typedef struct keyword
191191
char *keyword;
192192
} keyword;
193193

194+
/*
195+
* Array of key words should be sorted by length and then
196+
* alphabetical order
197+
*/
198+
194199
static keyword keywords[] = {
195-
{ 2, false, IN_P, "in" },
200+
{ 2, false, IN_P, "in"},
201+
{ 2, false, IS_P, "is"},
196202
{ 4, true, NULL_P, "null"},
197203
{ 4, true, TRUE_P, "true"},
198-
{ 5, true, FALSE_P, "false"}
204+
{ 5, false, ARRAY_P, "array"},
205+
{ 5, true, FALSE_P, "false"},
206+
{ 6, false, NUMBER_P, "number"},
207+
{ 6, false, OBJECT_P, "object"},
208+
{ 6, false, TEXT_P, "string"},
209+
{ 7, false, BOOLEAN_P, "boolean"},
199210
};
200211

201212
static int
@@ -212,7 +223,7 @@ checkSpecialVal()
212223

213224
while(StopLow < StopHigh)
214225
{
215-
StopMiddle = StopLow + (StopHigh - StopLow) / 2;
226+
StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
216227

217228
if (StopMiddle->len == scanstring.len)
218229
diff = pg_strncasecmp(StopMiddle->keyword, scanstring.val, scanstring.len);

‎jsquery_support.c

Copy file name to clipboardExpand all lines: jsquery_support.c
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ jsqInitByBuffer(JsQueryItem *v, char *base, int32 pos)
7979
/* follow next */
8080
case jqiNumeric:
8181
case jqiBool:
82+
case jqiIs:
8283
v->value.data = base + pos;
8384
break;
8485
case jqiArray:
@@ -186,6 +187,14 @@ jsqGetNumeric(JsQueryItem *v)
186187
return (Numeric)v->value.data;
187188
}
188189

190+
int32
191+
jsqGetIsType(JsQueryItem *v)
192+
{
193+
Assert(v->type = jqiIs);
194+
195+
return (int32)*v->value.data;
196+
}
197+
189198
char*
190199
jsqGetString(JsQueryItem *v, int32 *len)
191200
{

‎sql/jsquery.sql

Copy file name to clipboardExpand all lines: sql/jsquery.sql
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,20 @@ select 'a\r = "\abcdx"'::jsquery AS err;
193193
select 'a\r = "\\abcdx"'::jsquery;
194194
select 'a\r = x"\\abcd"'::jsquery AS err;
195195

196+
--IS
197+
198+
select 'as IS boolean | as is ARRAY | as is ObJect | as is Number | as is string'::jsquery;
199+
select '{"as": "xxx"}' @@ 'as IS string'::jsquery;
200+
select '{"as": "xxx"}' @@ 'as IS boolean | as is ARRAY | as is ObJect | as is Number'::jsquery;
201+
select '{"as": 5}' @@ 'as is Number'::jsquery;
202+
select '{"as": true}' @@ 'as is boolean'::jsquery;
203+
select '{"as": false}' @@ 'as is boolean'::jsquery;
204+
select '{"as": "false"}' @@ 'as is boolean'::jsquery;
205+
select '["xxx"]' @@ '$ IS array'::jsquery;
206+
select '{"as": false}' @@ '$ IS object'::jsquery;
207+
select '"xxx"' @@ '$ IS string'::jsquery;
208+
select '"xxx"' @@ '$ IS number'::jsquery;
209+
196210
---table and index
197211

198212
select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 0;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.