@@ -130,6 +130,7 @@ static Node *transformJsonArrayQueryCtor(ParseState *pstate,
130130 JsonArrayQueryCtor * ctor );
131131static Node * transformJsonObjectAgg (ParseState * pstate , JsonObjectAgg * agg );
132132static Node * transformJsonArrayAgg (ParseState * pstate , JsonArrayAgg * agg );
133+ static Node * transformJsonIsPredicate (ParseState * pstate , JsonIsPredicate * p );
133134static Node * make_row_comparison_op (ParseState * pstate , List * opname ,
134135 List * largs , List * rargs , int location );
135136static Node * make_row_distinct_op (ParseState * pstate , List * opname ,
@@ -398,6 +399,10 @@ transformExprRecurse(ParseState *pstate, Node *expr)
398399 result = transformJsonArrayAgg (pstate , (JsonArrayAgg * ) expr );
399400 break ;
400401
402+ case T_JsonIsPredicate :
403+ result = transformJsonIsPredicate (pstate , (JsonIsPredicate * ) expr );
404+ break ;
405+
401406 default :
402407 /* should not reach here */
403408 elog (ERROR , "unrecognized node type: %d" , (int ) nodeTag (expr ));
@@ -4155,3 +4160,108 @@ transformJsonArrayCtor(ParseState *pstate, JsonArrayCtor *ctor)
41554160
41564161 return coerceJsonFuncExpr (pstate , (Node * ) fexpr , & returning , true);
41574162}
4163+
4164+ static const char *
4165+ JsonValueTypeStrings [] =
4166+ {
4167+ "any" ,
4168+ "object" ,
4169+ "array" ,
4170+ "scalar" ,
4171+ };
4172+
4173+ static Const *
4174+ makeJsonValueTypeConst (JsonValueType type )
4175+ {
4176+ return makeConst (TEXTOID , -1 , InvalidOid , -1 ,
4177+ PointerGetDatum (cstring_to_text (
4178+ JsonValueTypeStrings [(int ) type ])),
4179+ false, false);
4180+ }
4181+
4182+ /*
4183+ * Transform IS JSON predicate into
4184+ * json[b]_is_valid(json, value_type [, check_key_uniqueness]) call.
4185+ */
4186+ static Node *
4187+ transformJsonIsPredicate (ParseState * pstate , JsonIsPredicate * pred )
4188+ {
4189+ Node * expr = transformExprRecurse (pstate , pred -> expr );
4190+ Oid exprtype = exprType (expr );
4191+ FuncExpr * fexpr ;
4192+ JsonIsPredicateOpts * opts ;
4193+
4194+ /* prepare input document */
4195+ if (exprtype == BYTEAOID )
4196+ {
4197+ expr = makeJsonByteaToTextConversion (expr , & pred -> format ,
4198+ exprLocation (expr ));
4199+ exprtype = TEXTOID ;
4200+ }
4201+ else
4202+ {
4203+ char typcategory ;
4204+ bool typispreferred ;
4205+
4206+ get_type_category_preferred (exprtype , & typcategory , & typispreferred );
4207+
4208+ if (exprtype == UNKNOWNOID || typcategory == TYPCATEGORY_STRING )
4209+ {
4210+ expr = coerce_to_target_type (pstate , (Node * ) expr , exprtype ,
4211+ TEXTOID , -1 ,
4212+ COERCION_IMPLICIT ,
4213+ COERCE_IMPLICIT_CAST , -1 );
4214+ exprtype = TEXTOID ;
4215+ }
4216+
4217+ if (pred -> format .encoding != JS_ENC_DEFAULT )
4218+ ereport (ERROR ,
4219+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
4220+ parser_errposition (pstate , pred -> format .location ),
4221+ errmsg ("cannot use JSON FORMAT ENCODING clause for non-bytea input types" )));
4222+ }
4223+
4224+ expr = (Node * ) makeJsonValueExpr ((Expr * ) expr , pred -> format );
4225+
4226+ /* make resulting expression */
4227+ if (exprtype == TEXTOID || exprtype == JSONOID )
4228+ {
4229+ fexpr = makeFuncExpr (F_JSON_IS_VALID , BOOLOID ,
4230+ list_make3 (expr ,
4231+ makeJsonValueTypeConst (pred -> vtype ),
4232+ makeBoolConst (pred -> unique_keys , false)),
4233+ InvalidOid , InvalidOid , COERCE_EXPLICIT_CALL );
4234+
4235+ fexpr -> location = pred -> location ;
4236+ }
4237+ else if (exprtype == JSONBOID )
4238+ {
4239+ /* XXX the following expressions also can be used here:
4240+ * jsonb_type(jsonb) = 'type' (for object and array checks)
4241+ * CASE jsonb_type(jsonb) WHEN ... END (for scalars checks)
4242+ */
4243+ fexpr = makeFuncExpr (F_JSONB_IS_VALID , BOOLOID ,
4244+ list_make2 (expr ,
4245+ makeJsonValueTypeConst (pred -> vtype )),
4246+ InvalidOid , InvalidOid , COERCE_EXPLICIT_CALL );
4247+
4248+ fexpr -> location = pred -> location ;
4249+ }
4250+ else
4251+ {
4252+ ereport (ERROR ,
4253+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
4254+ errmsg ("cannot use type %s in IS JSON predicate" ,
4255+ format_type_be (exprtype ))));
4256+ return NULL ;
4257+ }
4258+
4259+ opts = makeNode (JsonIsPredicateOpts );
4260+ opts -> unique_keys = pred -> unique_keys ;
4261+ opts -> value_type = pred -> vtype ;
4262+
4263+ fexpr -> funcformat2 = FUNCFMT_IS_JSON ;
4264+ fexpr -> funcformatopts = (Node * ) opts ;
4265+
4266+ return (Node * ) fexpr ;
4267+ }
0 commit comments