@@ -131,6 +131,7 @@ static Node *transformJsonArrayQueryConstructor(ParseState *pstate,
131
131
JsonArrayQueryConstructor * ctor );
132
132
static Node * transformJsonObjectAgg (ParseState * pstate , JsonObjectAgg * agg );
133
133
static Node * transformJsonArrayAgg (ParseState * pstate , JsonArrayAgg * agg );
134
+ static Node * transformJsonIsPredicate (ParseState * pstate , JsonIsPredicate * p );
134
135
static Node * make_row_comparison_op (ParseState * pstate , List * opname ,
135
136
List * largs , List * rargs , int location );
136
137
static Node * make_row_distinct_op (ParseState * pstate , List * opname ,
@@ -399,6 +400,10 @@ transformExprRecurse(ParseState *pstate, Node *expr)
399
400
result = transformJsonArrayAgg (pstate , (JsonArrayAgg * ) expr );
400
401
break ;
401
402
403
+ case T_JsonIsPredicate :
404
+ result = transformJsonIsPredicate (pstate , (JsonIsPredicate * ) expr );
405
+ break ;
406
+
402
407
default :
403
408
/* should not reach here */
404
409
elog (ERROR , "unrecognized node type: %d" , (int ) nodeTag (expr ));
@@ -4340,3 +4345,101 @@ transformJsonArrayConstructor(ParseState *pstate, JsonArrayConstructor *ctor)
4340
4345
returning , false, ctor -> absent_on_null ,
4341
4346
ctor -> location );
4342
4347
}
4348
+
4349
+ static const char *
4350
+ JsonValueTypeStrings [] =
4351
+ {
4352
+ "any" ,
4353
+ "object" ,
4354
+ "array" ,
4355
+ "scalar" ,
4356
+ };
4357
+
4358
+ static Const *
4359
+ makeJsonValueTypeConst (JsonValueType type )
4360
+ {
4361
+ return makeConst (TEXTOID , -1 , InvalidOid , -1 ,
4362
+ PointerGetDatum (cstring_to_text (
4363
+ JsonValueTypeStrings [(int ) type ])),
4364
+ false, false);
4365
+ }
4366
+
4367
+ /*
4368
+ * Transform IS JSON predicate into
4369
+ * json[b]_is_valid(json, value_type [, check_key_uniqueness]) call.
4370
+ */
4371
+ static Node *
4372
+ transformJsonIsPredicate (ParseState * pstate , JsonIsPredicate * pred )
4373
+ {
4374
+ Node * expr = transformExprRecurse (pstate , pred -> expr );
4375
+ Oid exprtype = exprType (expr );
4376
+ FuncExpr * fexpr ;
4377
+
4378
+ /* prepare input document */
4379
+ if (exprtype == BYTEAOID )
4380
+ {
4381
+ expr = makeJsonByteaToTextConversion (expr , pred -> format ,
4382
+ exprLocation (expr ));
4383
+ exprtype = TEXTOID ;
4384
+ }
4385
+ else
4386
+ {
4387
+ char typcategory ;
4388
+ bool typispreferred ;
4389
+
4390
+ get_type_category_preferred (exprtype , & typcategory , & typispreferred );
4391
+
4392
+ if (exprtype == UNKNOWNOID || typcategory == TYPCATEGORY_STRING )
4393
+ {
4394
+ expr = coerce_to_target_type (pstate , (Node * ) expr , exprtype ,
4395
+ TEXTOID , -1 ,
4396
+ COERCION_IMPLICIT ,
4397
+ COERCE_IMPLICIT_CAST , -1 );
4398
+ exprtype = TEXTOID ;
4399
+ }
4400
+
4401
+ if (pred -> format -> encoding != JS_ENC_DEFAULT )
4402
+ ereport (ERROR ,
4403
+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
4404
+ parser_errposition (pstate , pred -> format -> location ),
4405
+ errmsg ("cannot use JSON FORMAT ENCODING clause for non-bytea input types" )));
4406
+ }
4407
+
4408
+ expr = (Node * ) makeJsonValueExpr ((Expr * ) expr , pred -> format );
4409
+
4410
+ /* make resulting expression */
4411
+ if (exprtype == TEXTOID || exprtype == JSONOID )
4412
+ {
4413
+ fexpr = makeFuncExpr (F_JSON_IS_VALID , BOOLOID ,
4414
+ list_make3 (expr ,
4415
+ makeJsonValueTypeConst (pred -> value_type ),
4416
+ makeBoolConst (pred -> unique_keys , false)),
4417
+ InvalidOid , InvalidOid , COERCE_EXPLICIT_CALL );
4418
+
4419
+ fexpr -> location = pred -> location ;
4420
+ }
4421
+ else if (exprtype == JSONBOID )
4422
+ {
4423
+ /* XXX the following expressions also can be used here:
4424
+ * jsonb_type(jsonb) = 'type' (for object and array checks)
4425
+ * CASE jsonb_type(jsonb) WHEN ... END (for scalars checks)
4426
+ */
4427
+ fexpr = makeFuncExpr (F_JSONB_IS_VALID , BOOLOID ,
4428
+ list_make2 (expr ,
4429
+ makeJsonValueTypeConst (pred -> value_type )),
4430
+ InvalidOid , InvalidOid , COERCE_EXPLICIT_CALL );
4431
+
4432
+ fexpr -> location = pred -> location ;
4433
+ }
4434
+ else
4435
+ {
4436
+ ereport (ERROR ,
4437
+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
4438
+ errmsg ("cannot use type %s in IS JSON predicate" ,
4439
+ format_type_be (exprtype ))));
4440
+ return NULL ;
4441
+ }
4442
+
4443
+ return makeJsonIsPredicate ((Node * ) fexpr , NULL , pred -> value_type ,
4444
+ pred -> unique_keys );
4445
+ }
0 commit comments