Merge pull request #1939 from webmin/dev/collation-downgrade

Add ability to downgrade database collation
This commit is contained in:
Jamie Cameron
2023-07-01 19:11:38 -07:00
committed by GitHub
5 changed files with 80 additions and 6 deletions

File diff suppressed because one or more lines are too long

View File

@@ -9,6 +9,8 @@ $access{'edonly'} && &error($text{'dbase_ecannot'});
&error_setup($text{'exec_err'});
$sql_charset = $in{'charset'};
my ($ver, $variant) = &get_remote_mysql_variant();
if ($in{'mode'}) {
# From uploaded file
$in{'upload'} || &error($text{'exec_eupload'});
@@ -50,18 +52,22 @@ if ($cmd) {
}
# Check the file for tables created and rows inserted
$create_count = 0;
$insert_count = 0;
my $create_count = 0;
my $insert_count = 0;
my $collation_downgrade = 0;
open(SQL, "<$file");
while(<SQL>) {
if (/^\s*insert\s+into\s+`(\S+)`/i ||
/^\s*insert\s+into\s+(\S+)/i) {
/^\s*insert\s+into\s+(\S+)/i) {
$insert_count++;
}
if (/^\s*create\s+table\s+`(\S+)`/i ||
/^\s*create\s+table\s+(\S+)/i) {
/^\s*create\s+table\s+(\S+)/i) {
$create_count++;
}
if ($variant eq 'mariadb' && /COLLATE\s+utf8mb4_0900_ai_ci/i) {
$collation_downgrade++;
}
}
close(SQL);
@@ -73,6 +79,9 @@ $got++ if ($out =~ /\S/);
print "<i>$text{'exec_noout'}</i>\n" if (!$got);
print "</pre>\n";
if (!$ex) {
if ($collation_downgrade) {
print &text('exec_collationdown', 'utf8mb4_0900_ai_ci', 'utf8mb4_unicode_520_ci'),"<br>\n";
}
if ($create_count) {
print &text('exec_created', $create_count),"\n";
}

View File

@@ -433,6 +433,7 @@ exec_iheader=Text file import options
exec_created=$1 tables were created.
exec_inserted=$1 records were inserted.
exec_cs=Character set for data
exec_collationdown=Database collation was downgraded from <tt>$1</tt> to <tt>$2</tt>
tprivs_title=Table Permissions
tprivs_table=Table

View File

@@ -1034,7 +1034,7 @@ local $cs = $sql_charset ? "--default-character-set=".quotemeta($sql_charset)
: "";
local $temp = &transname();
&open_tempfile(TEMP, ">$temp");
&print_tempfile(TEMP, "source ".$file.";\n");
&print_tempfile(TEMP, "source ".&fix_collation($file).";\n");
&close_tempfile(TEMP);
&set_ownership_permissions(undef, undef, 0644, $temp);
&set_authstr_env();
@@ -1412,6 +1412,29 @@ if (&compare_version_numbers(&get_remote_mysql_version(), "5") >= 0) {
return sort { lc($a->[0]) cmp lc($b->[0]) } @rv;
}
# fix_collation(file)
# Fixes unsupported collations on restore, by replacing
# unsuported with the closest supported variant
sub fix_collation
{
my ($file) = @_;
my ($version, $variant) = &get_remote_mysql_variant();
if ($variant eq 'mariadb') {
my $tfile = &transname();
open(IN, '<' . $file) or die $!;
open(OUT, '>' . $tfile) or die $!;
while(<IN>) {
s/COLLATE(\s|=)utf8mb4_0900_ai_ci/COLLATE$1utf8mb4_unicode_520_ci/g;
print OUT;
}
close(OUT);
close(IN);
&copy_permissions_source_dest($file, $tfile);
return $tfile;
}
return $file;
}
# list_system_variables()
# Returns a list of all system variables, and their default values
sub list_system_variables

View File

@@ -7662,6 +7662,47 @@ foreach my $f (@_) {
return wantarray ? ($rv, $err) : $rv;
}
=head2 copy_permissions_source_dest(source, dest)
Copy file permissions from one file to another. Returns 1
on success, or 0 on failure - also sets $! on failure.
=cut
sub copy_permissions_source_dest
{
return (1, undef) if (&is_readonly_mode());
my ($src, $dst) = @_;
my ($err, $ok);
# Stat source file
my @ssrc = stat($src);
if ($!) {
return wantarray ? (0, "$src : $!") : 0;
}
# Set permissions
chmod($ssrc[2] & 07777, $dst);
if ($!) {
return wantarray ? (0, "$dst : $!") : 0;
}
# Set owner and group
chown($ssrc[4], $ssrc[5], $dst);
if ($!) {
return wantarray ? (0, "$dst : $!") : 0;
}
# Set security context
if (&is_selinux_enabled() && &has_command("chcon")) {
&execute_command("chcon --reference=".quotemeta($src). " ".quotemeta($dst), undef, undef, \$err);
if ($err) {
return wantarray ? (0, $err) : 0;
}
}
return wantarray ? (1, undef) : 1;
}
=head2 copy_source_dest(source, dest, [copy-link-target])
Copy some file or directory to a new location. Returns 1 on success, or 0