From 038c59b1bf7cddd3634a665c864de976ba1eecf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Thu, 19 Dec 2024 16:26:36 -0300 Subject: [PATCH] Remove some sql_* global variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MaurĂ­cio Meneghini Fauth --- phpstan-baseline.neon | 32 +-- psalm-baseline.xml | 60 ++--- psalm.xml | 9 - src/Controllers/Export/ExportController.php | 40 --- src/Export/Export.php | 14 +- src/Plugins/Export/ExportSql.php | 235 +++++++++++------- .../Export/ExportControllerTest.php | 2 + tests/unit/Export/ExportTest.php | 1 - tests/unit/Plugins/Export/ExportSqlTest.php | 101 ++++---- tests/unit/Table/TableTest.php | 3 - 10 files changed, 230 insertions(+), 267 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 2dce99a5dd..b74c9114f5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -12435,12 +12435,6 @@ parameters: count: 1 path: src/Plugins/Export/ExportPhparray.php - - - message: '#^Binary operation "\." between ''SET SQL_MODE\="'' and mixed results in an error\.$#' - identifier: binaryOp.invalid - count: 1 - path: src/Plugins/Export/ExportSql.php - - message: '#^Binary operation "\." between ''SET time_zone \= "'' and mixed results in an error\.$#' identifier: binaryOp.invalid @@ -12570,7 +12564,7 @@ parameters: - message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#' identifier: empty.notAllowed - count: 41 + count: 34 path: src/Plugins/Export/ExportSql.php - @@ -12639,18 +12633,6 @@ parameters: count: 5 path: src/Plugins/Export/ExportSql.php - - - message: '#^Parameter \#2 \$compat of method PhpMyAdmin\\Plugins\\Export\\ExportSql\:\:exportUseStatement\(\) expects string, mixed given\.$#' - identifier: argument.type - count: 2 - path: src/Plugins/Export/ExportSql.php - - - - message: '#^Parameter \#2 \$compatibility of static method PhpMyAdmin\\Util\:\:backquoteCompat\(\) expects string, mixed given\.$#' - identifier: argument.type - count: 13 - path: src/Plugins/Export/ExportSql.php - - message: '#^Parameter \#2 \$haystack of function in_array expects array, mixed given\.$#' identifier: argument.type @@ -12669,12 +12651,6 @@ parameters: count: 2 path: src/Plugins/Export/ExportSql.php - - - message: '#^Parameter \#2 \$string of function explode expects string, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Plugins/Export/ExportSql.php - - message: '#^Parameter \#3 \$name of static method PhpMyAdmin\\Database\\Events\:\:getDefinition\(\) expects string, mixed given\.$#' identifier: argument.type @@ -12699,12 +12675,6 @@ parameters: count: 3 path: src/Plugins/Export/ExportSql.php - - - message: '#^Parameter \#5 \$compat of method PhpMyAdmin\\Plugins\\Export\\ExportSql\:\:generateComment\(\) expects string, mixed given\.$#' - identifier: argument.type - count: 3 - path: src/Plugins/Export/ExportSql.php - - message: '#^Property PhpMyAdmin\\SqlParser\\Components\\CreateDefinition\:\:\$name \(string\|null\) does not accept mixed\.$#' identifier: assign.propertyType diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 38e16b2856..968ba1e2a1 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1459,16 +1459,9 @@ - - - - - - - @@ -1476,11 +1469,8 @@ - - - @@ -4876,17 +4866,10 @@ - - - - - - - @@ -7192,22 +7175,21 @@ - - - - - - - - + + + + + + + + + - - @@ -7216,7 +7198,6 @@ - @@ -7239,7 +7220,7 @@ - + @@ -7253,6 +7234,7 @@ + name->database]]> name->table]]> table->table]]> @@ -7300,15 +7282,19 @@ + + + + - - - + + + collation)]]> selectedServer['port'])]]> @@ -7321,9 +7307,6 @@ - - - @@ -13135,11 +13118,15 @@ + + selectedServer]]> + + @@ -13450,9 +13437,6 @@ - - - diff --git a/psalm.xml b/psalm.xml index 6c7ee1fb66..996aa0e552 100644 --- a/psalm.xml +++ b/psalm.xml @@ -84,15 +84,6 @@ save_on_server: bool, SESSION_KEY: string, showtable: array<string, string|null>, - sql_compatibility: 'NONE'|'ANSI'|'DB2'|'MAXDB'|'MYSQL323'|'MYSQL40'|'MSSQL'|'ORACLE'|'TRADITIONAL', - sql_constraints: string, - sql_constraints_query: string, - sql_drop_foreign_keys: string, - sql_if_not_exists: bool, - sql_ignore: bool, - sql_insert_syntax: 'complete'|'extended'|'both'|'none', - sql_max_query_size: 0|positive-int, - sql_type: 'INSERT'|'UPDATE'|'REPLACE', tbl_storage_engine: string, token_mismatch: bool, token_provided: bool, diff --git a/src/Controllers/Export/ExportController.php b/src/Controllers/Export/ExportController.php index 8d79d4678a..c2d0a0650a 100644 --- a/src/Controllers/Export/ExportController.php +++ b/src/Controllers/Export/ExportController.php @@ -510,42 +510,6 @@ final class ExportController implements InvocableController $GLOBALS['excel_edition'] = $postParams['excel_edition']; } - if (isset($postParams['sql_header_comment'])) { - $GLOBALS['sql_header_comment'] = $postParams['sql_header_comment']; - } - - if (isset($postParams['sql_use_transaction'])) { - $GLOBALS['sql_use_transaction'] = $postParams['sql_use_transaction']; - } - - if (isset($postParams['sql_disable_fk'])) { - $GLOBALS['sql_disable_fk'] = $postParams['sql_disable_fk']; - } - - if (isset($postParams['sql_compatibility'])) { - $GLOBALS['sql_compatibility'] = $postParams['sql_compatibility']; - } - - if (isset($postParams['sql_create_database'])) { - $GLOBALS['sql_create_database'] = $postParams['sql_create_database']; - } - - if (isset($postParams['sql_drop_table'])) { - $GLOBALS['sql_drop_table'] = $postParams['sql_drop_table']; - } - - if (isset($postParams['sql_procedure_function'])) { - $GLOBALS['sql_procedure_function'] = $postParams['sql_procedure_function']; - } - - if (isset($postParams['sql_create_table'])) { - $GLOBALS['sql_create_table'] = $postParams['sql_create_table']; - } - - if (isset($postParams['sql_create_view'])) { - $GLOBALS['sql_create_view'] = $postParams['sql_create_view']; - } - if (isset($postParams['sql_create_trigger'])) { $GLOBALS['sql_create_trigger'] = $postParams['sql_create_trigger']; } @@ -582,10 +546,6 @@ final class ExportController implements InvocableController $GLOBALS['sql_ignore'] = $postParams['sql_ignore']; } - if (isset($postParams['sql_type'])) { - $GLOBALS['sql_type'] = $postParams['sql_type']; - } - if (isset($postParams['sql_insert_syntax'])) { $GLOBALS['sql_insert_syntax'] = $postParams['sql_insert_syntax']; } diff --git a/src/Export/Export.php b/src/Export/Export.php index 5ae2a01cc1..a65d5ec325 100644 --- a/src/Export/Export.php +++ b/src/Export/Export.php @@ -574,7 +574,7 @@ class Export if ( $exportPlugin instanceof ExportSql && $structureOrData !== StructureOrData::Data - && isset($GLOBALS['sql_procedure_function']) + && $exportPlugin->hasCreateProcedureFunction() ) { $exportPlugin->exportRoutines($db->getName(), $aliases); @@ -607,12 +607,12 @@ class Export if ($isView) { if ( $separateFiles === '' - && isset($GLOBALS['sql_create_view']) + && $exportPlugin instanceof ExportSql && $exportPlugin->hasCreateView() && ! $exportPlugin->exportStructure($db->getName(), $table, 'stand_in', $aliases) ) { break; } - } elseif (isset($GLOBALS['sql_create_table'])) { + } elseif ($exportPlugin instanceof ExportSql && $exportPlugin->hasCreateTable()) { $tableSize = $GLOBALS['maxsize']; // Checking if the maximum table size constrain has been set // And if that constrain is a valid number or not @@ -677,7 +677,7 @@ class Export $this->saveObjectInBuffer('table_' . $table, true); } - if (isset($GLOBALS['sql_create_view'])) { + if ($exportPlugin instanceof ExportSql && $exportPlugin->hasCreateView()) { foreach ($views as $view) { // no data export for a view if ($structureOrData === StructureOrData::Data) { @@ -719,7 +719,7 @@ class Export if ( ! ($exportPlugin instanceof ExportSql) || $structureOrData === StructureOrData::Data - || ! isset($GLOBALS['sql_procedure_function']) + || ! $exportPlugin->hasCreateProcedureFunction() ) { return; } @@ -798,12 +798,12 @@ class Export $isView = $tableObject->isView(); if ($structureOrData !== StructureOrData::Data) { if ($isView) { - if (isset($GLOBALS['sql_create_view'])) { + if ($exportPlugin instanceof ExportSql && $exportPlugin->hasCreateView()) { if (! $exportPlugin->exportStructure($db, $table, 'create_view', $aliases)) { return; } } - } elseif (isset($GLOBALS['sql_create_table'])) { + } elseif ($exportPlugin instanceof ExportSql && $exportPlugin->hasCreateTable()) { if (! $exportPlugin->exportStructure($db, $table, 'create_table', $aliases)) { return; } diff --git a/src/Plugins/Export/ExportSql.php b/src/Plugins/Export/ExportSql.php index 613bf0fc47..173ca1b0f0 100644 --- a/src/Plugins/Export/ExportSql.php +++ b/src/Plugins/Export/ExportSql.php @@ -48,6 +48,7 @@ use function explode; use function implode; use function in_array; use function is_array; +use function is_string; use function mb_strlen; use function mb_strpos; use function mb_substr; @@ -74,23 +75,32 @@ class ExportSql extends ExportPlugin */ private bool $sentCharset = false; - private bool $useSqlBackquotes = false; - - private string $sqlViews = ''; - - public string|null $sqlAutoIncrements = null; - public string|null $sqlIndexes = null; - public string|null $sqlConstraints = null; - - public string $sqlConstraintsQuery = ''; - - private bool $doRelation = false; - - private bool $doMime = false; - - private bool $doDates = false; - private bool $doComments = false; + private bool $doDates = false; + private bool $doMime = false; + private bool $doRelation = false; + private string $headerComment = ''; + public string|null $sqlAutoIncrements = null; + public string|null $sqlConstraints = null; + public string $sqlConstraintsQuery = ''; + public string|null $sqlIndexes = null; + private string $sqlViews = ''; + private bool $useSqlBackquotes = false; + private bool $useTransaction = false; + private bool $disableForeignKey = false; + + /** @var 'NONE'|'ANSI'|'DB2'|'MAXDB'|'MYSQL323'|'MYSQL40'|'MSSQL'|'ORACLE'|'TRADITIONAL' */ + private string $compatibility = 'NONE'; + + private bool $createDatabase = false; + private bool $dropTable = false; + private bool $procedureFunction = false; + private bool $createTable = false; + + /** @var 'INSERT'|'UPDATE'|'REPLACE' */ + private string $type = 'INSERT'; + + private bool $createView = false; /** @psalm-return non-empty-lowercase-string */ public function getName(): string @@ -521,7 +531,7 @@ class ExportSql extends ExportPlugin $procQuery = ''; foreach ($routines as $routine) { - if (! empty($GLOBALS['sql_drop_table'])) { + if ($this->dropTable) { $procQuery .= 'DROP ' . $type . ' IF EXISTS ' . Util::backquote($routine) . $delimiter . "\n"; @@ -672,11 +682,11 @@ class ExportSql extends ExportPlugin { $foot = ''; - if (isset($GLOBALS['sql_disable_fk'])) { + if ($this->disableForeignKey) { $foot .= 'SET FOREIGN_KEY_CHECKS=1;' . "\n"; } - if (isset($GLOBALS['sql_use_transaction'])) { + if ($this->useTransaction) { $foot .= 'COMMIT;' . "\n"; } @@ -707,15 +717,8 @@ class ExportSql extends ExportPlugin public function exportHeader(): bool { $dbi = DatabaseInterface::getInstance(); - if (isset($GLOBALS['sql_compatibility'])) { - $tmpCompat = $GLOBALS['sql_compatibility']; - if ($tmpCompat === 'NONE') { - $tmpCompat = ''; - } - $dbi->tryQuery('SET SQL_MODE="' . $tmpCompat . '"'); - unset($tmpCompat); - } + $dbi->tryQuery('SET SQL_MODE="' . ($this->compatibility !== 'NONE' ? $this->compatibility : '') . '"'); $head = $this->exportComment('phpMyAdmin SQL Dump') . $this->exportComment('version ' . Version::VERSION) @@ -738,10 +741,10 @@ class ExportSql extends ExportPlugin . $this->exportComment(__('PHP Version:') . ' ' . PHP_VERSION) . $this->possibleCRLF(); - if (! empty($GLOBALS['sql_header_comment'])) { + if ($this->headerComment !== '') { // '\n' is not a newline (like "\n" would be), it's the characters // backslash and n, as explained on the export interface - $lines = explode('\n', $GLOBALS['sql_header_comment']); + $lines = explode('\n', $this->headerComment); $head .= $this->exportComment(); foreach ($lines as $oneLine) { $head .= $this->exportComment($oneLine); @@ -750,17 +753,17 @@ class ExportSql extends ExportPlugin $head .= $this->exportComment(); } - if (isset($GLOBALS['sql_disable_fk'])) { + if ($this->disableForeignKey) { $head .= 'SET FOREIGN_KEY_CHECKS=0;' . "\n"; } // We want exported AUTO_INCREMENT columns to have still same value, // do this only for recent MySQL exports - if (! isset($GLOBALS['sql_compatibility']) || $GLOBALS['sql_compatibility'] === 'NONE') { + if ($this->compatibility === 'NONE') { $head .= 'SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";' . "\n"; } - if (isset($GLOBALS['sql_use_transaction'])) { + if ($this->useTransaction) { $head .= 'START TRANSACTION;' . "\n"; } @@ -816,15 +819,13 @@ class ExportSql extends ExportPlugin $dbAlias = $db; } - $compat = $GLOBALS['sql_compatibility'] ?? 'NONE'; - if ($this->structureOrData !== StructureOrData::Data && isset($GLOBALS['sql_drop_database'])) { if ( ! $this->export->outputHandler( 'DROP DATABASE IF EXISTS ' . Util::backquoteCompat( $dbAlias, - $compat, + $this->compatibility, $this->useSqlBackquotes, ) . ';' . "\n", @@ -834,12 +835,12 @@ class ExportSql extends ExportPlugin } } - if (ExportPlugin::$exportType === ExportType::Database && ! isset($GLOBALS['sql_create_database'])) { + if (ExportPlugin::$exportType === ExportType::Database && ! $this->createDatabase) { return true; } $createQuery = 'CREATE DATABASE IF NOT EXISTS ' - . Util::backquoteCompat($dbAlias, $compat, $this->useSqlBackquotes); + . Util::backquoteCompat($dbAlias, $this->compatibility, $this->useSqlBackquotes); $collation = DatabaseInterface::getInstance()->getDbCollation($db); if (str_contains($collation, '_')) { $createQuery .= ' DEFAULT CHARACTER SET ' @@ -858,7 +859,7 @@ class ExportSql extends ExportPlugin return false; } - return $this->exportUseStatement($dbAlias, $compat); + return $this->exportUseStatement($dbAlias, $this->compatibility); } /** @@ -896,14 +897,12 @@ class ExportSql extends ExportPlugin $dbAlias = $db; } - $compat = $GLOBALS['sql_compatibility'] ?? 'NONE'; - $head = $this->exportComment() . $this->exportComment( __('Database:') . ' ' . Util::backquoteCompat( $dbAlias, - $compat, + $this->compatibility, $this->useSqlBackquotes, ), ) @@ -973,7 +972,7 @@ class ExportSql extends ExportPlugin . $this->exportComment(); foreach ($eventNames as $eventName) { - if (! empty($GLOBALS['sql_drop_table'])) { + if ($this->dropTable) { $text .= 'DROP EVENT IF EXISTS ' . Util::backquote($eventName) . $delimiter . "\n"; @@ -1031,7 +1030,7 @@ class ExportSql extends ExportPlugin return false; } - if (! $this->exportUseStatement((string) $relationParameters->db, $GLOBALS['sql_compatibility'])) { + if (! $this->exportUseStatement((string) $relationParameters->db, $this->compatibility)) { return false; } @@ -1225,7 +1224,7 @@ class ExportSql extends ExportPlugin $viewAlias = $view; $this->initAlias($aliases, $dbAlias, $viewAlias); $createQuery = ''; - if (! empty($GLOBALS['sql_drop_table'])) { + if ($this->dropTable) { $createQuery .= 'DROP VIEW IF EXISTS ' . Util::backquote($viewAlias) . ';' . "\n"; @@ -1317,9 +1316,7 @@ class ExportSql extends ExportPlugin $createQuery .= "\n" . ');' . "\n"; - $compat = $GLOBALS['sql_compatibility'] ?? 'NONE'; - - if ($compat === 'MSSQL') { + if ($this->compatibility === 'MSSQL') { return $this->makeCreateTableMSSQLCompatible($createQuery); } @@ -1348,7 +1345,6 @@ class ExportSql extends ExportPlugin bool $updateIndexesIncrements = true, array $aliases = [], ): string { - $GLOBALS['sql_drop_table'] ??= null; $GLOBALS['sql_indexes_query'] ??= null; $GLOBALS['sql_drop_foreign_keys'] ??= null; @@ -1356,19 +1352,17 @@ class ExportSql extends ExportPlugin $tableAlias = $table; $this->initAlias($aliases, $dbAlias, $tableAlias); - $compat = $GLOBALS['sql_compatibility'] ?? 'NONE'; - $schemaCreate = $this->getTableStatus($db, $table); $dbi = DatabaseInterface::getInstance(); - if (! empty($GLOBALS['sql_drop_table']) && $dbi->getTable($db, $table)->isView()) { + if ($this->dropTable && $dbi->getTable($db, $table)->isView()) { $schemaCreate .= 'DROP VIEW IF EXISTS ' . Util::backquoteCompat($tableAlias, 'NONE', $this->useSqlBackquotes) . ';' . "\n"; } // no need to generate a DROP VIEW here, it was done earlier - if (! empty($GLOBALS['sql_drop_table']) && ! $dbi->getTable($db, $table)->isView()) { + if ($this->dropTable && ! $dbi->getTable($db, $table)->isView()) { $schemaCreate .= 'DROP TABLE IF EXISTS ' . Util::backquoteCompat($tableAlias, 'NONE', $this->useSqlBackquotes) . ';' . "\n"; @@ -1499,7 +1493,7 @@ class ExportSql extends ExportPlugin } // Making the query MSSQL compatible. - if ($compat === 'MSSQL') { + if ($this->compatibility === 'MSSQL') { $createQuery = $this->makeCreateTableMSSQLCompatible($createQuery); } @@ -1513,7 +1507,7 @@ class ExportSql extends ExportPlugin } // Using appropriate quotes. - if ($compat === 'MSSQL') { + if ($this->compatibility === 'MSSQL') { Context::setMode(Context::getMode() | Context::SQL_MODE_ANSI_QUOTES); } } @@ -1616,7 +1610,11 @@ class ExportSql extends ExportPlugin /** * The header of the `ALTER` statement (`ALTER TABLE tbl`). */ - $alterHeader = 'ALTER TABLE ' . Util::backquoteCompat($tableAlias, $compat, $this->useSqlBackquotes); + $alterHeader = 'ALTER TABLE ' . Util::backquoteCompat( + $tableAlias, + $this->compatibility, + $this->useSqlBackquotes, + ); /** * The footer of the `ALTER` statement (usually ';') @@ -1634,7 +1632,7 @@ class ExportSql extends ExportPlugin __('Constraints for dumped tables'), __('Constraints for table'), $tableAlias, - $compat, + $this->compatibility, ) . $this->sqlConstraintsQuery; } @@ -1662,7 +1660,7 @@ class ExportSql extends ExportPlugin __('Indexes for dumped tables'), __('Indexes for table'), $tableAlias, - $compat, + $this->compatibility, ) . $GLOBALS['sql_indexes_query']; } @@ -1693,7 +1691,7 @@ class ExportSql extends ExportPlugin __('AUTO_INCREMENT for dumped tables'), __('AUTO_INCREMENT for table'), $tableAlias, - $compat, + $this->compatibility, ) . $sqlAutoIncrementsQuery; } @@ -1877,9 +1875,7 @@ class ExportSql extends ExportPlugin $dbAlias = $db; $tableAlias = $table; $this->initAlias($aliases, $dbAlias, $tableAlias); - $compat = $GLOBALS['sql_compatibility'] ?? 'NONE'; - - $formattedTableName = Util::backquoteCompat($tableAlias, $compat, $this->useSqlBackquotes); + $formattedTableName = Util::backquoteCompat($tableAlias, $this->compatibility, $this->useSqlBackquotes); $dump = $this->possibleCRLF() . $this->exportComment(str_repeat('-', 56)) . $this->possibleCRLF() @@ -1908,7 +1904,7 @@ class ExportSql extends ExportPlugin $usedAlias = false; $triggerQuery = ''; foreach ($triggers as $trigger) { - if (! empty($GLOBALS['sql_drop_table'])) { + if ($this->dropTable) { $triggerQuery .= $trigger->getDropSql() . ';' . "\n"; } @@ -2025,9 +2021,7 @@ class ExportSql extends ExportPlugin $tableAlias = $table; $this->initAlias($aliases, $dbAlias, $tableAlias); - $compat = $GLOBALS['sql_compatibility'] ?? 'NONE'; - - $formattedTableName = Util::backquoteCompat($tableAlias, $compat, $this->useSqlBackquotes); + $formattedTableName = Util::backquoteCompat($tableAlias, $this->compatibility, $this->useSqlBackquotes); // Do not export data for a VIEW, unless asked to export the view as a table // (For a VIEW, this is called only when exporting a single VIEW) @@ -2074,10 +2068,10 @@ class ExportSql extends ExportPlugin $colAs = $aliases[$db]['tables'][$table]['columns'][$colAs]; } - $fieldSet[$j] = Util::backquoteCompat($colAs, $compat, $this->useSqlBackquotes); + $fieldSet[$j] = Util::backquoteCompat($colAs, $this->compatibility, $this->useSqlBackquotes); } - if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] === 'UPDATE') { + if ($this->type === 'UPDATE') { // update $schemaInsert = 'UPDATE '; if (isset($GLOBALS['sql_ignore'])) { @@ -2085,10 +2079,10 @@ class ExportSql extends ExportPlugin } // avoid EOL blank - $schemaInsert .= Util::backquoteCompat($tableAlias, $compat, $this->useSqlBackquotes) . ' SET'; + $schemaInsert .= Util::backquoteCompat($tableAlias, $this->compatibility, $this->useSqlBackquotes) . ' SET'; } else { // insert or replace - if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] === 'REPLACE') { + if ($this->type === 'REPLACE') { $sqlCommand = 'REPLACE'; } else { $sqlCommand = 'INSERT'; @@ -2102,14 +2096,14 @@ class ExportSql extends ExportPlugin } // insert ignore? - if (isset($GLOBALS['sql_type'], $GLOBALS['sql_ignore']) && $GLOBALS['sql_type'] === 'INSERT') { + if (isset($GLOBALS['sql_ignore']) && $this->type === 'INSERT') { $insertDelayed .= ' IGNORE'; } //truncate table before insert if (isset($GLOBALS['sql_truncate']) && $GLOBALS['sql_truncate'] && $sqlCommand === 'INSERT') { $truncate = 'TRUNCATE TABLE ' - . Util::backquoteCompat($tableAlias, $compat, $this->useSqlBackquotes) . ';'; + . Util::backquoteCompat($tableAlias, $this->compatibility, $this->useSqlBackquotes) . ';'; $truncatehead = $this->possibleCRLF() . $this->exportComment() . $this->exportComment( @@ -2126,11 +2120,11 @@ class ExportSql extends ExportPlugin if ($GLOBALS['sql_insert_syntax'] === 'complete' || $GLOBALS['sql_insert_syntax'] === 'both') { $fields = implode(', ', $fieldSet); $schemaInsert = $sqlCommand . $insertDelayed . ' INTO ' - . Util::backquoteCompat($tableAlias, $compat, $this->useSqlBackquotes) + . Util::backquoteCompat($tableAlias, $this->compatibility, $this->useSqlBackquotes) . ' (' . $fields . ') VALUES'; // avoid EOL blank } else { $schemaInsert = $sqlCommand . $insertDelayed . ' INTO ' - . Util::backquoteCompat($tableAlias, $compat, $this->useSqlBackquotes) + . Util::backquoteCompat($tableAlias, $this->compatibility, $this->useSqlBackquotes) . ' VALUES'; } } @@ -2141,8 +2135,7 @@ class ExportSql extends ExportPlugin if ( ($GLOBALS['sql_insert_syntax'] === 'extended' || $GLOBALS['sql_insert_syntax'] === 'both') - && (! isset($GLOBALS['sql_type']) - || $GLOBALS['sql_type'] !== 'UPDATE') + && $this->type !== 'UPDATE' ) { $separator = ','; $schemaInsert .= "\n"; @@ -2166,17 +2159,13 @@ class ExportSql extends ExportPlugin } // We need to SET IDENTITY_INSERT ON for MSSQL - if ( - $currentRow === 0 - && isset($GLOBALS['sql_compatibility']) - && $GLOBALS['sql_compatibility'] === 'MSSQL' - ) { + if ($currentRow === 0 && $this->compatibility === 'MSSQL') { if ( ! $this->export->outputHandler( 'SET IDENTITY_INSERT ' . Util::backquoteCompat( $tableAlias, - $compat, + $this->compatibility, $this->useSqlBackquotes, ) . ' ON ;' . "\n", @@ -2229,7 +2218,7 @@ class ExportSql extends ExportPlugin } // should we make update? - if (isset($GLOBALS['sql_type']) && $GLOBALS['sql_type'] === 'UPDATE') { + if ($this->type === 'UPDATE') { $insertLine = $schemaInsert; /** @infection-ignore-all */ for ($i = 0; $i < $fieldsCnt; $i++) { @@ -2284,16 +2273,12 @@ class ExportSql extends ExportPlugin } // We need to SET IDENTITY_INSERT OFF for MSSQL - if ( - isset($GLOBALS['sql_compatibility']) - && $GLOBALS['sql_compatibility'] === 'MSSQL' - && $currentRow > 0 - ) { + if ($this->compatibility === 'MSSQL' && $currentRow > 0) { $outputSucceeded = $this->export->outputHandler( "\n" . 'SET IDENTITY_INSERT ' . Util::backquoteCompat( $tableAlias, - $compat, + $this->compatibility, $this->useSqlBackquotes, ) . ' OFF;' . "\n", @@ -2703,5 +2688,79 @@ class ExportSql extends ExportPlugin $this->doDates = (bool) ($request->getParsedBodyParam('sql_dates') ?? $exportConfig['sql_dates'] ?? false); $this->doComments = (bool) ($request->getParsedBodyParam('sql_include_comments') ?? $exportConfig['sql_include_comments'] ?? false); + $this->headerComment = $this->setStringValue( + $request->getParsedBodyParam('sql_header_comment'), + $exportConfig['sql_header_comment'] ?? null, + ); + $this->useTransaction = (bool) ($request->getParsedBodyParam('sql_use_transaction') + ?? $exportConfig['sql_use_transaction'] ?? false); + $this->disableForeignKey = (bool) ($request->getParsedBodyParam('sql_disable_fk') + ?? $exportConfig['sql_disable_fk'] ?? false); + $this->compatibility = $this->setCompatibility($this->setStringValue( + $request->getParsedBodyParam('sql_compatibility'), + $exportConfig['sql_compatibility'] ?? null, + )); + $this->createDatabase = (bool) ($request->getParsedBodyParam('sql_create_database') + ?? $exportConfig['sql_create_database'] ?? false); + $this->dropTable = (bool) ($request->getParsedBodyParam('sql_drop_table') + ?? $exportConfig['sql_drop_table'] ?? false); + $this->procedureFunction = (bool) ($request->getParsedBodyParam('sql_procedure_function') + ?? $exportConfig['sql_procedure_function'] ?? false); + $this->createTable = (bool) ($request->getParsedBodyParam('sql_create_table') + ?? $exportConfig['sql_create_table'] ?? false); + $this->type = $this->setType($this->setStringValue( + $request->getParsedBodyParam('sql_type'), + $exportConfig['sql_type'] ?? null, + )); + $this->createView = (bool) ($request->getParsedBodyParam('sql_create_view') + ?? $exportConfig['sql_create_view'] ?? false); + } + + private function setStringValue(mixed $fromRequest, mixed $fromConfig): string + { + if (is_string($fromRequest) && $fromRequest !== '') { + return $fromRequest; + } + + if (is_string($fromConfig) && $fromConfig !== '') { + return $fromConfig; + } + + return ''; + } + + /** @return 'NONE'|'ANSI'|'DB2'|'MAXDB'|'MYSQL323'|'MYSQL40'|'MSSQL'|'ORACLE'|'TRADITIONAL' */ + private function setCompatibility(string $mode): string + { + if (in_array($mode, ['ANSI', 'DB2', 'MAXDB', 'MYSQL323', 'MYSQL40', 'MSSQL', 'ORACLE', 'TRADITIONAL'], true)) { + return $mode; + } + + return 'NONE'; + } + + public function hasCreateProcedureFunction(): bool + { + return $this->procedureFunction; + } + + public function hasCreateTable(): bool + { + return $this->createTable; + } + + /** @return 'INSERT'|'UPDATE'|'REPLACE' */ + private function setType(string $type): string + { + if (in_array($type, ['UPDATE', 'REPLACE'], true)) { + return $type; + } + + return 'INSERT'; + } + + public function hasCreateView(): bool + { + return $this->createView; } } diff --git a/tests/unit/Controllers/Export/ExportControllerTest.php b/tests/unit/Controllers/Export/ExportControllerTest.php index c0472740d7..929c44c006 100644 --- a/tests/unit/Controllers/Export/ExportControllerTest.php +++ b/tests/unit/Controllers/Export/ExportControllerTest.php @@ -51,6 +51,7 @@ final class ExportControllerTest extends AbstractTestCase $GLOBALS['lang'] = 'en'; $config = Config::getInstance(); $config->selectServer('1'); + $config->settings['Export']['sql_procedure_function'] = false; $dbiDummy->addResult( 'SELECT `SCHEMA_NAME` FROM `INFORMATION_SCHEMA`.`SCHEMATA`', @@ -211,6 +212,7 @@ final class ExportControllerTest extends AbstractTestCase $GLOBALS['lang'] = 'en'; $config = Config::getInstance(); $config->selectServer('1'); + $config->settings['Export']['sql_procedure_function'] = false; $dbiDummy->addResult( 'SELECT `SCHEMA_NAME` FROM `INFORMATION_SCHEMA`.`SCHEMATA`', diff --git a/tests/unit/Export/ExportTest.php b/tests/unit/Export/ExportTest.php index 44cff62567..a24e882c5c 100644 --- a/tests/unit/Export/ExportTest.php +++ b/tests/unit/Export/ExportTest.php @@ -98,7 +98,6 @@ class ExportTest extends AbstractTestCase public function testExportDatabase(): void { - $GLOBALS['sql_create_view'] = 'something'; $GLOBALS['output_kanji_conversion'] = false; $GLOBALS['buffer_needed'] = false; $GLOBALS['asfile'] = false; diff --git a/tests/unit/Plugins/Export/ExportSqlTest.php b/tests/unit/Plugins/Export/ExportSqlTest.php index 8d414b3ebd..7ce465e623 100644 --- a/tests/unit/Plugins/Export/ExportSqlTest.php +++ b/tests/unit/Plugins/Export/ExportSqlTest.php @@ -301,7 +301,10 @@ class ExportSqlTest extends AbstractTestCase public function testExportRoutines(): void { - $GLOBALS['sql_drop_table'] = true; + $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') + ->withParsedBody(['sql_drop_table' => 'On']); + + $this->object->setExportOptions($request, []); $this->expectOutputString( "\n" . 'DELIMITER $$' . "\n" . 'DROP PROCEDURE IF EXISTS `test_proc1`$$' . "\n" . 'CREATE PROCEDURE' @@ -382,8 +385,6 @@ class ExportSqlTest extends AbstractTestCase public function testExportFooter(): void { - $GLOBALS['sql_disable_fk'] = true; - $GLOBALS['sql_use_transaction'] = true; $GLOBALS['charset'] = 'utf-8'; $GLOBALS['sql_utc_time'] = true; $GLOBALS['old_tz'] = 'GMT'; @@ -400,6 +401,11 @@ class ExportSqlTest extends AbstractTestCase DatabaseInterface::$instance = $dbi; + $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') + ->withParsedBody(['sql_use_transaction' => 'On', 'sql_disable_fk' => 'On']); + + $this->object->setExportOptions($request, []); + $this->expectOutputString('SET FOREIGN_KEY_CHECKS=1;' . "\n" . 'COMMIT;' . "\n"); self::assertTrue( @@ -409,18 +415,13 @@ class ExportSqlTest extends AbstractTestCase public function testExportHeader(): void { - $GLOBALS['sql_compatibility'] = 'NONE'; $config = Config::getInstance(); $config->selectedServer['host'] = 'localhost'; $config->selectedServer['port'] = 80; - $GLOBALS['sql_disable_fk'] = true; - $GLOBALS['sql_use_transaction'] = true; $GLOBALS['sql_utc_time'] = true; $GLOBALS['old_tz'] = 'GMT'; $GLOBALS['asfile'] = 'yes'; $GLOBALS['output_charset_conversion'] = 'utf-8'; - $GLOBALS['sql_header_comment'] = "h1C\nh2C"; - $GLOBALS['sql_use_transaction'] = true; $GLOBALS['charset'] = 'utf-8'; $dbi = $this->getMockBuilder(DatabaseInterface::class) @@ -443,7 +444,12 @@ class ExportSqlTest extends AbstractTestCase DatabaseInterface::$instance = $dbi; $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') - ->withParsedBody(['sql_include_comments' => 'On']); + ->withParsedBody([ + 'sql_include_comments' => 'On', + 'sql_header_comment' => "h1C\nh2C", + 'sql_use_transaction' => 'On', + 'sql_disable_fk' => 'On', + ]); $this->object->setExportOptions($request, []); @@ -474,11 +480,7 @@ class ExportSqlTest extends AbstractTestCase public function testExportDBCreate(): void { - $GLOBALS['sql_compatibility'] = 'NONE'; $GLOBALS['sql_drop_database'] = true; - $GLOBALS['sql_create_database'] = true; - $GLOBALS['sql_create_table'] = true; - $GLOBALS['sql_create_view'] = true; $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() @@ -514,7 +516,6 @@ class ExportSqlTest extends AbstractTestCase self::assertStringContainsString('USE `db`;', $result); // case2: no backquotes - unset($GLOBALS['sql_compatibility']); Config::getInstance()->selectedServer['DisableIS'] = true; $dbi = $this->getMockBuilder(DatabaseInterface::class) @@ -550,10 +551,12 @@ class ExportSqlTest extends AbstractTestCase public function testExportDBHeader(): void { - $GLOBALS['sql_compatibility'] = 'MSSQL'; - $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') - ->withParsedBody(['sql_backquotes' => 'true', 'sql_include_comments' => 'On']); + ->withParsedBody([ + 'sql_backquotes' => 'true', + 'sql_include_comments' => 'On', + 'sql_compatibility' => 'MSSQL', + ]); $this->object->setExportOptions($request, []); @@ -568,8 +571,6 @@ class ExportSqlTest extends AbstractTestCase self::assertStringContainsString('"testDB"', $result); // case 2 - unset($GLOBALS['sql_compatibility']); - $this->object->useSqlBackquotes(false); ob_start(); @@ -585,8 +586,6 @@ class ExportSqlTest extends AbstractTestCase public function testExportEvents(): void { - $GLOBALS['sql_procedure_function'] = true; - $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); @@ -627,7 +626,6 @@ class ExportSqlTest extends AbstractTestCase public function testExportDBFooter(): void { $this->object->sqlConstraints = 'SqlConstraints'; - $GLOBALS['sql_procedure_function'] = true; $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() @@ -646,7 +644,6 @@ class ExportSqlTest extends AbstractTestCase public function testGetTableDefStandIn(): void { - $GLOBALS['sql_drop_table'] = true; $GLOBALS['sql_if_not_exists'] = true; $dbi = $this->getMockBuilder(DatabaseInterface::class) @@ -660,6 +657,11 @@ class ExportSqlTest extends AbstractTestCase DatabaseInterface::$instance = $dbi; + $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') + ->withParsedBody(['sql_drop_table' => 'On']); + + $this->object->setExportOptions($request, []); + $result = $this->object->getTableDefStandIn('db', 'view'); self::assertStringContainsString('DROP VIEW IF EXISTS `view`;', $result); @@ -672,7 +674,6 @@ class ExportSqlTest extends AbstractTestCase public function testGetTableDefForView(): void { - $GLOBALS['sql_drop_table'] = true; $GLOBALS['sql_if_not_exists'] = true; $dbi = $this->getMockBuilder(DatabaseInterface::class) @@ -699,7 +700,11 @@ class ExportSqlTest extends AbstractTestCase ]); DatabaseInterface::$instance = $dbi; - $GLOBALS['sql_compatibility'] = 'MSSQL'; + + $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') + ->withParsedBody(['sql_compatibility' => 'MSSQL']); + + $this->object->setExportOptions($request, []); $method = new ReflectionMethod(ExportSql::class, 'getTableDefForView'); $result = $method->invoke($this->object, 'db', 'view'); @@ -712,8 +717,6 @@ class ExportSqlTest extends AbstractTestCase ); // case 2 - unset($GLOBALS['sql_compatibility']); - $dbi = $this->getMockBuilder(DatabaseInterface::class) ->disableOriginalConstructor() ->getMock(); @@ -738,6 +741,11 @@ class ExportSqlTest extends AbstractTestCase ]); DatabaseInterface::$instance = $dbi; + $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') + ->withParsedBody([]); + + $this->object->setExportOptions($request, []); + $result = $method->invoke($this->object, 'db', 'view'); self::assertSame( @@ -750,9 +758,7 @@ class ExportSqlTest extends AbstractTestCase public function testGetTableDef(): void { - $GLOBALS['sql_compatibility'] = 'MSSQL'; $GLOBALS['sql_auto_increment'] = true; - $GLOBALS['sql_drop_table'] = true; $GLOBALS['sql_if_not_exists'] = true; $this->object->sqlConstraints = null; @@ -809,6 +815,8 @@ SQL; 'sql_backquotes' => 'true', 'sql_dates' => 'On', 'sql_include_comments' => 'On', + 'sql_compatibility' => 'MSSQL', + 'sql_drop_table' => 'On', ]); $this->object->setExportOptions($request, []); @@ -834,9 +842,7 @@ SQL; public function testGetTableDefWithError(): void { - $GLOBALS['sql_compatibility'] = ''; $GLOBALS['sql_auto_increment'] = true; - $GLOBALS['sql_drop_table'] = true; $GLOBALS['sql_if_not_exists'] = true; $this->object->sqlConstraints = null; @@ -859,7 +865,7 @@ SQL; Config::getInstance()->selectedServer['DisableIS'] = false; $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') - ->withParsedBody(['sql_include_comments' => 'On']); + ->withParsedBody(['sql_include_comments' => 'On', 'sql_drop_table' => 'On']); $this->object->setExportOptions($request, []); @@ -921,10 +927,12 @@ SQL; public function testExportStructure(): void { - $GLOBALS['sql_compatibility'] = 'MSSQL'; - $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') - ->withParsedBody(['sql_backquotes' => 'true', 'sql_include_comments' => 'On']); + ->withParsedBody([ + 'sql_backquotes' => 'true', + 'sql_include_comments' => 'On', + 'sql_compatibility' => 'MSSQL', + ]); $this->object->setExportOptions($request, []); @@ -938,10 +946,7 @@ SQL; self::assertStringContainsString('CREATE TABLE `test_table`', $result); // case 2 - unset($GLOBALS['sql_compatibility']); - $GLOBALS['sql_create_trigger'] = true; - $GLOBALS['sql_drop_table'] = true; $this->object->useSqlBackquotes(false); @@ -957,7 +962,6 @@ SQL; ); unset($GLOBALS['sql_create_trigger']); - unset($GLOBALS['sql_drop_table']); // case 3 $GLOBALS['sql_views_as_tables'] = false; @@ -1075,10 +1079,8 @@ SQL; ->willReturn($tableObj); DatabaseInterface::$instance = $dbi; - $GLOBALS['sql_compatibility'] = 'MSSQL'; $GLOBALS['sql_max_query_size'] = 50000; $GLOBALS['sql_views_as_tables'] = true; - $GLOBALS['sql_type'] = 'INSERT'; $GLOBALS['sql_delayed'] = ' DELAYED'; $GLOBALS['sql_ignore'] = true; $GLOBALS['sql_truncate'] = true; @@ -1086,7 +1088,10 @@ SQL; $GLOBALS['sql_hex_for_binary'] = true; Config::getInstance()->selectedServer['DisableIS'] = false; - $this->object->useSqlBackquotes(true); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') + ->withParsedBody(['sql_backquotes' => 'true', 'sql_compatibility' => 'MSSQL']); + + $this->object->setExportOptions($request, []); ob_start(); $this->object->exportData('db', 'table', 'SELECT a FROM b WHERE 1'); @@ -1172,9 +1177,7 @@ SQL; ->willReturn($tableObj); DatabaseInterface::$instance = $dbi; - $GLOBALS['sql_compatibility'] = 'MSSQL'; $GLOBALS['sql_views_as_tables'] = true; - $GLOBALS['sql_type'] = 'UPDATE'; $GLOBALS['sql_delayed'] = ' DELAYED'; $GLOBALS['sql_ignore'] = true; $GLOBALS['sql_truncate'] = true; @@ -1182,7 +1185,10 @@ SQL; $GLOBALS['sql_hex_for_binary'] = true; Config::getInstance()->selectedServer['DisableIS'] = false; - $this->object->useSqlBackquotes(true); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') + ->withParsedBody(['sql_backquotes' => 'true', 'sql_compatibility' => 'MSSQL', 'sql_type' => 'UPDATE']); + + $this->object->setExportOptions($request, []); ob_start(); $this->object->exportData('db', 'table', 'SELECT a FROM b WHERE 1'); @@ -1220,8 +1226,6 @@ SQL; DatabaseInterface::$instance = $dbi; Config::getInstance()->selectedServer['DisableIS'] = false; $GLOBALS['sql_views_as_tables'] = false; - $oldVal = $GLOBALS['sql_compatibility'] ?? ''; - $GLOBALS['sql_compatibility'] = 'NONE'; $request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/') ->withParsedBody(['sql_backquotes' => 'true', 'sql_include_comments' => 'On']); @@ -1239,9 +1243,6 @@ SQL; self::assertStringContainsString("-- VIEW `tbl`\n", $result); self::assertStringContainsString("-- Data: None\n", $result); - - // reset - $GLOBALS['sql_compatibility'] = $oldVal; } public function testExportDataWithError(): void diff --git a/tests/unit/Table/TableTest.php b/tests/unit/Table/TableTest.php index 595cd03d4b..a7e9d2fe7a 100644 --- a/tests/unit/Table/TableTest.php +++ b/tests/unit/Table/TableTest.php @@ -51,7 +51,6 @@ class TableTest extends AbstractTestCase $config->selectedServer['pmadb'] = 'pmadb'; $GLOBALS['sql_auto_increment'] = true; $GLOBALS['sql_if_not_exists'] = true; - $GLOBALS['sql_drop_table'] = true; $config->selectedServer['table_uiprefs'] = 'pma__table_uiprefs'; $sqlIsViewTrue = 'SELECT 1' @@ -1342,8 +1341,6 @@ class TableTest extends AbstractTestCase $targetTable = 'PMA_BookMark_new'; $targetDb = 'PMA_new'; - unset($GLOBALS['sql_drop_table']); - $getTableMap = [ [$targetDb, $targetTable, new Table($targetTable, $targetDb, $this->mockedDbi)], ['aa', 'ad', new Table('ad', 'aa', $this->mockedDbi)],