Skip to content

Commit

Permalink
Merge pull request #85 from jsangmeister/add-identical-motion-ids
Browse files Browse the repository at this point in the history
Add support for self-referencing relations
  • Loading branch information
jsangmeister committed Apr 19, 2024
2 parents 936d185 + fae58a6 commit b6da76d
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 29 deletions.
30 changes: 14 additions & 16 deletions dev/sql/schema_relational.sql
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ BEGIN
END;
$$ LANGUAGE plpgsql;

-- MODELS_YML_CHECKSUM = 'bbd75cac13c55c82f772ae52df63aa96'
-- MODELS_YML_CHECKSUM = '82f9031bf779d97f165fdce1ceb5cf71'
-- Type definitions

-- Table definitions
Expand Down Expand Up @@ -128,13 +128,15 @@ CREATE TABLE IF NOT EXISTS user_t (
is_demo_user boolean,
last_login timestamptz,
organization_management_level varchar(256) CONSTRAINT enum_user_organization_management_level CHECK (organization_management_level IN ('superadmin', 'can_manage_organization', 'can_manage_users')),
meeting_ids integer[],
organization_id integer GENERATED ALWAYS AS (1) STORED NOT NULL
);



comment on column user_t.saml_id is 'unique-key from IdP for SAML login';
comment on column user_t.organization_management_level is 'Hierarchical permission level for the whole organization.';
comment on column user_t.meeting_ids is 'Calculated. All ids from meetings calculated via meeting_user and group_ids as integers.';


CREATE TABLE IF NOT EXISTS meeting_user_t (
Expand Down Expand Up @@ -403,6 +405,7 @@ This email was generated automatically.',
font_projector_h1_id integer,
font_projector_h2_id integer,
committee_id integer NOT NULL,
user_ids integer[],
reference_projector_id integer NOT NULL,
list_of_speakers_countdown_id integer,
poll_countdown_id integer,
Expand All @@ -417,6 +420,7 @@ comment on column meeting_t.is_active_in_organization_id is 'Backrelation and bo
comment on column meeting_t.is_archived_in_organization_id is 'Backrelation and boolean flag at once';
comment on column meeting_t.list_of_speakers_default_structure_level_time is '0 disables structure level countdowns.';
comment on column meeting_t.list_of_speakers_intervention_time is '0 disables intervention speakers.';
comment on column meeting_t.user_ids is 'Calculated. All user ids from all users assigned to groups of this meeting.';


CREATE TABLE IF NOT EXISTS structure_level_t (
Expand Down Expand Up @@ -608,7 +612,6 @@ CREATE TABLE IF NOT EXISTS motion_t (
sort_parent_id integer,
origin_id integer,
origin_meeting_id integer,
identical_motion_ids integer[],
state_id integer NOT NULL,
recommendation_id integer,
category_id integer,
Expand All @@ -621,7 +624,6 @@ CREATE TABLE IF NOT EXISTS motion_t (

comment on column motion_t.number_value is 'The number value of this motion. This number is auto-generated and read-only.';
comment on column motion_t.sequential_number is 'The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.';
comment on column motion_t.identical_motion_ids is 'with psycopg 3.2.0 we could use the as_string method without cursor and change dummy to number. Changed from relation-list to number[], because it still can''t be generated.';


CREATE TABLE IF NOT EXISTS motion_submitter_t (
Expand Down Expand Up @@ -1129,12 +1131,6 @@ CREATE TABLE IF NOT EXISTS nm_meeting_present_user_ids_user_t (
PRIMARY KEY (meeting_id, user_id)
);

CREATE TABLE IF NOT EXISTS nm_meeting_user_ids_user_t (
meeting_id integer NOT NULL REFERENCES meeting_t (id),
user_id integer NOT NULL REFERENCES user_t (id),
PRIMARY KEY (meeting_id, user_id)
);

CREATE TABLE IF NOT EXISTS nm_group_meeting_user_ids_meeting_user_t (
group_id integer NOT NULL REFERENCES group_t (id),
meeting_user_id integer NOT NULL REFERENCES meeting_user_t (id),
Expand Down Expand Up @@ -1188,6 +1184,12 @@ CREATE TABLE IF NOT EXISTS nm_motion_all_derived_motion_ids_motion_t (
PRIMARY KEY (all_derived_motion_id, all_origin_id)
);

CREATE TABLE IF NOT EXISTS nm_motion_identical_motion_ids_motion_t (
identical_motion_id_1 integer NOT NULL REFERENCES motion_t (id),
identical_motion_id_2 integer NOT NULL REFERENCES motion_t (id),
PRIMARY KEY (identical_motion_id_1, identical_motion_id_2)
);

CREATE TABLE IF NOT EXISTS gm_motion_state_extension_reference_ids_t (
id integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
motion_id integer NOT NULL REFERENCES motion_t(id),
Expand Down Expand Up @@ -1264,12 +1266,10 @@ CREATE OR REPLACE VIEW user_ AS SELECT *,
(select array_agg(o.id) from option_t o where o.content_object_id_user_id = u.id) as option_ids,
(select array_agg(v.id) from vote_t v where v.user_id = u.id) as vote_ids,
(select array_agg(v.id) from vote_t v where v.delegated_user_id = u.id) as delegated_vote_ids,
(select array_agg(p.id) from poll_candidate_t p where p.user_id = u.id) as poll_candidate_ids,
(select array_agg(n.meeting_id) from nm_meeting_user_ids_user_t n where n.user_id = u.id) as meeting_ids
(select array_agg(p.id) from poll_candidate_t p where p.user_id = u.id) as poll_candidate_ids
FROM user_t u;

comment on column user_.committee_ids is 'Calculated field: Returns committee_ids, where the user is manager or member in a meeting';
comment on column user_.meeting_ids is 'Calculated. All ids from meetings calculated via meeting_user and group_ids as integers.';

CREATE OR REPLACE VIEW meeting_user AS SELECT *,
(select array_agg(p.id) from personal_note_t p where p.meeting_user_id = m.id) as personal_note_ids,
Expand Down Expand Up @@ -1353,7 +1353,6 @@ CREATE OR REPLACE VIEW meeting AS SELECT *,
(select c.id from committee_t c where c.default_meeting_id = m.id) as default_meeting_for_committee_id,
(select array_agg(g.organization_tag_id) from gm_organization_tag_tagged_ids_t g where g.tagged_id_meeting_id = m.id) as organization_tag_ids,
(select array_agg(n.user_id) from nm_meeting_present_user_ids_user_t n where n.meeting_id = m.id) as present_user_ids,
(select array_agg(n.user_id) from nm_meeting_user_ids_user_t n where n.meeting_id = m.id) as user_ids,
(select array_agg(p.id) from projection_t p where p.content_object_id_meeting_id = m.id) as projection_ids,
(select array_agg(p.id) from projector_t p where p.used_as_default_projector_for_agenda_item_list_in_meeting_id = m.id) as default_projector_agenda_item_list_ids,
(select array_agg(p.id) from projector_t p where p.used_as_default_projector_for_topic_in_meeting_id = m.id) as default_projector_topic_ids,
Expand All @@ -1371,7 +1370,6 @@ CREATE OR REPLACE VIEW meeting AS SELECT *,
(select array_agg(p.id) from projector_t p where p.used_as_default_projector_for_poll_in_meeting_id = m.id) as default_projector_poll_ids
FROM meeting_t m;

comment on column meeting.user_ids is 'Calculated. All user ids from all users assigned to groups of this meeting.';

CREATE OR REPLACE VIEW structure_level AS SELECT *,
(select array_agg(n.meeting_user_id) from nm_meeting_user_structure_level_ids_structure_level_t n where n.structure_level_id = s.id) as meeting_user_ids,
Expand Down Expand Up @@ -1438,6 +1436,7 @@ CREATE OR REPLACE VIEW motion AS SELECT *,
(select array_agg(m1.id) from motion_t m1 where m1.origin_id = m.id) as derived_motion_ids,
(select array_agg(n.all_origin_id) from nm_motion_all_derived_motion_ids_motion_t n where n.all_derived_motion_id = m.id) as all_origin_ids,
(select array_agg(n.all_derived_motion_id) from nm_motion_all_derived_motion_ids_motion_t n where n.all_origin_id = m.id) as all_derived_motion_ids,
(select array_cat((select array_agg(n.identical_motion_id_1) from nm_motion_identical_motion_ids_motion_t n where n.identical_motion_id_2 = m.id), (select array_agg(n.identical_motion_id_2) from nm_motion_identical_motion_ids_motion_t n where n.identical_motion_id_1 = m.id))) as identical_motion_ids,
(select array_agg(g.id) from gm_motion_state_extension_reference_ids_t g where g.motion_id = m.id) as state_extension_reference_ids,
(select array_agg(g.motion_id) from gm_motion_state_extension_reference_ids_t g where g.state_extension_reference_id_motion_id = m.id) as referenced_in_motion_state_extension_ids,
(select array_agg(g.id) from gm_motion_recommendation_extension_reference_ids_t g where g.motion_id = m.id) as recommendation_extension_reference_ids,
Expand Down Expand Up @@ -1943,7 +1942,6 @@ SQL nt:1Gr => user/option_ids:-> option/content_object_id
SQL nt:1r => user/vote_ids:-> vote/user_id
SQL nt:1r => user/delegated_vote_ids:-> vote/delegated_user_id
SQL nt:1r => user/poll_candidate_ids:-> poll_candidate/user_id
SQL nt:nt => user/meeting_ids:-> meeting/user_ids
FIELD 1rR: => meeting_user/user_id:-> user/
FIELD 1rR: => meeting_user/meeting_id:-> meeting/
Expand Down Expand Up @@ -2041,7 +2039,6 @@ FIELD 1rR: => meeting/committee_id:-> committee/
SQL 1t:1r => meeting/default_meeting_for_committee_id:-> committee/default_meeting_id
SQL nt:nGt => meeting/organization_tag_ids:-> organization_tag/tagged_ids
SQL nt:nt => meeting/present_user_ids:-> user/is_present_in_meeting_ids
SQL nt:nt => meeting/user_ids:-> user/meeting_ids
FIELD 1rR: => meeting/reference_projector_id:-> projector/
FIELD 1r: => meeting/list_of_speakers_countdown_id:-> projector_countdown/
FIELD 1r: => meeting/poll_countdown_id:-> projector_countdown/
Expand Down Expand Up @@ -2133,6 +2130,7 @@ FIELD 1r: => motion/origin_meeting_id:-> meeting/
SQL nt:1r => motion/derived_motion_ids:-> motion/origin_id
SQL nt:nt => motion/all_origin_ids:-> motion/all_derived_motion_ids
SQL nt:nt => motion/all_derived_motion_ids:-> motion/all_origin_ids
SQL nt:nt => motion/identical_motion_ids:-> motion/identical_motion_ids
FIELD 1rR: => motion/state_id:-> motion_state/
FIELD 1r: => motion/recommendation_id:-> motion_state/
SQL nGt:nt => motion/state_extension_reference_ids:-> motion/referenced_in_motion_state_extension_ids
Expand Down
30 changes: 21 additions & 9 deletions dev/src/generate_sql_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ def get_relation_list_type(
foreign_table_name,
foreign_table_column,
foreign_table_ref_column,
own_table_field.field_def == foreign_table_field.field_def,
)
if comment := fdata.get("description"):
text["post_view"] = Helper.get_post_view_comment(
Expand All @@ -448,15 +449,25 @@ def get_sql_for_relation_n_1(
foreign_table_name: str,
foreign_table_column: str,
foreign_table_ref_column: str,
self_reference: bool = False,
) -> str:
table_letter = Helper.get_table_letter(table_name)
letters = [table_letter]
foreign_letter = Helper.get_table_letter(foreign_table_name, letters)
foreign_letter = Helper.get_table_letter(foreign_table_name, [table_letter])
foreign_table_name = HelperGetNames.get_table_name(foreign_table_name)
if foreign_table_column:
return f"(select array_agg({foreign_letter}.{foreign_table_ref_column}) from {foreign_table_name} {foreign_letter} where {foreign_letter}.{foreign_table_column} = {table_letter}.{own_ref_column}) as {fname},\n"
AGG_TEMPLATE = f"select array_agg({foreign_letter}.{{}}) from {foreign_table_name} {foreign_letter}"
COND_TEMPLATE = (
f" where {foreign_letter}.{{}} = {table_letter}.{own_ref_column}"
)
if not foreign_table_column or not self_reference:
query = AGG_TEMPLATE.format(foreign_table_ref_column)
if foreign_table_column:
query += COND_TEMPLATE.format(foreign_table_column)
else:
return f"(select array_agg({foreign_letter}.{foreign_table_ref_column}) from {foreign_table_name} {foreign_letter}) as {fname},\n"
assert foreign_table_ref_column == (col := foreign_table_column)
arr1 = AGG_TEMPLATE.format(f"{col}_1") + COND_TEMPLATE.format(f"{col}_2")
arr2 = AGG_TEMPLATE.format(f"{col}_2") + COND_TEMPLATE.format(f"{col}_1")
query = f"select array_cat(({arr1}), ({arr2}))"
return f"({query}) as {fname},\n"

@classmethod
def get_trigger_check_not_null_for_relation_lists(
Expand Down Expand Up @@ -814,6 +825,9 @@ def get_nm_table_for_n_m_relation_lists(
field2 = HelperGetNames.get_field_in_n_m_relation_list(
foreign_table_field, own_table_field.table
)
if field1 == field2:
field1 += "_1"
field2 += "_2"
text = Helper.INTERMEDIATE_TABLE_N_M_RELATION_TEMPLATE.substitute(
{
"table_name": HelperGetNames.get_table_name(nm_table_name),
Expand Down Expand Up @@ -1082,11 +1096,9 @@ def generate_field_or_sql_decision(
error = f"Type combination not implemented: {own_c}:{foreign_c} on field {own.collectionfield}\n"
state = FieldSqlErrorType.ERROR
elif primary == "primary_decide_alphabetical":
if own.collectionfield == foreign.collectionfield:
error = f"Field {own.collectionfield} identical with foreign.collectionfield. SQL_decice_alphabetical uncedidable!\n"
state = FieldSqlErrorType.ERROR
primary = (
foreign.collectionfield == "-"
own.collectionfield == foreign.collectionfield
or foreign.collectionfield == "-"
or own.collectionfield < foreign.collectionfield
)
return cast(FieldSqlErrorType, state), cast(bool, primary), error
Expand Down
6 changes: 2 additions & 4 deletions models.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2691,10 +2691,8 @@ motion:
to: motion/all_origin_ids
restriction_mode: A
identical_motion_ids:
type: number[]
# type: relation-list
# to: motion/identical_motion_ids
description: with psycopg 3.2.0 we could use the as_string method without cursor and change dummy to number. Changed from relation-list to number[], because it still can''t be generated.
type: relation-list
to: motion/identical_motion_ids
restriction_mode: C
state_id:
type: relation
Expand Down

0 comments on commit b6da76d

Please sign in to comment.