diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..8e6d81647 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,15 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +polar: # Replace with a single Polar username +buy_me_a_coffee: jmrenouard +thanks_dev: # Replace with a single thanks.dev username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/CURRENT_VERSION.txt b/CURRENT_VERSION.txt index 37c6fdb60..7ee492487 100644 --- a/CURRENT_VERSION.txt +++ b/CURRENT_VERSION.txt @@ -1 +1 @@ -2.8.23 +2.8.25 diff --git a/Changelog b/Changelog index 2599ed6d7..be5c5d66c 100644 --- a/Changelog +++ b/Changelog @@ -1,7 +1,18 @@ -2.8.23 2026-01-18 +2.8.25 2026-01-18 - +2.8.24 2026-01-18 + +- fix: improve MariaDB 11+ detection by checking version_comment (issue #869) +- fix: handle innodb_buffer_pool_chunk_size=0 (autosize) in MariaDB 10.8+ (#869) +- chore: bump version to 2.8.24 + +2.8.23 2026-01-18 + +- feat: add --ignore-tables CLI option to filter specific tables from analysis (#749) +- chore: bump version to 2.8.23 + 2.8.22 2026-01-18 - feat: update all repository links from 'major' to 'jmrenouard' (issue #410) diff --git a/mysqltuner.pl b/mysqltuner.pl index 59dca56ad..faf1346e5 100755 --- a/mysqltuner.pl +++ b/mysqltuner.pl @@ -1,5 +1,5 @@ #!/usr/bin/env perl -# mysqltuner.pl - Version 2.8.23 +# mysqltuner.pl - Version 2.8.25 # High Performance MySQL Tuning Script # Copyright (C) 2015-2023 Jean-Marie Renouard - jmrenouard@gmail.com # Copyright (C) 2006-2023 Major Hayden - major@mhtx.net @@ -59,7 +59,7 @@ package main; my $is_win = $^O eq 'MSWin32'; # Set up a few variables for use in the script -my $tunerversion = "2.8.23"; +my $tunerversion = "2.8.25"; my ( @adjvars, @generalrec ); # Set defaults @@ -132,7 +132,8 @@ package main; "ssh-password" => '', "ssh-identity-file" => '', "container" => '', - "max-password-checks" => 100 + "max-password-checks" => 100, + "ignore-tables" => '' ); # Gather the options from the command line @@ -174,7 +175,8 @@ package main; 'noprettyicon', 'cloud', 'azure', 'ssh-host=s', 'ssh-user=s', 'ssh-password=s', - 'ssh-identity-file=s', 'container=s', 'max-password-checks=i' + 'ssh-identity-file=s', 'container=s', 'max-password-checks=i', + 'ignore-tables=s' ) or pod2usage( -exitval => 1, @@ -2601,7 +2603,7 @@ sub security_recommendations { # New table schema available since mysql-5.7 and mariadb-10.2 # But need to be checked - if ( $myvar{'version'} =~ /5\.7|10\.[2-5]\..*MariaDB*/ ) { + if ( ($myvar{'version'} =~ /5\.7/) or (($myvar{'version'} =~ /10\.[2-5]\..*/) and (($myvar{'version'} =~ /MariaDB/i) or ($myvar{'version_comment'} =~ /MariaDB/i)))) { my $password_column_exists = `$mysqlcmd $mysqllogin -Bse "SELECT 1 FROM information_schema.columns WHERE TABLE_SCHEMA = 'mysql' AND TABLE_NAME = 'user' AND COLUMN_NAME = 'password'" 2>>$devnull`; my $authstring_column_exists = @@ -2918,7 +2920,7 @@ sub get_replication_status { } # Parallel replication checks (MariaDB specific) - if ( $myvar{'version'} =~ /MariaDB/i ) { + if ( ($myvar{'version'} =~ /MariaDB/i) or ($myvar{'version_comment'} =~ /MariaDB/i) ) { my $parallel_threads = $myvar{'slave_parallel_threads'} // $myvar{'replica_parallel_threads'} // 0; if ( $parallel_threads > 1 ) { @@ -7194,8 +7196,9 @@ sub mysql_innodb { } # InnoDB Used Buffer Pool Size vs CHUNK size - if ( $myvar{'version'} =~ /MariaDB/i + if ( ( ( $myvar{'version'} =~ /MariaDB/i ) or ( $myvar{'version_comment'} =~ /MariaDB/i ) ) and mysql_version_ge( 10, 8 ) + and defined( $myvar{'innodb_buffer_pool_chunk_size'} ) and $myvar{'innodb_buffer_pool_chunk_size'} == 0 ) { infoprint @@ -7360,7 +7363,7 @@ sub mysql_innodb { sub mariadb_query_cache_info { subheaderprint "Query Cache Information"; - unless ( $myvar{'version'} =~ /MariaDB/i ) { + unless ( ($myvar{'version'} =~ /MariaDB/i) or ($myvar{'version_comment'} =~ /MariaDB/i) ) { infoprint "Not a MariaDB server. Skipping Query Cache Info plugin check."; return; @@ -7452,26 +7455,32 @@ sub mysql_databases { return; } + my $ignore_tables_sql = ""; + if ( $opt{'ignore-tables'} ne '' ) { + my @ignored = split /,/, $opt{'ignore-tables'}; + $ignore_tables_sql = " AND TABLE_NAME NOT IN ('" . join( "','", @ignored ) . "')"; + } + @dblist = select_array( "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME NOT IN ( 'mysql', 'performance_schema', 'information_schema', 'sys' );" ); infoprint "There is " . scalar(@dblist) . " Database(s)."; my @totaldbinfo = split /\s/, select_one( -"SELECT SUM(TABLE_ROWS), SUM(DATA_LENGTH), SUM(INDEX_LENGTH), SUM(DATA_LENGTH+INDEX_LENGTH), COUNT(TABLE_NAME), COUNT(DISTINCT(TABLE_COLLATION)), COUNT(DISTINCT(ENGINE)) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys');" +"SELECT SUM(TABLE_ROWS), SUM(DATA_LENGTH), SUM(INDEX_LENGTH), SUM(DATA_LENGTH+INDEX_LENGTH), COUNT(TABLE_NAME), COUNT(DISTINCT(TABLE_COLLATION)), COUNT(DISTINCT(ENGINE)) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')$ignore_tables_sql;" ); infoprint "All User Databases:"; infoprint " +-- TABLE : " . select_one( -"SELECT count(*) from information_schema.TABLES WHERE TABLE_TYPE ='BASE TABLE' AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')" +"SELECT count(*) from information_schema.TABLES WHERE TABLE_TYPE ='BASE TABLE' AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')$ignore_tables_sql" ) . ""; infoprint " +-- VIEW : " . select_one( -"SELECT count(*) from information_schema.TABLES WHERE TABLE_TYPE ='VIEW' AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')" +"SELECT count(*) from information_schema.TABLES WHERE TABLE_TYPE ='VIEW' AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')$ignore_tables_sql" ) . ""; infoprint " +-- INDEX : " . select_one( -"SELECT count(distinct(concat(TABLE_NAME, TABLE_SCHEMA, INDEX_NAME))) from information_schema.STATISTICS WHERE TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')" +"SELECT count(distinct(concat(TABLE_NAME, TABLE_SCHEMA, INDEX_NAME))) from information_schema.STATISTICS WHERE TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')$ignore_tables_sql" ) . ""; infoprint " +-- CHARS : " @@ -7479,7 +7488,7 @@ sub mysql_databases { . ( join ", ", select_array( -"select distinct(CHARACTER_SET_NAME) from information_schema.columns WHERE CHARACTER_SET_NAME IS NOT NULL AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys');" +"select distinct(CHARACTER_SET_NAME) from information_schema.columns WHERE CHARACTER_SET_NAME IS NOT NULL AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')$ignore_tables_sql;" ) ) . ")"; infoprint " +-- COLLA : " @@ -7487,7 +7496,7 @@ sub mysql_databases { . ( join ", ", select_array( -"SELECT DISTINCT(TABLE_COLLATION) FROM information_schema.TABLES WHERE TABLE_COLLATION IS NOT NULL AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys');" +"SELECT DISTINCT(TABLE_COLLATION) FROM information_schema.TABLES WHERE TABLE_COLLATION IS NOT NULL AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')$ignore_tables_sql;" ) ) . ")"; infoprint " +-- ROWS : " @@ -7504,7 +7513,7 @@ sub mysql_databases { . ( join ", ", select_array( -"SELECT DISTINCT(ENGINE) FROM information_schema.TABLES WHERE ENGINE IS NOT NULL AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys');" +"SELECT DISTINCT(ENGINE) FROM information_schema.TABLES WHERE ENGINE IS NOT NULL AND TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys')$ignore_tables_sql;" ) ) . ")"; @@ -7524,29 +7533,29 @@ sub mysql_databases { foreach (@dblist) { my @dbinfo = split /\s/, select_one( -"SELECT TABLE_SCHEMA, SUM(TABLE_ROWS), SUM(DATA_LENGTH), SUM(INDEX_LENGTH), SUM(DATA_LENGTH+INDEX_LENGTH), COUNT(DISTINCT ENGINE), COUNT(TABLE_NAME), COUNT(DISTINCT(TABLE_COLLATION)), COUNT(DISTINCT(ENGINE)) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$_' GROUP BY TABLE_SCHEMA ORDER BY TABLE_SCHEMA" +"SELECT TABLE_SCHEMA, SUM(TABLE_ROWS), SUM(DATA_LENGTH), SUM(INDEX_LENGTH), SUM(DATA_LENGTH+INDEX_LENGTH), COUNT(DISTINCT ENGINE), COUNT(TABLE_NAME), COUNT(DISTINCT(TABLE_COLLATION)), COUNT(DISTINCT(ENGINE)) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$_'$ignore_tables_sql GROUP BY TABLE_SCHEMA ORDER BY TABLE_SCHEMA" ); next unless defined $dbinfo[0]; infoprint "Database: " . $dbinfo[0] . ""; $nbTables = select_one( -"SELECT count(*) from information_schema.TABLES WHERE TABLE_TYPE ='BASE TABLE' AND TABLE_SCHEMA='$_'" +"SELECT count(*) from information_schema.TABLES WHERE TABLE_TYPE ='BASE TABLE' AND TABLE_SCHEMA='$_'$ignore_tables_sql" ); infoprint " +-- TABLE : $nbTables"; infoprint " +-- VIEW : " . select_one( -"SELECT count(*) from information_schema.TABLES WHERE TABLE_TYPE ='VIEW' AND TABLE_SCHEMA='$_'" +"SELECT count(*) from information_schema.TABLES WHERE TABLE_TYPE ='VIEW' AND TABLE_SCHEMA='$_'$ignore_tables_sql" ) . ""; infoprint " +-- INDEX : " . select_one( -"SELECT count(distinct(concat(TABLE_NAME, TABLE_SCHEMA, INDEX_NAME))) from information_schema.STATISTICS WHERE TABLE_SCHEMA='$_'" +"SELECT count(distinct(concat(TABLE_NAME, TABLE_SCHEMA, INDEX_NAME))) from information_schema.STATISTICS WHERE TABLE_SCHEMA='$_'$ignore_tables_sql" ) . ""; infoprint " +-- CHARS : " . ( $totaldbinfo[5] eq 'NULL' ? 0 : $totaldbinfo[5] ) . " (" . ( join ", ", select_array( -"select distinct(CHARACTER_SET_NAME) from information_schema.columns WHERE CHARACTER_SET_NAME IS NOT NULL AND TABLE_SCHEMA='$_';" +"select distinct(CHARACTER_SET_NAME) from information_schema.columns WHERE CHARACTER_SET_NAME IS NOT NULL AND TABLE_SCHEMA='$_'$ignore_tables_sql;" ) ) . ")"; infoprint " +-- COLLA : " @@ -7554,7 +7563,7 @@ sub mysql_databases { . ( join ", ", select_array( -"SELECT DISTINCT(TABLE_COLLATION) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$_' AND TABLE_COLLATION IS NOT NULL;" +"SELECT DISTINCT(TABLE_COLLATION) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$_' AND TABLE_COLLATION IS NOT NULL$ignore_tables_sql;" ) ) . ")"; infoprint " +-- ROWS : " @@ -7572,19 +7581,19 @@ sub mysql_databases { . ( join ", ", select_array( -"SELECT DISTINCT(ENGINE) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$_' AND ENGINE IS NOT NULL" +"SELECT DISTINCT(ENGINE) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$_' AND ENGINE IS NOT NULL$ignore_tables_sql" ) ) . ")"; foreach my $eng ( select_array( -"SELECT DISTINCT(ENGINE) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$_' AND ENGINE IS NOT NULL" +"SELECT DISTINCT(ENGINE) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$_' AND ENGINE IS NOT NULL$ignore_tables_sql" ) ) { infoprint " +-- ENGINE $eng : " . select_one( -"SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$dbinfo[0]' AND ENGINE='$eng'" +"SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$dbinfo[0]' AND ENGINE='$eng'$ignore_tables_sql" ) . " TABLE(s)"; } @@ -7698,12 +7707,18 @@ sub mysql_tables { } + my $ignore_tables_sql = ""; + if ( $opt{'ignore-tables'} ne '' ) { + my @ignored = split /,/, $opt{'ignore-tables'}; + $ignore_tables_sql = " AND TABLE_NAME NOT IN ('" . join( "','", @ignored ) . "')"; + } + foreach ( select_user_dbs() ) { my $dbname = $_; next unless defined $_; infoprint "Database: " . $_ . ""; my @dbtable = select_array( -"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA='$dbname' AND TABLE_TYPE='BASE TABLE' ORDER BY TABLE_NAME" +"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA='$dbname' AND TABLE_TYPE='BASE TABLE'$ignore_tables_sql ORDER BY TABLE_NAME" ); foreach (@dbtable) { my $tbname = $_; @@ -7805,7 +7820,13 @@ sub mysql_indexes { #"Skip Index metrics from information schema due to erroneous information provided in this version"; # return; # } - my $selIdxReq = <<'ENDSQL'; + my $ignore_tables_sql = ""; + if ( $opt{'ignore-tables'} ne '' ) { + my @ignored = split /,/, $opt{'ignore-tables'}; + $ignore_tables_sql = " AND TABLE_NAME NOT IN ('" . join( "','", @ignored ) . "')"; + } + + my $selIdxReq = <<"ENDSQL"; SELECT CONCAT(t.TABLE_SCHEMA, '.', t.TABLE_NAME) AS 'table', CONCAT(s.INDEX_NAME, '(', s.COLUMN_NAME, ')') AS 'index' @@ -7826,14 +7847,14 @@ sub mysql_indexes { , INDEX_NAME , MAX(SEQ_IN_INDEX) AS max_columns FROM INFORMATION_SCHEMA.STATISTICS - WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema') + WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema')$ignore_tables_sql AND INDEX_TYPE <> 'FULLTEXT' GROUP BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME ) AS s2 ON s.TABLE_SCHEMA = s2.TABLE_SCHEMA AND s.TABLE_NAME = s2.TABLE_NAME AND s.INDEX_NAME = s2.INDEX_NAME -WHERE t.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema') +WHERE t.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema')$ignore_tables_sql AND t.TABLE_ROWS > 10 AND s.CARDINALITY IS NOT NULL AND (s.CARDINALITY / IFNULL(t.TABLE_ROWS, 0.01)) < 8.00 @@ -7876,7 +7897,7 @@ sub mysql_indexes { INDEX_TYPE as type FROM information_schema.statistics WHERE INDEX_SCHEMA='$dbname' - AND index_name IS NOT NULL + AND index_name IS NOT NULL$ignore_tables_sql GROUP BY table_name, idxname, type ENDSQL my $found = 0; @@ -7902,13 +7923,13 @@ sub mysql_indexes { unless ( defined( $myvar{'performance_schema'} ) and $myvar{'performance_schema'} eq 'ON' ); - $selIdxReq = <<'ENDSQL'; + $selIdxReq = <<"ENDSQL"; SELECT CONCAT(object_schema, '.', object_name) AS 'table', index_name FROM performance_schema.table_io_waits_summary_by_index_usage WHERE index_name IS NOT NULL AND count_star = 0 AND index_name <> 'PRIMARY' -AND object_schema NOT IN ('mysql', 'performance_schema', 'information_schema') +AND object_schema NOT IN ('mysql', 'performance_schema', 'information_schema')$ignore_tables_sql ORDER BY count_star, object_schema, object_name; ENDSQL @idxinfo = select_array($selIdxReq); @@ -8340,7 +8361,7 @@ =head1 OUTPUT OPTIONS =head1 VERSION -Version 2.8.23 +Version 2.8.25 =head1 PERLDOC You can find documentation for this module with the perldoc command. diff --git a/tests/test_ignore_tables.t b/tests/test_ignore_tables.t new file mode 100644 index 000000000..4874ad611 --- /dev/null +++ b/tests/test_ignore_tables.t @@ -0,0 +1,98 @@ +use strict; +use warnings; +use Test::More; + +# Mocking variables and functions from mysqltuner.pl +our %opt = ( + "ignore-tables" => '' +); +our %myvar; +our %mystat; +our %mycalc; +our @adjvars; +our @generalrec; +our %result; + +sub subheaderprint { } +sub infoprint { } +sub badprint { } +sub goodprint { } +sub debugprint { } +sub hr_bytes { return $_[0]; } +sub hr_num { return $_[0]; } +sub percentage { return "10"; } + +# Mocking select_array and select_one for collation checks +our @mock_dblist = ('db1'); +our %mock_queries = ( + "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME NOT IN ( 'mysql', 'performance_schema', 'information_schema', 'sys' );" => ['db1'], + "SELECT SUM(TABLE_ROWS), SUM(DATA_LENGTH), SUM(INDEX_LENGTH), SUM(DATA_LENGTH+INDEX_LENGTH), COUNT(TABLE_NAME), COUNT(DISTINCT(TABLE_COLLATION)), COUNT(DISTINCT(ENGINE)) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('mysql', 'performance_schema', 'information_schema', 'sys');" => "100 1024 1024 2048 2 2 1", + "SELECT TABLE_SCHEMA, SUM(TABLE_ROWS), SUM(DATA_LENGTH), SUM(INDEX_LENGTH), SUM(DATA_LENGTH+INDEX_LENGTH), COUNT(DISTINCT ENGINE), COUNT(TABLE_NAME), COUNT(DISTINCT(TABLE_COLLATION)), COUNT(DISTINCT(ENGINE)) FROM information_schema.TABLES WHERE TABLE_SCHEMA='db1' GROUP BY TABLE_SCHEMA ORDER BY TABLE_SCHEMA" => "db1 100 1024 1024 2048 1 2 2 1", +); + +sub mysql_version_ge { return 1; } + +sub select_one { + my $query = shift; + return $mock_queries{$query} if exists $mock_queries{$query}; + if ($query =~ /BASE TABLE/ && $query =~ /db1/) { return 2; } + if ($query =~ /VIEW/ && $query =~ /db1/) { return 0; } + if ($query =~ /STATISTICS/ && $query =~ /db1/) { return 2; } + return "NULL"; +} + +sub select_array { + my $query = shift; + if ($query eq "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME NOT IN ( 'mysql', 'performance_schema', 'information_schema', 'sys' );") { + return @mock_dblist; + } + if ($query =~ /CHARACTER_SET_NAME/) { return ('utf8mb4'); } + if ($query =~ /TABLE_COLLATION/ && $query =~ /db1/) { + # This is where we simulate mismatch + if ($opt{"ignore-tables"} =~ /mismatch_table/) { + return ('utf8mb4_general_ci'); + } + return ('utf8mb4_general_ci', 'latin1_swedish_ci'); + } + if ($query =~ /DISTINCT\(ENGINE\)/) { return ('InnoDB'); } + return (); +} + +# The logic to be tested (simplified/extracted from mysql_databases) +sub test_collation_logic { + my @dblist = ('db1'); + @generalrec = (); + foreach my $db (@dblist) { + # Simulation of mysql_databases logic for collation mismatch check + my @dbinfo = split /\s/, select_one("SELECT TABLE_SCHEMA, SUM(TABLE_ROWS), SUM(DATA_LENGTH), SUM(INDEX_LENGTH), SUM(DATA_LENGTH+INDEX_LENGTH), COUNT(DISTINCT ENGINE), COUNT(TABLE_NAME), COUNT(DISTINCT(TABLE_COLLATION)), COUNT(DISTINCT(ENGINE)) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$db' GROUP BY TABLE_SCHEMA ORDER BY TABLE_SCHEMA"); + + my $coll_count = $dbinfo[7]; + + # If ignore-tables is active, we need to manually adjust $coll_count in our mock or the real function needs to use filtered queries + # For this test, we assume the REAL implementation will filter via SQL or post-processing. + # Let's mock a post-processing filtering behavior if we implemented it as such. + + if ($opt{"ignore-tables"}) { + # Simulate SQL that filters ignored tables + if ($opt{"ignore-tables"} =~ /mismatch_table/) { + $coll_count = 1; # Filtered + } + } + + if ( $coll_count > 1 ) { + push( @generalrec, "Check all table collations are identical for all tables in $db database." ); + } + } +} + +# Test 1: Mismatch detected without ignore-tables +$opt{"ignore-tables"} = ''; +test_collation_logic(); +ok(grep(/Check all table collations are identical/, @generalrec), "Should warn about collation mismatch by default"); + +# Test 2: Mismatch suppressed with ignore-tables +$opt{"ignore-tables"} = 'mismatch_table'; +test_collation_logic(); +ok(!grep(/Check all table collations are identical/, @generalrec), "Should NOT warn about collation mismatch when table is ignored"); + +done_testing(); diff --git a/tmp_changelog b/tmp_changelog new file mode 100644 index 000000000..4dae9dda9 --- /dev/null +++ b/tmp_changelog @@ -0,0 +1,248 @@ +2.8.23 2026-01-18 + +- + +2.8.22 2026-01-18 + +- feat: update all repository links from 'major' to 'jmrenouard' (issue #410) +- docs: add Changelog information and Useful Links to all README files (issue #411) +- feat: improve thread_pool_size recommendations based on logical CPU count (issue #404) +- feat: suggest enabling thread pool for servers with max_connections >= 512 (issue #404) +- fix: hide ThreadPool metrics when thread pool is not enabled to avoid noise (issue #404) +- feat: add logical_cpu_cores function to accurately detect threads including HT +- chore: bump version to 2.8.22 + +2.8.21 2026-01-18 + +- fix: remove contradictory query_cache_limit recommendation when disabling query cache (issue #671) +- fix: cap join_buffer_size recommendation at 4MB and prefer index optimization (issue #671) +- chore: bump version to 2.8.21 + +2.8.20 2026-01-18 + +- feat: add automated regression test for forcemem MB interpretation (issues #780, #810) +- chore: bump version to 2.8.20 + +2.8.18 2026-01-18 + +- feat: add --max-password-checks option to limit dictionary checks (default: 100) +- fix: ensure Machine type is reported as 'Container' when --container option is used +- chore: bump version to 2.8.18 + +2.8.17 2026-01-18 + +- feat: implementation of issue #403 to check weak passwords on MySQL 8.0+ and flush hosts every 100 attempts +- chore: bump version to 2.8.17 + +2.8.16 2026-01-18 + +- chore: bump version to 2.8.16 + +2.8.15 2026-01-18 + +- feat: update all GitHub links from 'major' to 'jmrenouard' organization +- feat: refactor plugin information to filter ACTIVE status and display specific columns grouped by type +- chore: bump version to 2.8.15 + +2.8.13 2026-01-18 + +- docs: add Useful Links section to all README files (English, French, Russian, Italian) +- chore: bump version to 2.8.13 + +2.8.12 2026-01-17 + +- feat: update is_docker() to detect containerd and podman runtimes +- chore: bump version to 2.8.12 + +2.8.11 2026-01-17 + +- docs: update INTERNALS.md with information about Cloud, SSH, Containers, and Plugins +- chore: bump version to 2.8.11 + +2.8.10 2026-01-17 + +- feat: add dates and commands to log files in test_envs.sh +- feat: add separators (=) at the end of log files in test_envs.sh +- chore: synchronize version strings across script, POD, and version file + +2.8.9 2026-01-17 + +- feat: improve container log detection by excluding proxy containers (traefik, haproxy, maxscale, proxy) +- feat: prioritize database-related container names (mysql, mariadb, percona, db, database) +- chore: bump version to 2.8.9 + +2.8.8 2026-01-17 + +- feat: add -d/--database parameter to test_envs.sh to tune specific databases +- feat: add -c/--configs parameter to test_envs.sh for easier configuration selection +- feat: add timestamps to major steps in test_envs.sh logs +- feat: add execution header to test_envs.sh output showing the full command +- chore: bump version to 2.8.8 + +2.8.7 2026-01-17 + +- docs: add standardized comment headers to all build shell scripts +- chore: synchronize version strings across script, POD, and version file +- fix: ensure version consistency between Changelog and CURRENT_VERSION.txt + +2.8.6 2026-01-17 + +- feat: add Plugin Information section and --plugininfo flag (#794) +- fix: memory calculation bug in system_recommendations (1.5GB check) +- fix: ensure forcemem is correctly interpreted and displayed as MB in os_setup +- chore: synchronize version strings across script, POD, and version file + +2.8.5 2026-01-17 + +- fix: noisy sysctl errors for sunrpc parameters when kernel module is not loaded +- fix: refactor get_kernel_info to handle missing sysctl parameters gracefully + +2.8.4 2026-01-17 + +- fix: database injection failing to find dump files due to incorrect working directory +- fix: ensure correct path handling for 'source' commands in employees.sql + +2.8.3 2026-01-17 + +- feat: detect docker/podman environment and automatically grab logs from container if local log file is not found +- feat: add --container option to manually specify a container for log retrieval + +2.8.2 2026-01-17 + +- fix: system command failures (ping/ifconfig/redirection) on modern Linux (Ubuntu 22.04/WSL2) +- feat: integrate external test dependencies (multi-db-docker-env, test_db) and automated employees database injection + +2.8.1 2026-01-17 + +- fix: resilient memory checks with /proc fallback on Linux and silencing expected ps failures + +2.8.0 2026-01-17 + +- Bump version to 2.8.0 +- enhance user hostname restriction checks +- feat: Translate comments and messages in updateCVElist.py to English +- chore: ignore VS Code workspace files +- build: update Debian File::Util dependency installation +- cleanup: MariaDB and MySQL support documentation (focus on LTS) +2.8.22 2026-01-18 + +- feat: update all repository links from 'major' to 'jmrenouard' (issue #410) +- docs: add Changelog information and Useful Links to all README files (issue #411) +- feat: improve thread_pool_size recommendations based on logical CPU count (issue #404) +- feat: suggest enabling thread pool for servers with max_connections >= 512 (issue #404) +- fix: hide ThreadPool metrics when thread pool is not enabled to avoid noise (issue #404) +- feat: add logical_cpu_cores function to accurately detect threads including HT +- chore: bump version to 2.8.22 + +2.8.21 2026-01-18 + +- fix: remove contradictory query_cache_limit recommendation when disabling query cache (issue #671) +- fix: cap join_buffer_size recommendation at 4MB and prefer index optimization (issue #671) +- chore: bump version to 2.8.21 + +2.8.20 2026-01-18 + +- feat: add automated regression test for forcemem MB interpretation (issues #780, #810) +- chore: bump version to 2.8.20 + +2.8.18 2026-01-18 + +- feat: add --max-password-checks option to limit dictionary checks (default: 100) +- fix: ensure Machine type is reported as 'Container' when --container option is used +- chore: bump version to 2.8.18 + +2.8.17 2026-01-18 + +- feat: implementation of issue #403 to check weak passwords on MySQL 8.0+ and flush hosts every 100 attempts +- chore: bump version to 2.8.17 + +2.8.16 2026-01-18 + +- chore: bump version to 2.8.16 + +2.8.15 2026-01-18 + +- feat: update all GitHub links from 'major' to 'jmrenouard' organization +- feat: refactor plugin information to filter ACTIVE status and display specific columns grouped by type +- chore: bump version to 2.8.15 + +2.8.13 2026-01-18 + +- docs: add Useful Links section to all README files (English, French, Russian, Italian) +- chore: bump version to 2.8.13 + +2.8.12 2026-01-17 + +- feat: update is_docker() to detect containerd and podman runtimes +- chore: bump version to 2.8.12 + +2.8.11 2026-01-17 + +- docs: update INTERNALS.md with information about Cloud, SSH, Containers, and Plugins +- chore: bump version to 2.8.11 + +2.8.10 2026-01-17 + +- feat: add dates and commands to log files in test_envs.sh +- feat: add separators (=) at the end of log files in test_envs.sh +- chore: synchronize version strings across script, POD, and version file + +2.8.9 2026-01-17 + +- feat: improve container log detection by excluding proxy containers (traefik, haproxy, maxscale, proxy) +- feat: prioritize database-related container names (mysql, mariadb, percona, db, database) +- chore: bump version to 2.8.9 + +2.8.8 2026-01-17 + +- feat: add -d/--database parameter to test_envs.sh to tune specific databases +- feat: add -c/--configs parameter to test_envs.sh for easier configuration selection +- feat: add timestamps to major steps in test_envs.sh logs +- feat: add execution header to test_envs.sh output showing the full command +- chore: bump version to 2.8.8 + +2.8.7 2026-01-17 + +- docs: add standardized comment headers to all build shell scripts +- chore: synchronize version strings across script, POD, and version file +- fix: ensure version consistency between Changelog and CURRENT_VERSION.txt + +2.8.6 2026-01-17 + +- feat: add Plugin Information section and --plugininfo flag (#794) +- fix: memory calculation bug in system_recommendations (1.5GB check) +- fix: ensure forcemem is correctly interpreted and displayed as MB in os_setup +- chore: synchronize version strings across script, POD, and version file + +2.8.5 2026-01-17 + +- fix: noisy sysctl errors for sunrpc parameters when kernel module is not loaded +- fix: refactor get_kernel_info to handle missing sysctl parameters gracefully + +2.8.4 2026-01-17 + +- fix: database injection failing to find dump files due to incorrect working directory +- fix: ensure correct path handling for 'source' commands in employees.sql + +2.8.3 2026-01-17 + +- feat: detect docker/podman environment and automatically grab logs from container if local log file is not found +- feat: add --container option to manually specify a container for log retrieval + +2.8.2 2026-01-17 + +- fix: system command failures (ping/ifconfig/redirection) on modern Linux (Ubuntu 22.04/WSL2) +- feat: integrate external test dependencies (multi-db-docker-env, test_db) and automated employees database injection + +2.8.1 2026-01-17 + +- fix: resilient memory checks with /proc fallback on Linux and silencing expected ps failures + +2.8.0 2026-01-17 + +- Bump version to 2.8.0 +- enhance user hostname restriction checks +- feat: Translate comments and messages in updateCVElist.py to English +- chore: ignore VS Code workspace files +- build: update Debian File::Util dependency installation +- cleanup: MariaDB and MySQL support documentation (focus on LTS)