@@ -33,39 +33,90 @@ DO $$
3333 END
3434$$;
3535
36+
37+
38+ --
39+ -- Extracts index keys/names from configuration json
40+ --
41+ -- Used by the _cs_config_check_indexes as part of the cs_configuration_data_v1_check constraint
42+ --
43+ DROP FUNCTION IF EXISTS _cs_extract_indexes(jsonb);
44+ CREATE FUNCTION _cs_extract_indexes (val jsonb)
45+ RETURNS SETOF text
46+ LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
47+ BEGIN ATOMIC
48+ SELECT jsonb_object_keys(jsonb_path_query(val,' $.tables.*.*.indexes' ));
49+ END;
50+
3651--
3752-- _cs_check_config_indexes returns true if the table configuration only includes valid index types
3853--
3954-- Used by the cs_configuration_data_v1_check constraint
4055--
41- -- Function types cannot be changed after creation so we always DROP & CREATE for flexibility
42- --
4356DROP FUNCTION IF EXISTS _cs_config_check_indexes(jsonb);
44-
4557CREATE FUNCTION _cs_config_check_indexes (val jsonb)
4658 RETURNS BOOLEAN
47- LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
48- BEGIN ATOMIC
49- SELECT jsonb_object_keys(jsonb_path_query(val, ' $.tables.*.*.indexes' )) = ANY(' {match, ore, unique, ste_vec}' );
50- END;
59+ AS $$
60+ BEGIN
61+ IF (SELECT EXISTS (SELECT _cs_extract_indexes(val))) THEN
62+ IF (SELECT bool_and(index = ANY(' {match, ore, unique, ste_vec}' )) FROM _cs_extract_indexes(val) AS index) THEN
63+ RETURN true;
64+ END IF;
65+ RAISE ' Configuration has an invalid index (%). Index should be one of {match, ore, unique, ste_vec}' , val;
66+ END IF;
67+ RETURN true;
68+ END;
69+ $$ LANGUAGE plpgsql;
5170
5271
5372DROP FUNCTION IF EXISTS _cs_config_check_cast(jsonb);
5473
5574CREATE FUNCTION _cs_config_check_cast (val jsonb)
5675 RETURNS BOOLEAN
57- LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
58- BEGIN ATOMIC
59- SELECT jsonb_array_elements_text(jsonb_path_query_array(val, ' $.tables.*.*.cast_as' )) = ANY(' {text, int, small_int, big_int, real, double, boolean, date, jsonb}' );
60- END;
76+ AS $$
77+ BEGIN
78+ IF EXISTS (SELECT jsonb_array_elements_text(jsonb_path_query_array(val, ' $.tables.*.*.cast_as' )) = ANY(' {text, int, small_int, big_int, real, double, boolean, date, jsonb}' )) THEN
79+ RETURN true;
80+ END IF;
81+ RAISE ' Configuration has an invalid cast_as (%). Cast should be one of {text, int, small_int, big_int, real, double, boolean, date, jsonb}' , val;
82+ END;
83+ $$ LANGUAGE plpgsql;
84+
85+ --
86+ -- Should include a tables field
87+ -- Tables should not be empty
88+ DROP FUNCTION IF EXISTS _cs_config_check_tables(jsonb);
89+ CREATE FUNCTION _cs_config_check_tables (val jsonb)
90+ RETURNS boolean
91+ AS $$
92+ BEGIN
93+ IF (val ? ' tables' ) AND (val- > ' tables' <> ' {}' ::jsonb) THEN
94+ RETURN true;
95+ END IF;
96+ RAISE ' Configuration missing tables (tables) field: %' , val;
97+ END;
98+ $$ LANGUAGE plpgsql;
99+
100+ -- Should include a version field
101+ DROP FUNCTION IF EXISTS _cs_config_check_v(jsonb);
102+ CREATE FUNCTION _cs_config_check_v (val jsonb)
103+ RETURNS boolean
104+ AS $$
105+ BEGIN
106+ IF (val ? ' v' ) THEN
107+ RETURN true;
108+ END IF;
109+ RAISE ' Configuration missing version (v) field: %' , val;
110+ END;
111+ $$ LANGUAGE plpgsql;
61112
62113
63114ALTER DOMAIN cs_configuration_data_v1 DROP CONSTRAINT IF EXISTS cs_configuration_data_v1_check;
64115
65116ALTER DOMAIN cs_configuration_data_v1
66117 ADD CONSTRAINT cs_configuration_data_v1_check CHECK (
67- VALUE ?& array[ ' v ' , ' tables ' ] AND
68- VALUE- > ' tables ' <> ' {} ' ::jsonb AND
118+ _cs_config_check_v( VALUE) AND
119+ _cs_config_check_tables( VALUE) AND
69120 _cs_config_check_cast(VALUE) AND
70121 _cs_config_check_indexes(VALUE)
71122);
0 commit comments