@@ -4,21 +4,21 @@ CREATE TYPE json_schema_validation_result AS (
4
4
);
5
5
6
6
7
- CREATE OR REPLACE FUNCTION json_schema_validation_result_as_bool (json_schema_validation_result) RETURNS bool AS $$
7
+ CREATE OR REPLACE FUNCTION json_schema_validation_result_as_bool (@extschema@. json_schema_validation_result) RETURNS bool AS $$
8
8
SELECT ($1 ).error IS NULL ;
9
9
$$ LANGUAGE SQL IMMUTABLE;
10
10
11
- CREATE OR REPLACE FUNCTION json_schema_validation_result_array_as_bool (json_schema_validation_result[]) RETURNS bool AS $$
12
- SELECT $1 IS NULL OR true = ALL ($1 );
11
+ CREATE OR REPLACE FUNCTION json_schema_validation_result_array_as_bool (@extschema@. json_schema_validation_result[]) RETURNS bool AS $$
12
+ SELECT $1 IS NULL OR true = ALL ($1 ::bool[] );
13
13
$$ LANGUAGE SQL IMMUTABLE;
14
14
15
15
CREATE CAST ( json_schema_validation_result AS bool )
16
16
WITH FUNCTION @
[email protected] _schema_validation_result_as_bool(json_schema_validation_result)
17
- AS IMPLICIT ;
17
+ AS ASSIGNMENT ;
18
18
19
19
CREATE CAST ( json_schema_validation_result[] AS bool )
20
20
WITH FUNCTION @
[email protected] _schema_validation_result_array_as_bool(json_schema_validation_result[])
21
- AS IMPLICIT ;
21
+ AS ASSIGNMENT ;
22
22
23
23
24
24
@@ -93,12 +93,24 @@ CREATE OR REPLACE FUNCTION validate_json_schema(schema jsonb, data jsonb, root_s
93
93
SELECT @
[email protected] _json_schema_validations(schema, data, root_schema, ARRAY []::
text [], string_as_number)::bool;
94
94
$f$ LANGUAGE SQL IMMUTABLE ;
95
95
96
- CREATE OR REPLACE FUNCTION json_schema_check_constraint (schema jsonb, data jsonb, string_as_number bool default true) RETURNS bool AS $$
97
- DECLARE result json_schema_validation_result[];
96
+ CREATE OR REPLACE FUNCTION json_schema_check_constraint (
97
+ schema jsonb,
98
+ data jsonb,
99
+ string_as_number bool default false,
100
+ table_name text default ' ' ,
101
+ column_name text default ' '
102
+ ) RETURNS bool AS $$
103
+ DECLARE
104
+ result json_schema_validation_result[];
98
105
BEGIN
99
106
result :
= @
[email protected] _json_schema_validations(schema, data, schema,
' {}' ::
text [], string_as_number :
= string_as_number);
100
107
IF (NOT result) THEN
101
- RAISE check_violation USING MESSAGE = ' json_schema_validation_failed' , DETAIL = result;
108
+ RAISE check_violation USING
109
+ MESSAGE = ' json_schema_validation_failed' ,
110
+ DETAIL = to_jsonb(result),
111
+ -- HINT = v_value,
112
+ TABLE = table_name,
113
+ COLUMN = column_name;
102
114
END IF;
103
115
RETURN true;
104
116
END;
@@ -109,7 +121,7 @@ $$ LANGUAGE plpgsql IMMUTABLE ;
109
121
CREATE OR REPLACE FUNCTION _validate_json_multiple_schemas (
110
122
schemas_array jsonb, data jsonb, root_schema jsonb, schema_path text [], string_as_number bool,
111
123
OUT validation_booleans bool[],
112
- OUT all_errors json_schema_validation_result[]
124
+ OUT all_errors @extschema@. json_schema_validation_result[]
113
125
) AS $f$
114
126
WITH schema_validations AS (
115
127
SELECT q FROM jsonb_array_elements(schemas_array) sub_schema,
@@ -122,7 +134,7 @@ $f$ LANGUAGE SQL IMMUTABLE ;
122
134
123
135
124
136
CREATE OR REPLACE FUNCTION get_json_schema_validations (schema jsonb, data jsonb, root_schema jsonb, schema_path text [], string_as_number bool)
125
- RETURNS json_schema_validation_result[] AS $f$
137
+ RETURNS @extschema@. json_schema_validation_result[] AS $f$
126
138
DECLARE
127
139
prop text ;
128
140
item jsonb;
@@ -133,7 +145,7 @@ DECLARE
133
145
additionalItems jsonb;
134
146
pattern text ;
135
147
props text [];
136
- result json_schema_validation_result[];
148
+ result @extschema@. json_schema_validation_result[];
137
149
q_result record;
138
150
BEGIN
139
151
IF root_schema IS NULL THEN
@@ -160,7 +172,7 @@ BEGIN
160
172
ELSE
161
173
types = ARRAY[schema- >> ' type' ];
162
174
END IF;
163
- IF (SELECT NOT bool_or(@extschema@._validate_json_schema_type(type, data)) FROM unnest(types) type) THEN
175
+ IF (SELECT NOT bool_or(@extschema@._validate_json_schema_type(type, data, string_as_number )) FROM unnest(types) type) THEN
164
176
RETURN ARRAY [(schema_path, format(' %s is not a valid type: %s' , jsonb_typeof(data), types))];
165
177
END IF;
166
178
END IF;
@@ -179,7 +191,7 @@ BEGIN
179
191
IF schema ? ' required' AND jsonb_typeof(data) = ' object' THEN
180
192
IF NOT ARRAY(SELECT jsonb_object_keys(data)) @>
181
193
ARRAY(SELECT jsonb_array_elements_text(schema- > ' required' )) THEN
182
- RETURN ARRAY [(path , format(' %s is missing required properties: %s' , schema- >> ' type' , ARRAY(
194
+ RETURN ARRAY [(schema_path , format(' %s is missing required properties: %s' , schema- >> ' type' , ARRAY(
183
195
SELECT jsonb_array_elements_text(schema- > ' required' )
184
196
EXCEPT
185
197
SELECT jsonb_object_keys(data)
@@ -215,7 +227,7 @@ BEGIN
215
227
IF prefixItems IS NOT NULL THEN
216
228
SELECT array_agg(q) INTO result
217
229
FROM jsonb_array_elements(prefixItems) WITH ORDINALITY AS t(sub_schema, i),
218
- @
[email protected] _json_schema_validations(sub_schema, data
- > (i::
int - 1 ), root_schema, schema_path
|| i ::
text , string_as_number) q1, unnest(q1) q
230
+ @
[email protected] _json_schema_validations(sub_schema, data
- > (i::
int - 1 ), root_schema, schema_path
|| (i - 1 ) ::
text , string_as_number) q1, unnest(q1) q
219
231
WHERE i <= jsonb_array_length(data);
220
232
IF NOT result THEN
221
233
RETURN result;
@@ -225,14 +237,14 @@ BEGIN
225
237
226
238
IF jsonb_typeof(additionalItems) = ' boolean' and NOT (additionalItems)::text ::boolean THEN
227
239
IF jsonb_array_length(data) > COALESCE(jsonb_array_length(prefixItems), 0 ) THEN
228
- RETURN ARRAY [(path , format(' field only accepts %s items' , COALESCE(jsonb_array_length(prefixItems), 0 )))];
240
+ RETURN ARRAY [(schema_path , format(' field only accepts %s items' , COALESCE(jsonb_array_length(prefixItems), 0 )))];
229
241
END IF;
230
242
END IF;
231
243
232
244
IF jsonb_typeof(additionalItems) = ' object' THEN
233
245
SELECT array_agg(q) INTO result
234
246
FROM jsonb_array_elements(data) WITH ORDINALITY AS t(elem, i),
235
- @
[email protected] _json_schema_validations(additionalItems, elem, root_schema, schema_path
|| i ::
text , string_as_number)
AS q1, unnest(q1) q
247
+ @
[email protected] _json_schema_validations(additionalItems, elem, root_schema, schema_path
|| (i - 1 ) ::
text , string_as_number)
AS q1, unnest(q1) q
236
248
WHERE i > coalesce(jsonb_array_length(prefixItems), 0 ) AND NOT q LIMIT 1 ;
237
249
238
250
IF NOT result THEN
@@ -244,59 +256,59 @@ BEGIN
244
256
245
257
IF schema ? ' minimum' AND jsonb_typeof(data) = ' number' THEN
246
258
IF data::text ::numeric < (schema- >> ' minimum' )::numeric THEN
247
- RETURN ARRAY [(path , format(' value must be >= %s' , (schema- >> ' minimum' )))];
259
+ RETURN ARRAY [(schema_path , format(' value must be >= %s' , (schema- >> ' minimum' )))];
248
260
END IF;
249
261
END IF;
250
262
251
263
IF schema ? ' maximum' AND jsonb_typeof(data) = ' number' THEN
252
264
IF data::text ::numeric > (schema- >> ' maximum' )::numeric THEN
253
- RETURN ARRAY [(path , format(' value must be <= %s' , (schema- >> ' maximum' )))];
265
+ RETURN ARRAY [(schema_path , format(' value must be <= %s' , (schema- >> ' maximum' )))];
254
266
END IF;
255
267
END IF;
256
268
257
269
IF schema ? ' exclusiveMinimum' AND jsonb_typeof(data) = ' number' THEN
258
270
IF jsonb_typeof(schema- > ' exclusiveMinimum' ) = ' number' THEN
259
271
IF data::text ::numeric <= (schema- >> ' exclusiveMinimum' )::numeric THEN
260
- RETURN ARRAY [(path , format(' value must be > %s' , (schema- >> ' exclusiveMinimum' )))];
272
+ RETURN ARRAY [(schema_path , format(' value must be > %s' , (schema- >> ' exclusiveMinimum' )))];
261
273
END IF;
262
274
ELSEIF COALESCE((schema- > ' exclusiveMinimum' )::text ::bool, FALSE) THEN
263
275
IF data::text ::numeric = (schema- >> ' minimum' )::numeric THEN
264
- RETURN ARRAY [(path , format(' value must be > %s' , (schema- >> ' minimum' )))];
276
+ RETURN ARRAY [(schema_path , format(' value must be > %s' , (schema- >> ' minimum' )))];
265
277
END IF;
266
278
END IF;
267
279
END IF;
268
280
269
281
IF schema ? ' exclusiveMaximum' AND jsonb_typeof(data) = ' number' THEN
270
282
IF jsonb_typeof(schema- > ' exclusiveMaximum' ) = ' number' THEN
271
283
IF data::text ::numeric >= (schema- >> ' exclusiveMaximum' )::numeric THEN
272
- RETURN ARRAY [(path , format(' value must be < %s' , (schema- >> ' exclusiveMinimum' )))];
284
+ RETURN ARRAY [(schema_path , format(' value must be < %s' , (schema- >> ' exclusiveMinimum' )))];
273
285
END IF;
274
286
ELSEIF COALESCE((schema- > ' exclusiveMaximum' )::text ::bool, FALSE) THEN
275
287
IF data::text ::numeric = (schema- >> ' maximum' )::numeric THEN
276
- RETURN ARRAY [(path , format(' value must be < %s' , (schema- >> ' maximum' )))];
288
+ RETURN ARRAY [(schema_path , format(' value must be < %s' , (schema- >> ' maximum' )))];
277
289
END IF;
278
290
END IF;
279
291
END IF;
280
292
281
293
IF schema ? ' anyOf' THEN
282
294
q_result := @extschema@._validate_json_multiple_schemas(schema- > ' anyOf' , data, root_schema, schema_path, string_as_number);
283
295
IF NOT (SELECT true = any (q_result .validation_booleans )) THEN
284
- RETURN q_result .all_errors || (schema_path, ' does not match any of the required schemas' )::json_schema_validation_result;
296
+ RETURN q_result .all_errors || (schema_path, ' does not match any of the required schemas' )::@extschema@. json_schema_validation_result;
285
297
END IF;
286
298
END IF;
287
299
288
300
IF schema ? ' allOf' THEN
289
301
q_result := @extschema@._validate_json_multiple_schemas(schema- > ' allOf' , data, root_schema, schema_path, string_as_number);
290
302
IF NOT (SELECT true = all(q_result .validation_booleans )) THEN
291
- RETURN q_result .all_errors || (schema_path, ' does not match all of the required schemas' )::json_schema_validation_result;
303
+ RETURN q_result .all_errors || (schema_path, ' does not match all of the required schemas' )::@extschema@. json_schema_validation_result;
292
304
END IF;
293
305
END IF;
294
306
295
307
IF schema ? ' oneOf' THEN
296
308
q_result := @extschema@._validate_json_multiple_schemas(schema- > ' oneOf' , data, root_schema, schema_path, string_as_number);
297
309
SELECT count (a::bool) INTO idx FROM unnest(q_result .validation_booleans ) a WHERE a = true;
298
310
IF (idx != 1 ) THEN
299
- RETURN ARRAY [(schema_path, format(' should match exactly one of the schemas, but matches %s' , idx))::json_schema_validation_result];
311
+ RETURN ARRAY [(schema_path, format(' should match exactly one of the schemas, but matches %s' , idx))::@extschema@. json_schema_validation_result];
300
312
END IF;
301
313
END IF;
302
314
@@ -319,7 +331,7 @@ BEGIN
319
331
END IF;
320
332
ELSE
321
333
SELECT array_agg(q) INTO result
FROM unnest(props) key, @
[email protected] _json_schema_validations(schema
- > ' additionalProperties' , data
- > key, root_schema, schema_path
|| key, string_as_number) q1, unnest(q1) q;
322
- IF NOT (true = all(result)) THEN
334
+ IF NOT (true = all(result::bool[] )) THEN
323
335
RETURN result;
324
336
END IF;
325
337
END IF;
@@ -338,7 +350,7 @@ BEGIN
338
350
END IF;
339
351
340
352
result :
= @
[email protected] _json_schema_validations(root_schema
# > path, data, root_schema, schema_path, string_as_number);
341
- IF NOT (true = all(result)) THEN
353
+ IF NOT (true = all(result::bool[] )) THEN
342
354
RETURN result;
343
355
END IF;
344
356
END IF;
@@ -402,14 +414,14 @@ BEGIN
402
414
IF schema ? ' maxItems' AND jsonb_typeof(data) = ' array' THEN
403
415
SELECT count (* ) INTO idx FROM jsonb_array_elements(data);
404
416
IF idx > (schema- >> ' maxItems' )::numeric THEN
405
- RETURN ARRAY [(schema_path, format(' field items count %s exceeds maxItems of %s' , idx, schema- > ' maxItems' ))];
417
+ RETURN ARRAY [(schema_path, format(' items count of %s exceeds maxItems of %s' , idx, schema- > ' maxItems' ))];
406
418
END IF;
407
419
END IF;
408
420
409
421
IF schema ? ' minItems' AND jsonb_typeof(data) = ' array' THEN
410
422
SELECT count (* ) INTO idx FROM jsonb_array_elements(data);
411
423
IF idx < (schema- >> ' minItems' )::numeric THEN
412
- RETURN ARRAY [(schema_path, format(' field items count %s is less than minItems of %s' , idx, schema- > ' minItems' ))];
424
+ RETURN ARRAY [(schema_path, format(' items count of %s is less than minItems of %s' , idx, schema- > ' minItems' ))];
413
425
END IF;
414
426
END IF;
415
427
@@ -477,7 +489,7 @@ BEGIN
477
489
END IF;
478
490
END IF;
479
491
480
- RETURN ' {}' ::json_schema_validation_result[];
492
+ RETURN ' {}' ::@extschema@. json_schema_validation_result[];
481
493
END;
482
494
$f$ LANGUAGE ' plpgsql' VOLATILE ;
483
495
@@ -691,7 +703,7 @@ CREATE OR REPLACE FUNCTION json_schema_resolve_ids_to_paths (
691
703
ELSEIF jsonb_typeof(schema) = ' array' THEN
692
704
RETURN QUERY SELECT q.*
693
705
FROM jsonb_array_elements(schema) WITH ORDINALITY t(elem, idx),
694
- @
[email protected] _schema_resolve_ids_to_paths(elem,
path || (idx
- 1 )::
text , base_uri, base_path) q;
706
+ @
[email protected] _schema_resolve_ids_to_paths(elem,
path || (idx
- 1 )::
text , base_uri, base_path) q;
695
707
696
708
END IF;
697
709
resolved_path := path ;
0 commit comments