@@ -131,6 +131,7 @@ static Node *transformJsonArrayQueryConstructor(ParseState *pstate,
131131 JsonArrayQueryConstructor * ctor );
132132static Node * transformJsonObjectAgg (ParseState * pstate , JsonObjectAgg * agg );
133133static Node * transformJsonArrayAgg (ParseState * pstate , JsonArrayAgg * agg );
134+ static Node * transformJsonIsPredicate (ParseState * pstate , JsonIsPredicate * p );
134135static Node * make_row_comparison_op (ParseState * pstate , List * opname ,
135136 List * largs , List * rargs , int location );
136137static Node * make_row_distinct_op (ParseState * pstate , List * opname ,
@@ -399,6 +400,10 @@ transformExprRecurse(ParseState *pstate, Node *expr)
399400 result = transformJsonArrayAgg (pstate , (JsonArrayAgg * ) expr );
400401 break ;
401402
403+ case T_JsonIsPredicate :
404+ result = transformJsonIsPredicate (pstate , (JsonIsPredicate * ) expr );
405+ break ;
406+
402407 default :
403408 /* should not reach here */
404409 elog (ERROR , "unrecognized node type: %d" , (int ) nodeTag (expr ));
@@ -4340,3 +4345,101 @@ transformJsonArrayConstructor(ParseState *pstate, JsonArrayConstructor *ctor)
43404345 returning , false, ctor -> absent_on_null ,
43414346 ctor -> location );
43424347}
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