@@ -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 ));
@@ -4174,3 +4179,108 @@ transformJsonArrayCtor(ParseState *pstate, JsonArrayCtor *ctor)
41744179
41754180 return coerceJsonFuncExpr (pstate , (Node * ) fexpr , & returning , true);
41764181}
4182+
4183+ static const char *
4184+ JsonValueTypeStrings [] =
4185+ {
4186+ "any" ,
4187+ "object" ,
4188+ "array" ,
4189+ "scalar" ,
4190+ };
4191+
4192+ static Const *
4193+ makeJsonValueTypeConst (JsonValueType type )
4194+ {
4195+ return makeConst (TEXTOID , -1 , InvalidOid , -1 ,
4196+ PointerGetDatum (cstring_to_text (
4197+ JsonValueTypeStrings [(int ) type ])),
4198+ false, false);
4199+ }
4200+
4201+ /*
4202+ * Transform IS JSON predicate into
4203+ * json[b]_is_valid(json, value_type [, check_key_uniqueness]) call.
4204+ */
4205+ static Node *
4206+ transformJsonIsPredicate (ParseState * pstate , JsonIsPredicate * pred )
4207+ {
4208+ Node * expr = transformExprRecurse (pstate , pred -> expr );
4209+ Oid exprtype = exprType (expr );
4210+ FuncExpr * fexpr ;
4211+ JsonIsPredicateOpts * opts ;
4212+
4213+ /* prepare input document */
4214+ if (exprtype == BYTEAOID )
4215+ {
4216+ expr = makeJsonByteaToTextConversion (expr , & pred -> format ,
4217+ exprLocation (expr ));
4218+ exprtype = TEXTOID ;
4219+ }
4220+ else
4221+ {
4222+ char typcategory ;
4223+ bool typispreferred ;
4224+
4225+ get_type_category_preferred (exprtype , & typcategory , & typispreferred );
4226+
4227+ if (exprtype == UNKNOWNOID || typcategory == TYPCATEGORY_STRING )
4228+ {
4229+ expr = coerce_to_target_type (pstate , (Node * ) expr , exprtype ,
4230+ TEXTOID , -1 ,
4231+ COERCION_IMPLICIT ,
4232+ COERCE_IMPLICIT_CAST , -1 );
4233+ exprtype = TEXTOID ;
4234+ }
4235+
4236+ if (pred -> format .encoding != JS_ENC_DEFAULT )
4237+ ereport (ERROR ,
4238+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
4239+ parser_errposition (pstate , pred -> format .location ),
4240+ errmsg ("cannot use JSON FORMAT ENCODING clause for non-bytea input types" )));
4241+ }
4242+
4243+ expr = (Node * ) makeJsonValueExpr ((Expr * ) expr , pred -> format );
4244+
4245+ /* make resulting expression */
4246+ if (exprtype == TEXTOID || exprtype == JSONOID )
4247+ {
4248+ fexpr = makeFuncExpr (F_JSON_IS_VALID , BOOLOID ,
4249+ list_make3 (expr ,
4250+ makeJsonValueTypeConst (pred -> vtype ),
4251+ makeBoolConst (pred -> unique_keys , false)),
4252+ InvalidOid , InvalidOid , COERCE_EXPLICIT_CALL );
4253+
4254+ fexpr -> location = pred -> location ;
4255+ }
4256+ else if (exprtype == JSONBOID )
4257+ {
4258+ /* XXX the following expressions also can be used here:
4259+ * jsonb_type(jsonb) = 'type' (for object and array checks)
4260+ * CASE jsonb_type(jsonb) WHEN ... END (for scalars checks)
4261+ */
4262+ fexpr = makeFuncExpr (F_JSONB_IS_VALID , BOOLOID ,
4263+ list_make2 (expr ,
4264+ makeJsonValueTypeConst (pred -> vtype )),
4265+ InvalidOid , InvalidOid , COERCE_EXPLICIT_CALL );
4266+
4267+ fexpr -> location = pred -> location ;
4268+ }
4269+ else
4270+ {
4271+ ereport (ERROR ,
4272+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
4273+ errmsg ("cannot use type %s in IS JSON predicate" ,
4274+ format_type_be (exprtype ))));
4275+ return NULL ;
4276+ }
4277+
4278+ opts = makeNode (JsonIsPredicateOpts );
4279+ opts -> unique_keys = pred -> unique_keys ;
4280+ opts -> value_type = pred -> vtype ;
4281+
4282+ fexpr -> funcformat2 = FUNCFMT_IS_JSON ;
4283+ fexpr -> funcformatopts = (Node * ) opts ;
4284+
4285+ return (Node * ) fexpr ;
4286+ }
0 commit comments