Mailing List Archive

rt branch 5.0/cgm-cascade-delete created. rt-5.0.5-76-g4222af2a79
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt".

The branch, 5.0/cgm-cascade-delete has been created
at 4222af2a79f675ba753923cf448d0e9c78ffb8ae (commit)

- Log -----------------------------------------------------------------
commit 4222af2a79f675ba753923cf448d0e9c78ffb8ae
Author: sunnavy <sunnavy@bestpractical.com>
Date: Thu Dec 7 15:48:17 2023 -0500

Test cascaded deletion of cached group members

diff --git a/t/api/group.t b/t/api/group.t
index 13389567ee..0f5a997748 100644
--- a/t/api/group.t
+++ b/t/api/group.t
@@ -201,4 +201,33 @@ diag "Ticket role group members";
ok( !$CGM->id, 'No CGM record for admincc <-> bob still' );
}

+
+diag "Cascade delete cached group members";
+{
+ my $test1 = RT::Test->load_or_create_group('cascade test 1');
+ my $test2 = RT::Test->load_or_create_group('cascade test 2');
+ my $test3 = RT::Test->load_or_create_group('cascade test 3');
+ my $user = RT::Test->load_or_create_user( Name => 'User 1' );
+
+ ok( $test3->AddMember( $user->PrincipalId ), 'Add User 1 to test 3' );
+ ok( $test2->AddMember( $test3->PrincipalId ), 'Add test 3 to test 2' );
+ ok( $test1->AddMember( $test2->PrincipalId ), 'Add test 2 to test 1' );
+
+ ok( $test1->HasMemberRecursively( $test2->PrincipalId ), "Group test 1 has test 2 recursively" );
+ ok( $test1->HasMemberRecursively( $test3->PrincipalId ), "Group test 1 has test 3 recursively" );
+ ok( $test1->HasMemberRecursively( $user->PrincipalId ), "Group test 1 has User 1 recursively" );
+
+ my $cgms = RT::CachedGroupMembers->new( RT->SystemUser );
+ $cgms->Limit( FIELD => 'GroupId', VALUE => $test1->Id );
+ is( $cgms->Count, 4, 'Group test has 4 CachedGroupMembers rows' );
+
+ ok( $test1->DeleteMember( $test2->PrincipalId ), 'Delete test 2 from test' );
+ $cgms->RedoSearch;
+ is( $cgms->Count, 1, 'Group test has 1 CachedGroupMembers row' );
+
+ ok( !$test1->HasMemberRecursively( $test2->PrincipalId ), "Group test 1 does not have test 2 recursively" );
+ ok( !$test1->HasMemberRecursively( $test3->PrincipalId ), "Group test 1 does not have test 3 recursively" );
+ ok( !$test1->HasMemberRecursively( $user->PrincipalId ), "Group test 1 does not have User 1 recursively" );
+}
+
done_testing;

commit c2867d315e06fd2e6c3d4ba90cd05f1891fb9473
Author: sunnavy <sunnavy@bestpractical.com>
Date: Thu Dec 7 15:38:57 2023 -0500

Implement cascaded deletion of cached group members on DB level

The performance is obviously better to clean up stuff on DB level. As
Via is a foreign key, it can't be 0 any more.

diff --git a/etc/schema.Oracle b/etc/schema.Oracle
index d0893a74c9..28c59f6357 100644
--- a/etc/schema.Oracle
+++ b/etc/schema.Oracle
@@ -199,7 +199,8 @@ CREATE TABLE CachedGroupMembers (
MemberId NUMBER(11,0),
Via NUMBER(11,0),
ImmediateParentId NUMBER(11,0),
- Disabled NUMBER(11,0) DEFAULT 0 NOT NULL
+ Disabled NUMBER(11,0) DEFAULT 0 NOT NULL,
+ FOREIGN KEY (Via) REFERENCES CachedGroupMembers(id) ON DELETE CASCADE
);
CREATE INDEX DisGrouMem ON CachedGroupMembers (GroupId, MemberId, Disabled);
CREATE INDEX CachedGroupMembers2 ON CachedGroupMembers (MemberId, GroupId, Disabled);
diff --git a/etc/schema.Pg b/etc/schema.Pg
index 2e7a983062..2440171ee1 100644
--- a/etc/schema.Pg
+++ b/etc/schema.Pg
@@ -325,6 +325,7 @@ CREATE TABLE CachedGroupMembers (
Via int,
ImmediateParentId int,
Disabled integer NOT NULL DEFAULT 0 ,
+ FOREIGN KEY (Via) REFERENCES CachedGroupMembers(id) ON DELETE CASCADE,
PRIMARY KEY (id)

);
diff --git a/etc/schema.SQLite b/etc/schema.SQLite
index be08cfd925..3df66dd98f 100644
--- a/etc/schema.SQLite
+++ b/etc/schema.SQLite
@@ -221,11 +221,12 @@ create table CachedGroupMembers (
MemberId int,
Via int,
ImmediateParentId int,
- Disabled int2 NOT NULL DEFAULT 0 # if this cached group member is a member of this group by way of a disabled
+ Disabled int2 NOT NULL DEFAULT 0, # if this cached group member is a member of this group by way of a disabled
# group or this group is disabled, this will be set to 1
# this allows us to not find members of disabled subgroups when listing off
# group members recursively.
# Also, this allows us to have the ACL system elide members of disabled groups
+ FOREIGN KEY (Via) REFERENCES CachedGroupMembers(id) ON DELETE CASCADE


) ;
diff --git a/etc/schema.mysql b/etc/schema.mysql
index 0c21d2b8b4..aa18b45a77 100644
--- a/etc/schema.mysql
+++ b/etc/schema.mysql
@@ -207,6 +207,7 @@ create table CachedGroupMembers (
# this allows us to not find members of disabled subgroups when listing off
# group members recursively.
# Also, this allows us to have the ACL system elide members of disabled groups
+ FOREIGN KEY (Via) REFERENCES CachedGroupMembers(id) ON DELETE CASCADE,
PRIMARY KEY (id)
) ENGINE=InnoDB CHARACTER SET utf8mb4;

diff --git a/etc/upgrade/5.0.6/schema.Oracle b/etc/upgrade/5.0.6/schema.Oracle
index ec8e090828..9f3b4b28ef 100644
--- a/etc/upgrade/5.0.6/schema.Oracle
+++ b/etc/upgrade/5.0.6/schema.Oracle
@@ -1 +1,2 @@
CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);
+ALTER TABLE CachedGroupMembers ADD FOREIGN KEY (Via) REFERENCES CachedGroupMembers(id) ON DELETE CASCADE;
diff --git a/etc/upgrade/5.0.6/schema.Pg b/etc/upgrade/5.0.6/schema.Pg
index ec8e090828..9f3b4b28ef 100644
--- a/etc/upgrade/5.0.6/schema.Pg
+++ b/etc/upgrade/5.0.6/schema.Pg
@@ -1 +1,2 @@
CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);
+ALTER TABLE CachedGroupMembers ADD FOREIGN KEY (Via) REFERENCES CachedGroupMembers(id) ON DELETE CASCADE;
diff --git a/etc/upgrade/5.0.6/schema.mysql b/etc/upgrade/5.0.6/schema.mysql
index ec8e090828..9f3b4b28ef 100644
--- a/etc/upgrade/5.0.6/schema.mysql
+++ b/etc/upgrade/5.0.6/schema.mysql
@@ -1 +1,2 @@
CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);
+ALTER TABLE CachedGroupMembers ADD FOREIGN KEY (Via) REFERENCES CachedGroupMembers(id) ON DELETE CASCADE;
diff --git a/lib/RT/CachedGroupMember.pm b/lib/RT/CachedGroupMember.pm
index dc2feeed18..9debea6d56 100644
--- a/lib/RT/CachedGroupMember.pm
+++ b/lib/RT/CachedGroupMember.pm
@@ -99,7 +99,7 @@ sub Create {
my %args = ( Group => '',
Member => '',
ImmediateParent => '',
- Via => '0',
+ Via => undef,
Disabled => '0',
@_ );

@@ -141,7 +141,12 @@ sub Create {
. $args{'Via'} );
return (undef); #this will percolate up and bail out of the transaction
}
- if ( $self->__Value('Via') == 0 ) {
+
+ # Check $args{Via} instead of __Value('Via') to avoid cache issues on
+ # SQLite that may reuse ids: t/validator/group_members.t fails with
+ # __Value('Via')
+
+ if ( !$args{Via} ) {
my ( $vid, $vmsg ) = $self->__Set( Field => 'Via', Value => $id );
unless ($vid) {
$RT::Logger->warning( "Due to a via error, couldn't create "
@@ -181,44 +186,6 @@ sub Create {



-=head2 Delete
-
-Deletes the current CachedGroupMember from the group it's in and
-cascades the delete to all submembers.
-
-=cut
-
-sub Delete {
- my $self = shift;
-
-
- my $member = $self->MemberObj();
- if ( $member->IsGroup ) {
- my $deletable = RT::CachedGroupMembers->new( $self->CurrentUser );
-
- $deletable->Limit( FIELD => 'id',
- OPERATOR => '!=',
- VALUE => $self->id );
- $deletable->Limit( FIELD => 'Via',
- OPERATOR => '=',
- VALUE => $self->id );
-
- while ( my $kid = $deletable->Next ) {
- my ($ok, $msg) = $kid->Delete();
- unless ($ok) {
- $RT::Logger->error(
- "Couldn't delete CachedGroupMember " . $kid->Id );
- return ($ok, $msg);
- }
- }
- }
- my ($ok, $msg) = $self->SUPER::Delete();
- $RT::Logger->error( "Couldn't delete CachedGroupMember " . $self->Id ) unless $ok;
- return ($ok, $msg);
-}
-
-
-
=head2 SetDisabled

SetDisableds the current CachedGroupMember from the group it's in and cascades
diff --git a/lib/RT/GroupMember.pm b/lib/RT/GroupMember.pm
index 41b083561b..44286aa7a2 100644
--- a/lib/RT/GroupMember.pm
+++ b/lib/RT/GroupMember.pm
@@ -103,7 +103,7 @@ sub _InsertCGM {
Member => $self->MemberObj,
Group => $self->GroupObj,
ImmediateParent => $self->GroupObj,
- Via => '0'
+ Via => undef,
);


@@ -289,7 +289,7 @@ sub _StashUser {
Member => $args{'Member'},
Group => $args{'Group'},
ImmediateParent => $args{'Group'},
- Via => '0'
+ Via => undef,
);

unless ($cached_id) {
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 02e4667d7f..a7af75533e 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -154,6 +154,7 @@ sub Connect {
}
elsif ( $db_type eq 'SQLite' ) {
$self->dbh->{sqlite_see_if_its_a_number} = 1;
+ $self->dbh->do('PRAGMA foreign_keys = ON'); # ON DELETE CASCADE for CachedGroupMembers needs it
}

$self->dbh->{'LongReadLen'} = RT->Config->Get('MaxAttachmentSize');
diff --git a/lib/RT/Migrate/Importer.pm b/lib/RT/Migrate/Importer.pm
index f73240e522..6da135c5d0 100644
--- a/lib/RT/Migrate/Importer.pm
+++ b/lib/RT/Migrate/Importer.pm
@@ -632,7 +632,7 @@ sub CloseStream {
# Groups
$self->RunSQL(<<'EOF');
INSERT INTO CachedGroupMembers (GroupId, MemberId, Via, ImmediateParentId, Disabled)
- SELECT Groups.id, Groups.id, 0, Groups.id, Principals.Disabled FROM Groups
+ SELECT Groups.id, Groups.id, NULL, Groups.id, Principals.Disabled FROM Groups
LEFT JOIN Principals ON ( Groups.id = Principals.id )
LEFT JOIN CachedGroupMembers ON (
Groups.id = CachedGroupMembers.GroupId
@@ -645,7 +645,7 @@ EOF
# GroupMembers
$self->RunSQL(<<'EOF');
INSERT INTO CachedGroupMembers (GroupId, MemberId, Via, ImmediateParentId, Disabled)
- SELECT GroupMembers.GroupId, GroupMembers.MemberId, 0, GroupMembers.GroupId, Principals.Disabled FROM GroupMembers
+ SELECT GroupMembers.GroupId, GroupMembers.MemberId, NULL, GroupMembers.GroupId, Principals.Disabled FROM GroupMembers
LEFT JOIN Principals ON ( GroupMembers.GroupId = Principals.id )
LEFT JOIN CachedGroupMembers ON (
GroupMembers.GroupId = CachedGroupMembers.GroupId
@@ -657,7 +657,7 @@ EOF

# Fixup Via
$self->RunSQL(<<'EOF');
-UPDATE CachedGroupMembers SET Via=id WHERE Via=0
+UPDATE CachedGroupMembers SET Via=id WHERE Via IS NULL
EOF

# Cascaded GroupMembers, use the same SQL in rt-validator

commit 952c0c610f9663d2f31e1fdd1ee885ada324e923
Author: sunnavy <sunnavy@bestpractical.com>
Date: Thu Dec 7 15:37:40 2023 -0500

Index Via column of CachedGroupMembers

When we delete CachedGroupMember rows, we need to find and delete all
derived rows, by means of the Via column. Without the index, the search
could be quite slow.

diff --git a/etc/schema.Oracle b/etc/schema.Oracle
index 53210b145b..d0893a74c9 100644
--- a/etc/schema.Oracle
+++ b/etc/schema.Oracle
@@ -204,6 +204,7 @@ CREATE TABLE CachedGroupMembers (
CREATE INDEX DisGrouMem ON CachedGroupMembers (GroupId, MemberId, Disabled);
CREATE INDEX CachedGroupMembers2 ON CachedGroupMembers (MemberId, GroupId, Disabled);
CREATE INDEX CachedGroupMembers3 on CachedGroupMembers (MemberId, ImmediateParentId);
+CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);


CREATE SEQUENCE USERS_seq;
diff --git a/etc/schema.Pg b/etc/schema.Pg
index b614793b07..2e7a983062 100644
--- a/etc/schema.Pg
+++ b/etc/schema.Pg
@@ -332,6 +332,7 @@ CREATE TABLE CachedGroupMembers (
CREATE INDEX CachedGroupMembers2 on CachedGroupMembers (MemberId, GroupId, Disabled);
CREATE INDEX DisGrouMem on CachedGroupMembers (GroupId,MemberId,Disabled);
CREATE INDEX CachedGroupMembers3 on CachedGroupMembers (MemberId,ImmediateParentId);
+CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);



diff --git a/etc/schema.SQLite b/etc/schema.SQLite
index 4b64f3349f..be08cfd925 100644
--- a/etc/schema.SQLite
+++ b/etc/schema.SQLite
@@ -233,6 +233,7 @@ create table CachedGroupMembers (
CREATE INDEX CachedGroupMembers1 ON CachedGroupMembers (GroupId, MemberId, Disabled);
CREATE INDEX CachedGroupMembers2 ON CachedGroupMembers (MemberId, GroupId, Disabled);
CREATE INDEX CachedGroupMembers3 ON CachedGroupMembers (MemberId, ImmediateParentId);
+CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);

--- }}}

diff --git a/etc/schema.mysql b/etc/schema.mysql
index 382a10fc43..0c21d2b8b4 100644
--- a/etc/schema.mysql
+++ b/etc/schema.mysql
@@ -213,6 +213,7 @@ create table CachedGroupMembers (
CREATE INDEX DisGrouMem on CachedGroupMembers (GroupId,MemberId,Disabled);
CREATE INDEX CachedGroupMembers2 on CachedGroupMembers (MemberId, GroupId, Disabled);
CREATE INDEX CachedGroupMembers3 on CachedGroupMembers (MemberId, ImmediateParentId);
+CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);



diff --git a/etc/upgrade/5.0.6/schema.Oracle b/etc/upgrade/5.0.6/schema.Oracle
new file mode 100644
index 0000000000..ec8e090828
--- /dev/null
+++ b/etc/upgrade/5.0.6/schema.Oracle
@@ -0,0 +1 @@
+CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);
diff --git a/etc/upgrade/5.0.6/schema.Pg b/etc/upgrade/5.0.6/schema.Pg
new file mode 100644
index 0000000000..ec8e090828
--- /dev/null
+++ b/etc/upgrade/5.0.6/schema.Pg
@@ -0,0 +1 @@
+CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);
diff --git a/etc/upgrade/5.0.6/schema.mysql b/etc/upgrade/5.0.6/schema.mysql
new file mode 100644
index 0000000000..ec8e090828
--- /dev/null
+++ b/etc/upgrade/5.0.6/schema.mysql
@@ -0,0 +1 @@
+CREATE INDEX CachedGroupMembers4 ON CachedGroupMembers (Via);

-----------------------------------------------------------------------


hooks/post-receive
--
rt
_______________________________________________
rt-commit mailing list
rt-commit@lists.bestpractical.com
https://lists.bestpractical.com/mailman/listinfo/rt-commit