-
Couldn't load subscription status.
- Fork 11.6k
Description
Laravel Version
11.20.0
PHP Version
8.2.12
Database Driver & Version
MariaDB 10.6.16
Description
I noticed that the execution of
php artisan schema:dumpcan potentially run into two infinite recursive loop here:
framework/src/Illuminate/Database/Schema/MySqlSchemaState.php
Lines 155 to 165 in e1a9c5d
| if (Str::contains($e->getMessage(), ['column-statistics', 'column_statistics'])) { | |
| return $this->executeDumpProcess(Process::fromShellCommandLine( | |
| str_replace(' --column-statistics=0', '', $process->getCommandLine()) | |
| ), $output, $variables); | |
| } | |
| if (str_contains($e->getMessage(), 'set-gtid-purged')) { | |
| return $this->executeDumpProcess(Process::fromShellCommandLine( | |
| str_replace(' --set-gtid-purged=OFF', '', $process->getCommandLine()) | |
| ), $output, $variables); | |
| } |
There's even a comment on StackOverflow, where a user ran into exactly this issue:
https://stackoverflow.com/questions/59410746/getting-mysqldump-error-unknown-variable-column-statistics-0-when-exporting#comment136792230_59442494
I am fine with recursion in general, but there needs to be some kind of fail-safe to catch infinit loops here, e.g. a max retry count. We can't rely on consistent output of mysqldump here.
Steps To Reproduce
TLDR:
- Run
composer create-project laravel/laravel column-statistics - Setup MySQL/MariaDB database connection
- Set
DB_USERNAMEto a user that does not have theLOCK TABLESpermission - Run
php artisan schema:dump
Output:
> php artisan schema:dump
mysqldump: unknown variable 'column-statistics=0'
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
# ...Detailed Explanation:
There are for sure multiple ways of triggering an infinite recursion here, but the simplest way, that I have found, is to have the word column-statistics somewhere in the path of your working directory. Now, if any error is reported by mysqldump, it will result in an infinite loop, since the working directory is part of the error output that is being parsed here:
| if (Str::contains($e->getMessage(), ['column-statistics', 'column_statistics'])) { |
In my case $e->getMessage() looked like this:
The command "mysqldump --user="${:LARAVEL_LOAD_USER}" --password="${:LARAVEL_LOAD_PASSWORD}" --host="${:LARAVEL_LOAD_HOST}" --port="${:LARAVEL_LOAD_PORT}" --no-tablespaces --skip-add-locks --skip-comments --skip-set-charset --tz-utc "${:LARAVEL_LOAD_DATABASE}" --routines --result-file="${:LARAVEL_LOAD_PATH}" --no-data" failed.
Exit Code: 2(Misuse of shell builtins)
Working directory: C:\xampp\htdocs\column-statistics
Output:
================
Error Output:
================
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES