[Rt-commit] rt branch, 4.4/mysql8-quoted-tables, created. rt-4.4.4-139-g7ecd5ef54c

Aaron Trevena ast at bestpractical.com
Tue Sep 1 12:31:14 EDT 2020


The branch, 4.4/mysql8-quoted-tables has been created
        at  7ecd5ef54c733e103800437fb367582ee7fb96e4 (commit)

- Log -----------------------------------------------------------------
commit 353b51435e2b3ccb36e456661b23f13ba897f1b6
Author: Aaron Trevena <ast at bestpractical.com>
Date:   Tue Sep 1 16:19:56 2020 +0100

    Update mysql DDL for version 8

diff --git a/etc/acl.mysql b/etc/acl.mysql
index 26e27fbfbc..854a44797e 100644
--- a/etc/acl.mysql
+++ b/etc/acl.mysql
@@ -1,5 +1,7 @@
 
 sub acl {
+    my $dbh = shift;
+    my $mysql_version = $dbh->{mysql_serverversion};
     my $db_name = RT->Config->Get('DatabaseName');
     my $db_rthost = RT->Config->Get('DatabaseRTHost');
     my $db_user = RT->Config->Get('DatabaseUser');
@@ -13,12 +15,22 @@ sub acl {
         return;
     }
     $db_name =~ s/([_%\\])/\\$1/g;
-    return (
-        "GRANT SELECT,INSERT,CREATE,INDEX,UPDATE,DELETE
+
+    my @sql;
+    if ($mysql_version > 8011) {
+       @sql = (
+        "CREATE USER IF NOT EXISTS '$db_user'\@'$db_rthost' IDENTIFIED BY '$db_pass';",
+        "GRANT SELECT,INSERT,CREATE,INDEX,UPDATE,DELETE ON `$db_name`.* TO '$db_user'\@'$db_rthost';",
+    );
+    }
+    else {
+       @sql = ("GRANT SELECT,INSERT,CREATE,INDEX,UPDATE,DELETE
                ON `$db_name`.*
                TO '$db_user'\@'$db_rthost'
-               IDENTIFIED BY '$db_pass';",
-    );
+               IDENTIFIED BY '$db_pass';");
+   }
+
+    return ();
 }
 
 1;
diff --git a/etc/schema.mysql b/etc/schema.mysql
index eefc145ca4..f33f180be3 100644
--- a/etc/schema.mysql
+++ b/etc/schema.mysql
@@ -70,7 +70,7 @@ CREATE TABLE Principals (
 ) ENGINE=InnoDB CHARACTER SET ascii;
 
 
-CREATE TABLE Groups (
+CREATE TABLE `Groups` (
   id INTEGER NOT NULL  AUTO_INCREMENT,
   Name varchar(200) NULL  ,
   Description varchar(255) NULL  ,
@@ -83,8 +83,8 @@ CREATE TABLE Groups (
   PRIMARY KEY (id)
 ) ENGINE=InnoDB CHARACTER SET utf8;
 
-CREATE INDEX Groups1 ON Groups (Domain, Name, Instance);
-CREATE INDEX Groups2 On Groups (Instance);
+CREATE INDEX Groups1 ON `Groups` (Domain, Name, Instance);
+CREATE INDEX Groups2 On `Groups` (Instance);
 
 CREATE TABLE ScripConditions (
   id INTEGER NOT NULL  AUTO_INCREMENT,

commit 27af644cf49f3df6286421c9ee57d0ee27c6996e
Author: Aaron Trevena <ast at bestpractical.com>
Date:   Tue Sep 1 16:20:29 2020 +0100

    Add table quoting for mysql 8

diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 29e929e7b7..c210662991 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -119,6 +119,9 @@ sub Connect {
         $ENV{'NLS_LANG'} = "AMERICAN_AMERICA.AL32UTF8";
         $ENV{'NLS_NCHAR'} = "AL32UTF8";
     }
+    if ( $db_type eq 'mysql' ) {
+        $args{QuoteTableNames} //= 1;
+    }
 
     $self->SUPER::Connect(
         User => RT->Config->Get('DatabaseUser'),
diff --git a/lib/RT/Principal.pm b/lib/RT/Principal.pm
index aec96f7a2e..381e13fd2d 100644
--- a/lib/RT/Principal.pm
+++ b/lib/RT/Principal.pm
@@ -422,8 +422,9 @@ sub HasRights {
     }
     my $roles;
     {
+        my $groups_table = $self->QuoteOtherTableName('Groups');
         my $query
-            = "SELECT DISTINCT Groups.Name "
+            = "SELECT DISTINCT $groups_table.Name "
             . $self->_HasRoleRightQuery(
                 EquivObjects => $args{'EquivObjects'}
             );
@@ -555,8 +556,8 @@ sub _HasRoleRight {
 
     my @roles = $self->RolesWithRight(%args);
     return 0 unless @roles;
-
-    my $query = "SELECT Groups.id "
+    my $groups_table = $self->QuoteOtherTableName('Groups');
+    my $query = "SELECT $groups_table.id "
         . $self->_HasRoleRightQuery( %args, Roles => \@roles );
 
     $self->_Handle->ApplyLimits( \$query, 1 );
@@ -574,14 +575,15 @@ sub _HasRoleRightQuery {
                  @_
                );
 
+    my $groups_table = $self->QuoteOtherTableName('Groups');
     my $query =
-        " FROM Groups, Principals, CachedGroupMembers WHERE "
+        " FROM $groups_table, Principals, CachedGroupMembers WHERE "
 
         # Never find disabled things
         . "Principals.Disabled = 0 " . "AND CachedGroupMembers.Disabled = 0 "
 
         # We always grant rights to Groups
-        . "AND Principals.id = Groups.id "
+        . "AND Principals.id = $groups_table.id "
         . "AND Principals.PrincipalType = 'Group' "
 
 # See if the principal is a member of the group recursively or _is the rightholder_
@@ -594,7 +596,7 @@ sub _HasRoleRightQuery {
 
     if ( $args{'Roles'} ) {
         $query .= "AND (" . join( ' OR ',
-            map $RT::Handle->__MakeClauseCaseInsensitive('Groups.Name', '=', "'$_'"),
+            map $RT::Handle->__MakeClauseCaseInsensitive("$groups_table.Name", '=', "'$_'"),
             @{ $args{'Roles'} }
         ) . ")";
     }
diff --git a/lib/RT/Record.pm b/lib/RT/Record.pm
index 3503f67f30..9cebedb032 100644
--- a/lib/RT/Record.pm
+++ b/lib/RT/Record.pm
@@ -1600,6 +1600,7 @@ entire database.
 sub LockForUpdate {
     my $self = shift;
 
+    my $table = $self->QuotedTableName;
     my $pk = $self->_PrimaryKey;
     my $id = @_ ? $_[0] : $self->$pk;
     $self->_expire if $self->isa("DBIx::SearchBuilder::Record::Cachable");
@@ -1608,12 +1609,11 @@ sub LockForUpdate {
         # "RESERVED" on the first UPDATE/INSERT/DELETE.  Do a no-op
         # UPDATE to force the upgade.
         return RT->DatabaseHandle->dbh->do(
-            "UPDATE " .$self->Table.
-                " SET $pk = $pk WHERE 1 = 0");
+            "UPDATE $table SET $pk = $pk WHERE 1 = 0"
+        );
     } else {
         return $self->_LoadFromSQL(
-            "SELECT * FROM ".$self->Table
-                ." WHERE $pk = ? FOR UPDATE",
+            "SELECT * FROM $table WHERE $pk = ? FOR UPDATE",
             $id,
         );
     }
@@ -2598,7 +2598,7 @@ sub _AsInsertQuery
 
     my $dbh = $RT::Handle->dbh;
 
-    my $res = "INSERT INTO ". $dbh->quote_identifier( $self->Table );
+    my $res = "INSERT INTO ". $dbh->quote_identifier( $self->QuotedTableName );
     my $values = $self->{'values'};
     $res .= "(". join( ",", map { $dbh->quote_identifier( $_ ) } sort keys %$values ) .")";
     $res .= " VALUES";
diff --git a/lib/RT/Users.pm b/lib/RT/Users.pm
index 17d5f6df35..bad6e7f7b8 100644
--- a/lib/RT/Users.pm
+++ b/lib/RT/Users.pm
@@ -476,14 +476,16 @@ sub _RoleClauses {
     my $groups = shift;
     my @objects = @_;
 
+    my $groups_table = $self->RecordClass->QuoteOtherTableName($groups);
+
     my @groups_clauses;
     foreach my $obj ( @objects ) {
         my $type = ref($obj)? ref($obj): $obj;
 
-        my $role_clause = $RT::Handle->__MakeClauseCaseInsensitive("$groups.Domain", '=', "'$type-Role'");
+        my $role_clause = $RT::Handle->__MakeClauseCaseInsensitive("$groups_table.Domain", '=', "'$type-Role'");
 
         if ( my $id = eval { $obj->id } ) {
-            $role_clause .= " AND $groups.Instance = $id";
+            $role_clause .= " AND $groups_table.Instance = $id";
         }
         push @groups_clauses, "($role_clause)";
     }
diff --git a/sbin/rt-validator.in b/sbin/rt-validator.in
index 33767827f1..21cb5e4919 100644
--- a/sbin/rt-validator.in
+++ b/sbin/rt-validator.in
@@ -97,6 +97,7 @@ END
 
 my $dbh = $RT::Handle->dbh;
 my $db_type = RT->Config->Get('DatabaseType');
+my $groups_table = ($db_type eq 'mysql') ? '`Groups`' : 'Groups' ;
 
 my %TYPE = (
     'Transactions.Field'    => 'text',
@@ -641,11 +642,11 @@ push @CHECKS, 'Tickets -> other' => sub {
     {
         my $query = <<END;
 SELECT Tickets.Id, Tickets.Owner
-FROM Groups
-JOIN Tickets ON Tickets.Id = Groups.Instance
-LEFT JOIN GroupMembers ON Groups.Id = GroupMembers.GroupId
-WHERE Groups.Name = 'Owner'
-AND Groups.Domain = 'RT::Ticket-Role'
+FROM $groups_table
+JOIN Tickets ON Tickets.Id = $groups_table.Instance
+LEFT JOIN GroupMembers ON $groups_table.Id = GroupMembers.GroupId
+WHERE $groups_table.Name = 'Owner'
+AND $groups_table.Domain = 'RT::Ticket-Role'
 AND GroupMembers.MemberId IS NULL
 END
 
@@ -678,11 +679,11 @@ END
     {
         my $query = <<END;
 SELECT Tickets.Id, Tickets.Owner, GroupMembers.MemberId
-FROM Groups
-JOIN GroupMembers ON Groups.Id = GroupMembers.GroupId
-JOIN Tickets ON Tickets.Id = Groups.Instance
-WHERE Groups.Name = 'Owner'
-AND Groups.Domain = 'RT::Ticket-Role'
+FROM $groups_table
+JOIN GroupMembers ON $groups_table.Id = GroupMembers.GroupId
+JOIN Tickets ON Tickets.Id = $groups_table.Instance
+WHERE $groups_table.Name = 'Owner'
+AND $groups_table.Domain = 'RT::Ticket-Role'
 AND Tickets.Owner != GroupMembers.MemberId
 END
 
@@ -957,6 +958,7 @@ push @CHECKS, Attributes => sub {
 
 # Fix situations when Creator or LastUpdatedBy references ACL equivalence
 # group of a user instead of user
+
 push @CHECKS, 'FIX: LastUpdatedBy and Creator' => sub {
     my $res = 1;
     my %fix = ();
@@ -967,10 +969,11 @@ push @CHECKS, 'FIX: LastUpdatedBy and Creator' => sub {
             next unless $object->_Accessible( $column, 'auto' );
 
             my $table = m2t($model);
+            $table = "`$table`" if ($db_type eq 'mysql');
             my $query = <<END;
 SELECT m.id, g.id, g.Instance
 FROM
-    Groups g JOIN $table m ON g.id = m.$column
+    $groups_table g JOIN $table m ON g.id = m.$column
 WHERE
     g.Domain = ?
     AND g.Name = ?
@@ -1191,12 +1194,13 @@ push @CHECKS, 'Links: missing object' => sub {
 
         foreach my $use ( @URI_USES ) {
             my $stable = m2t( $use->{'model'} );
+            $stable = "`$stable`" if ($db_type eq 'mysql');
             my $scolumn = $use->{'column'};
 
             foreach my $tmodel ( @models ) {
                 my $tclass = 'RT::'. $tmodel;
                 my $ttable = m2t($tmodel);
-
+                $ttable = "`$ttable`" if ($db_type eq 'mysql');
                 my $tprefix = $prefix .'/'. ($tclass eq 'RT::Ticket'? 'ticket' : $tclass) .'/';
 
                 $tprefix = $prefix . '/article/' if $tclass eq 'RT::Article';
@@ -1271,6 +1275,9 @@ sub check_integrity {
     my ($ttable, @tcols) = (shift, shift);
     my %args = @_;
 
+    $ttable = "`$ttable`" if ($db_type eq 'mysql');
+    $stable = "`$stable`" if ($db_type eq 'mysql');
+
     @scols = @{ $scols[0] } if ref $scols[0];
     @tcols = @{ $tcols[0] } if ref $tcols[0];
 
@@ -1305,7 +1312,8 @@ sub check_integrity {
     my $sth = execute_query( $query, @binds );
     while ( my ($sid, @set) = $sth->fetchrow_array ) {
         $res = 0;
-
+        $stable =~ s/`//g;
+        $ttable =~ s/`//g;
         print STDERR "Record #$sid in $stable references a nonexistent record in $ttable\n";
         for ( my $i = 0; $i < @scols; $i++ ) {
             print STDERR "\t$scols[$i] => '$set[$i]' => $tcols[$i]\n";
@@ -1348,6 +1356,7 @@ sub check_uniqueness {
     my $on = shift;
     my %args = @_;
 
+    $on = "`$on`" if ($db_type eq 'mysql');
     my @columns = @{ $args{'columns'} };
 
     print "Checking uniqueness of ( ", join(', ', map "'$_'", @columns )," ) in table '$on'\n"
@@ -1388,6 +1397,7 @@ sub check_uniqueness {
 
 sub load_record {
     my ($table, $id) = @_;
+    $table = "`$table`" if ($db_type eq 'mysql');
     my $sth = execute_query( "SELECT * FROM $table WHERE id = ?", $id );
     return $sth->fetchrow_hashref('NAME_lc');
 }
@@ -1395,6 +1405,7 @@ sub load_record {
 sub delete_record {
     my ($table, $id) = (@_);
     print "Deleting record #$id in $table\n" if $opt{'verbose'};
+    $table = "`$table`" if ($db_type eq 'mysql');
     my $query = "DELETE FROM $table WHERE id = ?";
     $redo_check{ $_ } = 1 foreach @{ $redo_on{'Delete'}{ $table } || [] };
     return execute_query( $query, $id );
@@ -1411,6 +1422,8 @@ sub update_records {
     my $where = shift;
     my $what = shift;
 
+    $table = "`$table`" if ($db_type eq 'mysql');
+
     my (@where_cols, @where_binds);
     while ( my ($k, $v) = each %$where ) { push @where_cols, $k; push @where_binds, $v; }
 

commit 7ecd5ef54c733e103800437fb367582ee7fb96e4
Author: Aaron Trevena <ast at bestpractical.com>
Date:   Tue Sep 1 16:20:41 2020 +0100

    Update tests for mysql and table quoting

diff --git a/t/validator/transaction.t b/t/validator/transaction.t
index 6b8a5c2980..84ee2740ee 100644
--- a/t/validator/transaction.t
+++ b/t/validator/transaction.t
@@ -55,9 +55,11 @@ my $ticket = RT::Test->create_ticket( Queue => 'General', Subject => 'test ticke
 
     RT::Test->db_is_valid;
 
-    $RT::Handle->dbh->do( "DELETE FROM Users where id=" . $user->id );
-    $RT::Handle->dbh->do( "DELETE FROM Principals where id=" . $user->PrincipalId );
+    my $rv1 = $RT::Handle->dbh->do( "DELETE FROM Users where id=" . $user->id );
+    my $rv2 = $RT::Handle->dbh->do( "DELETE FROM Principals where id=" . $user->PrincipalId );
 
+    warn "rv1 : $rv1 / rv2 : $rv2 / err " . $RT::Handle->dbh->errstr;
+    
     my ( $ecode, $res ) = RT::Test->run_validator( resolve => 1 );
     isnt( $ecode, 0, 'non-zero exit code' );
     like(

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


More information about the rt-commit mailing list