Skip to main content
Glama
U0004__standard_model.sql53.8 kB
CREATE TABLE standard_models ( pk ident primary key default ident_create_v1(), table_name text NOT NULL, table_type text NOT NULL, history_event_label_base text NOT NULL, history_event_message_name text NOT NULL ); ALTER TABLE standard_models ADD CONSTRAINT standard_models_check_valid_table_type CHECK (table_type IN ('model', 'belongs_to', 'many_to_many')); CREATE OR REPLACE FUNCTION get_by_pk_v1(this_table_text text, this_pk ident, OUT object json) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; EXECUTE format('SELECT row_to_json(%1$I.*) AS object FROM %1$I WHERE %1$I.pk = %2$L', this_table, this_pk) INTO object; END ; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION get_by_id_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb, this_id ident) RETURNS TABLE ( id ident, visibility_change_set_pk ident, visibility_deleted_at timestamp with time zone, object json ) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; RETURN QUERY EXECUTE format('SELECT ' ' table_alias.id, ' ' table_alias.visibility_change_set_pk, ' ' table_alias.visibility_deleted_at, ' ' row_to_json(table_alias.*) AS object ' ' FROM %1$I_v1(%3$L, %4$L) AS table_alias ' ' WHERE table_alias.id = %2$L ' ' ORDER BY id, visibility_change_set_pk DESC, visibility_deleted_at DESC NULLS FIRST ' , this_table, this_id, this_tenancy, this_visibility); END ; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION find_by_attr_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb, this_attr_name text, this_value text) RETURNS TABLE ( id ident, visibility_change_set_pk ident, object json ) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; RETURN QUERY EXECUTE format('SELECT ' ' table_alias.id, ' ' table_alias.visibility_change_set_pk, ' ' row_to_json(table_alias.*) AS object ' ' FROM %1$I_v1(%2$L, %3$L) AS table_alias ' ' WHERE table_alias.%4$I = %5$L ' ' ORDER BY id, visibility_change_set_pk DESC ' , this_table, this_tenancy, this_visibility, this_attr_name, this_value); END ; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION find_by_attr_null_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb, this_attr_name text) RETURNS TABLE ( id ident, visibility_change_set_pk ident, object json ) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; RETURN QUERY EXECUTE format('SELECT ' ' table_alias.id, ' ' table_alias.visibility_change_set_pk, ' ' row_to_json(table_alias.*) AS object ' ' FROM %1$I_v1(%2$L, %3$L) AS table_alias ' ' WHERE table_alias.%4$I IS NULL ' ' ORDER BY id, visibility_change_set_pk DESC ' , this_table, this_tenancy, this_visibility, this_attr_name); END ; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION find_by_attr_in_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb, this_attr_name text, this_value text[]) RETURNS TABLE ( id ident, visibility_change_set_pk ident, object json ) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; RETURN QUERY EXECUTE format('SELECT ' ' table_alias.id, ' ' table_alias.visibility_change_set_pk, ' ' row_to_json(table_alias.*) AS object ' ' FROM %1$I_v1(%2$L, %3$L) AS table_alias ' ' WHERE table_alias.%4$I = ANY (%5$L) ' ' ORDER BY id, visibility_change_set_pk DESC ' , this_table, this_tenancy, this_visibility, this_attr_name, this_value); END ; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION find_by_attr_not_in_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb, this_attr_name text, this_value text[]) RETURNS TABLE ( id ident, visibility_change_set_pk ident, object json ) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; RETURN QUERY EXECUTE format('SELECT ' ' table_alias.id, ' ' table_alias.visibility_change_set_pk, ' ' row_to_json(table_alias.*) AS object ' ' FROM %1$I_v1(%2$L, %3$L) AS table_alias ' ' WHERE NOT table_alias.%4$I = ANY (%5$L) ' ' ORDER BY id, visibility_change_set_pk DESC ' , this_table, this_tenancy, this_visibility, this_attr_name, this_value); END ; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION update_by_id_v1( this_table text, this_column text, this_tenancy jsonb, this_visibility jsonb, this_id ident, this_value text, OUT updated_at timestamp with time zone) AS $$ DECLARE this_visibility_row visibility_record_v1; this_tenancy_record tenancy_record_v1; copy_change_set_column_names text; debugging_record_info record; BEGIN this_visibility_row = visibility_json_to_columns_v1(this_visibility); this_tenancy_record = tenancy_json_to_columns_v1(this_tenancy); /* First, try the update - if it works, we're all set. */ EXECUTE format('UPDATE %1$I SET %2$I = %6$L, updated_at = clock_timestamp() WHERE id = %5$L ' ' AND in_tenancy_v1(%3$L, %1$I.tenancy_workspace_pk) ' ' AND %1$I.visibility_change_set_pk = %4$L::ident ' ' AND CASE WHEN %7$L IS NULL THEN %1$I.visibility_deleted_at IS NULL ELSE TRUE END ' ' RETURNING updated_at', this_table, this_column, this_tenancy, this_visibility_row.visibility_change_set_pk, this_id, this_value, this_visibility_row.visibility_deleted_at) INTO updated_at; /* If updated_at is still null, that is because the update found no rows. We need to first copy the last known good data, and then update it. */ IF updated_at IS NULL THEN /* Check if we are doing an update to the change-set visibility. If we aren't, then we need to copy the head row. If it doesn't exist, that is an error. */ IF this_visibility_row.visibility_change_set_pk != ident_nil_v1() THEN SELECT string_agg(information_schema.columns.column_name::text, ',') FROM information_schema.columns WHERE information_schema.columns.table_name = this_table AND information_schema.columns.column_name NOT IN ( this_column, 'visibility_change_set_pk', 'pk', 'created_at', 'updated_at', 'tenancy_workspace_pk' ) AND information_schema.columns.is_generated = 'NEVER' INTO copy_change_set_column_names; EXECUTE format('INSERT INTO %1$I (%2$s, visibility_change_set_pk, tenancy_workspace_pk, %3$s) ' ' SELECT %4$L, %5$L, %8$L, %3$s ' ' FROM %1$I ' ' WHERE %1$I.id = %6$L ' ' AND in_tenancy_v1(%7$L, %1$I.tenancy_workspace_pk) ' ' AND %1$I.visibility_change_set_pk = ident_nil_v1() ' ' AND CASE WHEN %9$L IS NULL THEN %1$I.visibility_deleted_at IS NULL ELSE %1$I.visibility_deleted_at IS NOT NULL END ' ' ON CONFLICT (id, tenancy_workspace_pk, visibility_change_set_pk) DO UPDATE SET updated_at = CLOCK_TIMESTAMP() ' ' RETURNING updated_at', this_table, this_column, copy_change_set_column_names, this_value, this_visibility_row.visibility_change_set_pk, this_id, this_tenancy, this_tenancy_record.tenancy_workspace_pk, this_visibility_row.visibility_deleted_at) INTO updated_at; END IF; -- If updated_at is still null, then there is a provided tenancy -- that is not suitable--this could be an application bug! IF updated_at IS NULL THEN EXECUTE format('SELECT * FROM %1$I WHERE id = %2$L', this_table, this_id) INTO debugging_record_info; RAISE EXCEPTION 'update_by_id_v1: cannot update column % on table % of record % to value % (likely a tenancy issue). Tenancy(%), Visibility(%), %(%)', this_column, this_table, this_id, this_value, this_tenancy, this_visibility, this_table, debugging_record_info; END IF; END IF; END ; $$ LANGUAGE PLPGSQL VOLATILE; -- update_by_id_v1 (jsonb) CREATE OR REPLACE FUNCTION update_by_id_v1(this_table_text text, this_column text, this_tenancy jsonb, this_visibility jsonb, this_id ident, this_value jsonb, OUT updated_at timestamp with time zone) AS $$ BEGIN SELECT update_by_id_v1(this_table_text, this_column, this_tenancy, this_visibility, this_id, CAST(this_value as text)) INTO updated_at; END ; $$ LANGUAGE PLPGSQL VOLATILE; -- update_by_id_v1 (bool) CREATE OR REPLACE FUNCTION update_by_id_v1(this_table_text text, this_column text, this_tenancy jsonb, this_visibility jsonb, this_id ident, this_value bool, OUT updated_at timestamp with time zone) AS $$ BEGIN SELECT update_by_id_v1(this_table_text, this_column, this_tenancy, this_visibility, this_id, CAST(this_value as text)) INTO updated_at; END ; $$ LANGUAGE PLPGSQL VOLATILE; -- update_by_id_v1 (bigint) CREATE OR REPLACE FUNCTION update_by_id_v1(this_table_text text, this_column text, this_tenancy jsonb, this_visibility jsonb, this_id ident, this_value bigint, OUT updated_at timestamp with time zone) AS $$ BEGIN SELECT update_by_id_v1(this_table_text, this_column, this_tenancy, this_visibility, this_id, CAST(this_value as text)) INTO updated_at; END ; $$ LANGUAGE PLPGSQL VOLATILE; -- update_by_id_v1 (timestamp with time zone) CREATE OR REPLACE FUNCTION update_by_id_v1(this_table_text text, this_column text, this_tenancy jsonb, this_visibility jsonb, this_id ident, this_value timestamp with time zone, OUT updated_at timestamp with time zone) AS $$ BEGIN SELECT update_by_id_v1(this_table_text, this_column, this_tenancy, this_visibility, this_id, CAST(this_value as text)) INTO updated_at; END ; $$ LANGUAGE PLPGSQL VOLATILE; CREATE OR REPLACE FUNCTION delete_by_id_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb, this_id ident, OUT updated_at timestamp with time zone) AS $$ BEGIN SELECT update_by_id_v1(this_table_text, 'visibility_deleted_at', this_tenancy, this_visibility, this_id, CAST(clock_timestamp() as text)) INTO updated_at; END ; $$ LANGUAGE PLPGSQL VOLATILE; CREATE OR REPLACE FUNCTION delete_by_pk_v1(this_table_text text, this_tenancy jsonb, this_pk ident, OUT updated_at timestamp with time zone) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; EXECUTE format('UPDATE %1$I SET visibility_deleted_at = clock_timestamp(), updated_at = clock_timestamp() ' 'WHERE pk = %3$L ' ' AND in_tenancy_v1(%2$L, %1$I.tenancy_workspace_pk) ' ' RETURNING updated_at', this_table, this_tenancy, this_pk) INTO updated_at; END; $$ LANGUAGE PLPGSQL VOLATILE; CREATE OR REPLACE FUNCTION undelete_by_pk_v1(this_table_text text, this_tenancy jsonb, this_pk ident, OUT updated_at timestamp with time zone) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; EXECUTE format('UPDATE %1$I SET visibility_deleted_at = NULL, updated_at = clock_timestamp() ' 'WHERE pk = %3$L ' ' AND in_tenancy_v1(%2$L, %1$I.tenancy_workspace_pk) ' ' RETURNING updated_at', this_table, this_tenancy, this_pk) INTO updated_at; END; $$ LANGUAGE PLPGSQL VOLATILE; CREATE OR REPLACE FUNCTION hard_delete_by_pk_v1( this_table_text text, this_pk ident, OUT object json ) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; EXECUTE format( 'DELETE FROM %1$I WHERE %1$I.pk = %2$L RETURNING row_to_json(%1$I);', this_table, this_pk ) INTO object; END; $$ LANGUAGE PLPGSQL; CREATE OR REPLACE FUNCTION list_models_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb) RETURNS TABLE ( id ident, visibility_change_set_pk ident, visibility_deleted_at timestamp with time zone, object json ) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; RETURN QUERY EXECUTE format('SELECT ' ' table_alias.id, ' ' table_alias.visibility_change_set_pk, ' ' table_alias.visibility_deleted_at, ' ' row_to_json(table_alias.*) AS object ' ' FROM %1$I_v1(%2$L, %3$L) AS table_alias ' , this_table, this_tenancy, this_visibility); END ; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION belongs_to_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb, this_retrieve_table text, this_object_id ident) RETURNS TABLE ( id ident, visibility_change_set_pk ident, visibility_deleted_at timestamp with time zone, object json ) AS $$ DECLARE this_table regclass; BEGIN this_table := this_table_text::regclass; RETURN QUERY EXECUTE format('SELECT ' ' table_alias.id, ' ' table_alias.visibility_change_set_pk, ' ' table_alias.visibility_deleted_at, ' ' row_to_json(retrieve_table_alias.*) AS object ' ' FROM %1$I_v1(%2$L, %3$L) AS table_alias ' ' INNER JOIN %5$I_v1(%2$L, %3$L) AS retrieve_table_alias ' ' ON retrieve_table_alias.id = table_alias.belongs_to_id ' ' WHERE table_alias.object_id = %4$L ' ' ORDER BY retrieve_table_alias.id, ' ' retrieve_table_alias.visibility_change_set_pk DESC, ' ' retrieve_table_alias.visibility_deleted_at DESC NULLS FIRST ' ' LIMIT 1 ' , this_table, this_tenancy, this_visibility, this_object_id, this_retrieve_table); END; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION has_many_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb, this_retrieve_table text, this_belongs_to_id ident) RETURNS TABLE ( id ident, visibility_change_set_pk ident, visibility_deleted_at timestamp with time zone, object json ) AS $$ DECLARE this_table regclass; query text; BEGIN this_table := this_table_text::regclass; query := format('SELECT ' ' table_alias.id, ' ' table_alias.visibility_change_set_pk, ' ' table_alias.visibility_deleted_at, ' ' row_to_json(retrieve_table_alias.*) AS object ' ' FROM %1$I_v1(%2$L, %3$L) AS table_alias ' ' INNER JOIN %5$I_v1(%2$L, %3$L) AS retrieve_table_alias ' ' ON retrieve_table_alias.id = table_alias.object_id ' ' WHERE table_alias.belongs_to_id = %4$L ' ' ORDER BY table_alias.id, ' ' table_alias.visibility_change_set_pk DESC, ' ' table_alias.visibility_deleted_at DESC NULLS FIRST ' , this_table, this_tenancy, this_visibility, this_belongs_to_id, this_retrieve_table); RAISE DEBUG 'has_many query: %', query; RETURN QUERY EXECUTE query; END; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION many_to_many_v1(this_table_text text, this_tenancy jsonb, this_visibility jsonb, this_left_table text, this_right_table text, this_left_object_id ident, this_right_object_id ident) RETURNS TABLE ( id ident, visibility_change_set_pk ident, visibility_deleted_at timestamp with time zone, object json ) AS $$ DECLARE this_table regclass; query text; this_return_table text; this_query_object_id ident; this_join_column text; this_query_column text; BEGIN IF this_left_object_id IS NOT NULL THEN this_return_table := this_right_table; this_query_object_id := this_left_object_id; this_join_column := 'right_object_id'; this_query_column := 'left_object_id'; ELSIF this_right_object_id IS NOT NULL THEN this_return_table := this_left_table; this_query_object_id := this_right_object_id; this_join_column := 'left_object_id'; this_query_column := 'right_object_id'; ELSE RAISE EXCEPTION 'cannot retrieve many to many relationship without a left or right object id'; END IF; this_table := this_table_text::regclass; query := format('SELECT ' ' table_alias.id, ' ' table_alias.visibility_change_set_pk, ' ' table_alias.visibility_deleted_at, ' ' row_to_json(return_table_alias.*) AS object ' ' FROM %1$I_v1(%2$L, %3$L) AS table_alias ' ' INNER JOIN %5$I_v1(%2$L, %3$L) AS return_table_alias ' ' ON return_table_alias.id = table_alias.%6$I ' ' WHERE table_alias.%7$I = %4$L ' ' ORDER BY table_alias.id, ' ' table_alias.visibility_change_set_pk DESC, ' ' table_alias.visibility_deleted_at DESC NULLS FIRST ' , this_table, this_tenancy, this_visibility, this_query_object_id, this_return_table, this_join_column, this_query_column); RAISE DEBUG 'many_to_many query: %', query; RETURN QUERY EXECUTE query; END; $$ LANGUAGE PLPGSQL STABLE; CREATE OR REPLACE FUNCTION check_id_in_table_v1(this_table_name text, this_id ident, OUT result bool) AS $$ DECLARE check_query text; BEGIN check_query := format('SELECT true FROM %1$I WHERE id = %2$L', this_table_name, this_id); EXECUTE check_query INTO result; IF result IS NULL THEN result := false; END IF; END; $$ LANGUAGE plpgsql STABLE; CREATE OR REPLACE FUNCTION belongs_to_table_create_v1(this_table_name text, this_object_table text, this_belongs_to_table text) RETURNS VOID AS $$ DECLARE create_table text; BEGIN create_table := format('CREATE TABLE %1$I ( ' ' pk ident primary key default ident_create_v1(), ' ' id ident not null default ident_create_v1(), ' ' object_id ident NOT NULL, ' ' belongs_to_id ident NOT NULL, ' ' tenancy_workspace_pk ident, ' ' visibility_change_set_pk ident NOT NULL DEFAULT ident_nil_v1(), ' ' visibility_deleted_at timestamp with time zone, ' ' created_at timestamp with time zone NOT NULL DEFAULT CLOCK_TIMESTAMP(), ' ' updated_at timestamp with time zone NOT NULL DEFAULT CLOCK_TIMESTAMP() ' '); ' 'CREATE UNIQUE INDEX %1$s_visibility_tenancy ON %1$I (id, ' ' tenancy_workspace_pk, ' ' visibility_change_set_pk); ' 'ALTER TABLE %1$I ' ' ADD CONSTRAINT %1$s_object_id_is_valid ' ' CHECK (check_id_in_table_v1(%2$L, object_id)); ' 'ALTER TABLE %1$I ' ' ADD CONSTRAINT %1$s_belongs_to_id_is_valid ' ' CHECK (check_id_in_table_v1(%3$L, belongs_to_id)); ' 'CREATE UNIQUE INDEX %1$s_single_association ON %1$I (object_id, ' ' tenancy_workspace_pk, ' ' visibility_change_set_pk); ' 'CREATE INDEX ON %1$I (tenancy_workspace_pk); ' 'CREATE INDEX ON %1$I (visibility_change_set_pk); ' 'CREATE INDEX ON %1$I (object_id); ' 'CREATE INDEX ON %1$I (belongs_to_id); ' 'CREATE FUNCTION is_visible_v1( ' ' check_visibility jsonb, ' ' reference %1$I ' ') ' 'RETURNS bool ' 'LANGUAGE sql ' 'IMMUTABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $is_visible_fn$ ' ' SELECT is_visible_v1( ' ' check_visibility, ' ' reference.visibility_change_set_pk, ' ' reference.visibility_deleted_at ' ' ) ' '$is_visible_fn$; ' 'CREATE FUNCTION in_tenancy_v1( ' ' tenancy jsonb, ' ' record_to_check %1$I ' ') ' 'RETURNS bool ' 'LANGUAGE sql ' 'IMMUTABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $in_tenancy_fn$ ' ' SELECT in_tenancy_v1( ' ' tenancy, ' ' record_to_check.tenancy_workspace_pk ' ' ) ' '$in_tenancy_fn$; ' 'CREATE FUNCTION in_tenancy_and_visible_v1( ' ' tenancy jsonb, ' ' check_visibility jsonb, ' ' record_to_check %1$I ' ') ' 'RETURNS bool ' 'LANGUAGE sql ' 'IMMUTABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $in_tenancy_and_visible_fn$ ' ' SELECT ' ' in_tenancy_v1( ' ' tenancy, ' ' record_to_check.tenancy_workspace_pk ' ' ) ' ' AND is_visible_v1( ' ' check_visibility, ' ' record_to_check.visibility_change_set_pk, ' ' record_to_check.visibility_deleted_at ' ' ) ' '$in_tenancy_and_visible_fn$; ' 'CREATE FUNCTION %1$I_v1 ( ' ' this_tenancy jsonb, ' ' this_visibility jsonb ' ') ' 'RETURNS SETOF %1$I ' 'LANGUAGE sql ' 'STABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $table_view_fn$ ' ' SELECT DISTINCT ON (object_id) %1$I.* ' ' FROM %1$I ' ' WHERE in_tenancy_and_visible_v1(this_tenancy, this_visibility, %1$I) ' ' ORDER BY ' ' object_id, ' ' visibility_change_set_pk DESC, ' ' visibility_deleted_at DESC NULLS FIRST ' '$table_view_fn$; ', this_table_name, this_object_table, this_belongs_to_table); RAISE DEBUG 'create_table query: %', create_table; EXECUTE create_table; END; $$ LANGUAGE PLPGSQL VOLATILE; CREATE OR REPLACE FUNCTION standard_model_table_constraints_v1(this_table_name text) RETURNS VOID AS $$ DECLARE alter_query text; BEGIN alter_query := format('CREATE UNIQUE INDEX %1$s_visibility_tenancy ON %1$I (id, ' ' tenancy_workspace_pk, ' ' visibility_change_set_pk); ' 'CREATE INDEX ON %1$I (id); ' 'CREATE INDEX ON %1$I (visibility_deleted_at NULLS FIRST); ' 'CREATE INDEX ON %1$I (tenancy_workspace_pk); ' 'CREATE INDEX ON %1$I (visibility_change_set_pk); ' 'CREATE FUNCTION is_visible_v1( ' ' check_visibility jsonb, ' ' reference %1$I ' ') ' 'RETURNS bool ' 'LANGUAGE sql ' 'IMMUTABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $is_visible_fn$ ' ' SELECT is_visible_v1( ' ' check_visibility, ' ' reference.visibility_change_set_pk, ' ' reference.visibility_deleted_at ' ' ) ' '$is_visible_fn$; ' 'CREATE FUNCTION in_tenancy_v1( ' ' tenancy jsonb, ' ' record_to_check %1$I ' ') ' 'RETURNS bool ' 'LANGUAGE sql ' 'IMMUTABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $in_tenancy_fn$ ' ' SELECT in_tenancy_v1( ' ' tenancy, ' ' record_to_check.tenancy_workspace_pk ' ' ) ' '$in_tenancy_fn$; ' 'CREATE FUNCTION in_tenancy_and_visible_v1( ' ' tenancy jsonb, ' ' check_visibility jsonb, ' ' record_to_check %1$I ' ') ' 'RETURNS bool ' 'LANGUAGE sql ' 'IMMUTABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $in_tenancy_and_visible_fn$ ' ' SELECT ' ' in_tenancy_v1( ' ' tenancy, ' ' record_to_check.tenancy_workspace_pk ' ' ) ' ' AND is_visible_v1( ' ' check_visibility, ' ' record_to_check.visibility_change_set_pk, ' ' record_to_check.visibility_deleted_at ' ' ) ' '$in_tenancy_and_visible_fn$; ' 'CREATE FUNCTION %1$I_v1( ' ' this_tenancy jsonb, ' ' this_visibility jsonb ' ') ' 'RETURNS SETOF %1$I ' 'LANGUAGE SQL ' 'STABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $table_view_fn$ ' 'SELECT DISTINCT ON (table_version.id) ' ' table_version.* ' 'FROM %1$I AS table_version ' 'LEFT JOIN %1$I AS change_set_version ' ' ON table_version.id = change_set_version.id ' ' AND (this_visibility ->> ''visibility_change_set_pk'')::ident != ident_nil_v1() ' ' AND change_set_version.visibility_change_set_pk = (this_visibility ->> ''visibility_change_set_pk'')::ident ' ' AND table_version.visibility_change_set_pk = ident_nil_v1() ' ' AND change_set_version.visibility_deleted_at IS NOT NULL ' 'WHERE ' ' in_tenancy_and_visible_v1(this_tenancy, this_visibility, table_version) ' ' AND change_set_version.id IS NULL ' 'ORDER BY table_version.id, table_version.visibility_change_set_pk DESC, visibility_deleted_at DESC NULLS FIRST ' '$table_view_fn$; ', this_table_name ); RAISE DEBUG 'alter table query: %', alter_query; EXECUTE alter_query; END; $$ LANGUAGE plpgsql VOLATILE; CREATE OR REPLACE FUNCTION many_to_many_table_create_v1(this_table_name text, this_left_object_table text, this_right_object_table text) RETURNS VOID AS $$ DECLARE create_table text; BEGIN create_table := format('CREATE TABLE %1$I ( ' ' pk ident primary key default ident_create_v1(), ' ' id ident not null default ident_create_v1(), ' ' left_object_id ident NOT NULL, ' ' right_object_id ident NOT NULL, ' ' tenancy_workspace_pk ident, ' ' visibility_change_set_pk ident NOT NULL DEFAULT ident_nil_v1(), ' ' visibility_deleted_at timestamp with time zone, ' ' created_at timestamp with time zone NOT NULL DEFAULT CLOCK_TIMESTAMP(), ' ' updated_at timestamp with time zone NOT NULL DEFAULT CLOCK_TIMESTAMP() ' '); ' 'CREATE UNIQUE INDEX %1$s_visibility_tenancy ON %1$I (id, ' ' tenancy_workspace_pk, ' ' visibility_change_set_pk); ' 'ALTER TABLE %1$I ' ' ADD CONSTRAINT %1$s_left_object_id_is_valid ' ' CHECK (check_id_in_table_v1(%2$L, left_object_id)); ' 'ALTER TABLE %1$I ' ' ADD CONSTRAINT %1$s_right_object_id_is_valid ' ' CHECK (check_id_in_table_v1(%3$L, right_object_id)); ' 'CREATE UNIQUE INDEX %1$s_no_duplicate_associations ON %1$I (left_object_id, ' ' right_object_id, ' ' tenancy_workspace_pk, ' ' visibility_change_set_pk) ' ' WHERE visibility_deleted_at IS NULL; ' 'CREATE INDEX ON %1$I (left_object_id); ' 'CREATE INDEX ON %1$I (right_object_id); ' 'CREATE FUNCTION is_visible_v1( ' ' check_visibility jsonb, ' ' reference %1$I ' ') ' 'RETURNS bool ' 'LANGUAGE sql ' 'IMMUTABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $is_visible_fn$ ' ' SELECT is_visible_v1( ' ' check_visibility, ' ' reference.visibility_change_set_pk, ' ' reference.visibility_deleted_at ' ' ) ' '$is_visible_fn$; ' 'CREATE FUNCTION in_tenancy_v1( ' ' tenancy jsonb, ' ' record_to_check %1$I ' ') ' 'RETURNS bool ' 'LANGUAGE sql ' 'IMMUTABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $in_tenancy_fn$ ' ' SELECT in_tenancy_v1( ' ' tenancy, ' ' record_to_check.tenancy_workspace_pk ' ' ) ' '$in_tenancy_fn$; ' 'CREATE FUNCTION in_tenancy_and_visible_v1( ' ' tenancy jsonb, ' ' check_visibility jsonb, ' ' record_to_check %1$I ' ') ' 'RETURNS bool ' 'LANGUAGE sql ' 'IMMUTABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $in_tenancy_and_visible_fn$ ' ' SELECT ' ' in_tenancy_v1( ' ' tenancy, ' ' record_to_check.tenancy_workspace_pk ' ' ) ' ' AND is_visible_v1( ' ' check_visibility, ' ' record_to_check.visibility_change_set_pk, ' ' record_to_check.visibility_deleted_at ' ' ) ' '$in_tenancy_and_visible_fn$; ' 'CREATE FUNCTION %1$I_v1 ( ' ' this_tenancy jsonb, ' ' this_visibility jsonb ' ') ' 'RETURNS SETOF %1$I ' 'LANGUAGE sql ' 'STABLE PARALLEL SAFE CALLED ON NULL INPUT ' 'AS $table_view_fn$ ' ' SELECT DISTINCT ON (id) %1$I.* ' ' FROM %1$I ' ' WHERE in_tenancy_and_visible_v1(this_tenancy, this_visibility, %1$I) ' ' ORDER BY id, visibility_change_set_pk DESC, visibility_deleted_at DESC NULLS FIRST ' '$table_view_fn$;', this_table_name, this_left_object_table, this_right_object_table); RAISE DEBUG 'create_table query: %', create_table; EXECUTE create_table; END; $$ LANGUAGE PLPGSQL VOLATILE; CREATE OR REPLACE FUNCTION associate_many_to_many_v1(this_table_name text, this_tenancy jsonb, this_visibility jsonb, this_left_object_id ident, this_right_object_id ident ) RETURNS VOID AS $$ DECLARE insert_query text; this_tenancy_record tenancy_record_v1; this_visibility_record visibility_record_v1; BEGIN this_tenancy_record := tenancy_json_to_columns_v1(this_tenancy); this_visibility_record := visibility_json_to_columns_v1(this_visibility); insert_query := format('INSERT INTO %1$I (left_object_id, right_object_id, ' ' tenancy_workspace_pk, visibility_change_set_pk, ' ' visibility_deleted_at) ' 'VALUES (%2$L, ' ' %3$L, ' ' %4$L, ' ' %5$L, ' ' %6$L) ', this_table_name, this_left_object_id, this_right_object_id, this_tenancy_record.tenancy_workspace_pk, this_visibility_record.visibility_change_set_pk, this_visibility_record.visibility_deleted_at ); RAISE DEBUG 'associate many to many: %', insert_query; EXECUTE insert_query; END; $$ LANGUAGE plpgsql VOLATILE; CREATE OR REPLACE FUNCTION disassociate_many_to_many_v1(this_table_name text, this_tenancy jsonb, this_visibility jsonb, this_left_object_id ident, this_right_object_id ident ) RETURNS VOID AS $$ DECLARE this_existing_record_id ident; find_query text; BEGIN find_query := format('SELECT id FROM %1$I_v1(%2$L, %3$L) ' ' WHERE left_object_id = %4$L ' ' AND right_object_id = %5$L ', this_table_name, this_tenancy, this_visibility, this_left_object_id, this_right_object_id ); RAISE DEBUG 'disassociate many to many: %', find_query; EXECUTE find_query INTO this_existing_record_id; IF this_existing_record_id IS NOT NULL THEN -- Since there is an existing relation record for the object we're interested in, -- we need to update that record, rather than create a new relation record. PERFORM update_by_id_v1( this_table_name, 'visibility_deleted_at', this_tenancy, this_visibility, this_existing_record_id, CAST(clock_timestamp() as text) ); RETURN; END IF; END; $$ LANGUAGE plpgsql VOLATILE; CREATE OR REPLACE FUNCTION disassociate_all_many_to_many_v1(this_table_name text, this_tenancy jsonb, this_visibility jsonb, this_left_object_id ident ) RETURNS VOID AS $$ DECLARE this_existing_record_id ident; BEGIN SELECT id INTO this_existing_record_id FROM find_by_attr_v1( this_table_name, this_tenancy, this_visibility, 'left_object_id', this_left_object_id::text ); IF this_existing_record_id IS NOT NULL THEN -- Since there is an existing relation record for the object we're interested in, -- we need to update that record, rather than create a new relation record. PERFORM update_by_id_v1( this_table_name, 'visibility_deleted_at', this_tenancy, this_visibility, this_existing_record_id, CAST(clock_timestamp() as text) ); RETURN; END IF; END; $$ LANGUAGE plpgsql VOLATILE; CREATE OR REPLACE FUNCTION set_belongs_to_v1( this_table_name text, this_tenancy jsonb, this_visibility jsonb, this_object_id ident, this_belongs_to_id ident ) RETURNS VOID AS $$ DECLARE insert_query text; this_tenancy_record tenancy_record_v1; this_visibility_record visibility_record_v1; this_existing_record_id ident; BEGIN this_tenancy_record := tenancy_json_to_columns_v1(this_tenancy); this_visibility_record := visibility_json_to_columns_v1(this_visibility); SELECT id INTO this_existing_record_id FROM find_by_attr_v1( this_table_name, this_tenancy, this_visibility, 'object_id', this_object_id::text ); IF this_existing_record_id IS NOT NULL THEN -- Since there is an existing relation record for the object we're interested in, -- we need to update that record, rather than create a new relation record. PERFORM update_by_id_v1( this_table_name, 'belongs_to_id', this_tenancy, this_visibility, this_existing_record_id, this_belongs_to_id ); RETURN; END IF; insert_query := format(' INSERT INTO %1$I (object_id, belongs_to_id, ' ' tenancy_workspace_pk, visibility_change_set_pk, ' ' visibility_deleted_at) ' ' VALUES (%2$L, ' ' %3$L, ' ' %4$L, ' ' %5$L, ' ' %6$L) ', this_table_name, this_object_id, this_belongs_to_id, this_tenancy_record.tenancy_workspace_pk, this_visibility_record.visibility_change_set_pk, this_visibility_record.visibility_deleted_at ); RAISE DEBUG 'set belongs to: %', insert_query; EXECUTE insert_query; END; $$ LANGUAGE plpgsql VOLATILE; CREATE OR REPLACE FUNCTION unset_belongs_to_v1(this_table_name text, this_tenancy jsonb, this_visibility jsonb, this_object_id ident ) RETURNS VOID AS $$ DECLARE this_existing_record_id ident; BEGIN SELECT id INTO this_existing_record_id FROM find_by_attr_v1( this_table_name, this_tenancy, this_visibility, 'object_id', this_object_id::text ); IF this_existing_record_id IS NOT NULL THEN -- Since there is an existing relation record for the object we're interested in, -- we need to update that record, rather than create a new relation record. PERFORM update_by_id_v1( this_table_name, 'visibility_deleted_at', this_tenancy, this_visibility, this_existing_record_id, CAST(clock_timestamp() as text) ); RETURN; END IF; END; $$ LANGUAGE plpgsql VOLATILE; CREATE OR REPLACE FUNCTION hard_unset_belongs_to_in_change_set_v1(this_table_name text, this_tenancy jsonb, this_visibility jsonb, this_object_id ident ) RETURNS VOID AS $$ DECLARE update_query text; visibility_change_set_pk ident; BEGIN SELECT (this_visibility ->> 'visibility_change_set_pk') INTO visibility_change_set_pk; update_query := format('DELETE FROM %1$I ' ' WHERE object_id = %2$L ' ' AND visibility_change_set_pk = %4$L ' ' AND in_tenancy_v1(%3$L, %1$I.tenancy_workspace_pk)', this_table_name, this_object_id, this_tenancy, visibility_change_set_pk ); RAISE DEBUG 'unset belongs to: %', update_query; EXECUTE update_query; END; $$ LANGUAGE plpgsql VOLATILE; CREATE OR REPLACE FUNCTION unset_all_belongs_to_v1(this_table_name text, this_tenancy jsonb, this_visibility jsonb, this_belongs_to_id ident ) RETURNS VOID AS $$ DECLARE this_existing_record_ids ident[]; find_query text; id ident; BEGIN find_query := format('SELECT array_agg(DISTINCT id) FROM %1$I_v1(%2$L, %3$L) ' ' WHERE belongs_to_id = %4$L', this_table_name, this_tenancy, this_visibility, this_belongs_to_id ); RAISE DEBUG 'unset all belongs to: %', find_query; EXECUTE find_query INTO this_existing_record_ids; FOREACH id IN ARRAY coalesce(this_existing_record_ids, '{}') LOOP -- Since there is an existing relation record for the object we're interested in, -- we need to update that record, rather than create a new relation record. PERFORM update_by_id_v1( this_table_name, 'visibility_deleted_at', this_tenancy, this_visibility, id, CAST(clock_timestamp() as text) ); RETURN; END LOOP; END; $$ LANGUAGE plpgsql VOLATILE; CREATE OR REPLACE FUNCTION hard_unset_all_belongs_to_in_change_set_v1(this_table_name text, this_tenancy jsonb, this_visibility jsonb, this_belongs_to_id ident ) RETURNS VOID AS $$ DECLARE update_query text; visibility_change_set_pk ident; BEGIN SELECT (this_visibility ->> 'visibility_change_set_pk') INTO visibility_change_set_pk; update_query := format('DELETE FROM %1$I ' ' WHERE belongs_to_id = %2$L ' ' AND visibility_change_set_pk = %4$L ' ' AND in_tenancy_v1(%3$L, %1$I.tenancy_workspace_pk)', this_table_name, this_belongs_to_id, this_tenancy, visibility_change_set_pk ); RAISE DEBUG 'unset belongs to: %', update_query; EXECUTE update_query; END; $$ LANGUAGE plpgsql VOLATILE; CREATE OR REPLACE FUNCTION import_builtins_v1(destination_tenancy jsonb, source_workspace_pk ident) RETURNS VOID AS $$ DECLARE standard_model standard_models%ROWTYPE; destination_tenancy_record tenancy_record_v1; this_table_name regclass; insert_column_names text; BEGIN destination_tenancy_record = tenancy_json_to_columns_v1(destination_tenancy); FOR standard_model IN SELECT * FROM standard_models LOOP this_table_name := standard_model.table_name::regclass; SELECT string_agg(information_schema.columns.column_name::text, ',') FROM information_schema.columns WHERE information_schema.columns.table_name = standard_model.table_name AND information_schema.columns.column_name NOT IN ('pk', 'created_at', 'tenancy_workspace_pk', 'visibility_change_set_pk') AND information_schema.columns.is_generated = 'NEVER' INTO insert_column_names; -- No history events for this update EXECUTE format('INSERT INTO %1$I (tenancy_workspace_pk, visibility_change_set_pk, %2$s) SELECT %3$L, ident_nil_v1(), %2$s FROM %1$I WHERE in_tenancy_v1(%4$L, %1$I.tenancy_workspace_pk)', this_table_name, insert_column_names, destination_tenancy_record.tenancy_workspace_pk, jsonb_build_object('tenancy_workspace_pk', source_workspace_pk)); END LOOP; END; $$ LANGUAGE PLPGSQL VOLATILE;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server