diff options
| author | Charles Cabergs <me@cacharle.xyz> | 2020-07-27 10:05:23 +0200 |
|---|---|---|
| committer | Charles Cabergs <me@cacharle.xyz> | 2020-07-27 10:05:23 +0200 |
| commit | 5bf66662a9bdd62c5bccab15e607cd95cfb8fcab (patch) | |
| tree | 39a1a4629749056191c05dfd899f931701b7acf3 /srcs/phpmyadmin/libraries/classes/DatabaseInterface.php | |
| parent | 5afd237bbd22028b85532b8c0b3fcead49a00764 (diff) | |
| download | ft_server-master.tar.gz ft_server-master.tar.bz2 ft_server-master.zip | |
Removed wordpress and phpmyadmin, my server doesn't handle it well and it brings shame on my famillyHEADmaster
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/DatabaseInterface.php')
| -rw-r--r-- | srcs/phpmyadmin/libraries/classes/DatabaseInterface.php | 3187 |
1 files changed, 0 insertions, 3187 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/DatabaseInterface.php b/srcs/phpmyadmin/libraries/classes/DatabaseInterface.php deleted file mode 100644 index 3e12302..0000000 --- a/srcs/phpmyadmin/libraries/classes/DatabaseInterface.php +++ /dev/null @@ -1,3187 +0,0 @@ -<?php -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * Main interface for database interactions - * - * @package PhpMyAdmin-DBI - */ -declare(strict_types=1); - -namespace PhpMyAdmin; - -use mysqli_result; -use PhpMyAdmin\Database\DatabaseList; -use PhpMyAdmin\Dbi\DbiExtension; -use PhpMyAdmin\Dbi\DbiMysqli; -use PhpMyAdmin\SqlParser\Context; - -/** - * Main interface for database interactions - * - * @package PhpMyAdmin-DBI - */ -class DatabaseInterface -{ - /** - * Force STORE_RESULT method, ignored by classic MySQL. - */ - public const QUERY_STORE = 1; - /** - * Do not read whole query. - */ - public const QUERY_UNBUFFERED = 2; - /** - * Get session variable. - */ - public const GETVAR_SESSION = 1; - /** - * Get global variable. - */ - public const GETVAR_GLOBAL = 2; - - /** - * User connection. - */ - public const CONNECT_USER = 0x100; - /** - * Control user connection. - */ - public const CONNECT_CONTROL = 0x101; - /** - * Auxiliary connection. - * - * Used for example for replication setup. - */ - public const CONNECT_AUXILIARY = 0x102; - - /** - * @var DbiExtension - */ - private $_extension; - - /** - * Opened database links - * - * @var array - */ - private $_links; - - /** - * @var array Table data cache - */ - private $_table_cache; - - /** - * @var array Current user and host cache - */ - private $_current_user; - - /** - * @var null|string lower_case_table_names value cache - */ - private $_lower_case_table_names = null; - - /** - * @var boolean Whether connection is MariaDB - */ - private $_is_mariadb = false; - /** - * @var boolean Whether connection is Percona - */ - private $_is_percona = false; - /** - * @var integer Server version as number - */ - private $_version_int = 55000; - /** - * @var string Server version - */ - private $_version_str = '5.50.0'; - /** - * @var string Server version comment - */ - private $_version_comment = ''; - - /** - * @var Types MySQL types data - */ - public $types; - - /** - * @var Relation - */ - private $relation; - - /** - * Constructor - * - * @param DbiExtension $ext Object to be used for database queries - */ - public function __construct(DbiExtension $ext) - { - $this->_extension = $ext; - $this->_links = []; - if (defined('TESTSUITE')) { - $this->_links[DatabaseInterface::CONNECT_USER] = 1; - $this->_links[DatabaseInterface::CONNECT_CONTROL] = 2; - } - $this->_table_cache = []; - $this->_current_user = []; - $this->types = new Types($this); - $this->relation = new Relation($this); - } - - /** - * Checks whether database extension is loaded - * - * @param string $extension mysql extension to check - * - * @return bool - */ - public static function checkDbExtension(string $extension = 'mysqli'): bool - { - return function_exists($extension . '_connect'); - } - - /** - * runs a query - * - * @param string $query SQL query to execute - * @param mixed $link optional database link to use - * @param int $options optional query options - * @param bool $cache_affected_rows whether to cache affected rows - * - * @return mixed - */ - public function query( - string $query, - $link = DatabaseInterface::CONNECT_USER, - int $options = 0, - bool $cache_affected_rows = true - ) { - $res = $this->tryQuery($query, $link, $options, $cache_affected_rows) - or Util::mysqlDie($this->getError($link), $query); - - return $res; - } - - /** - * Get a cached value from table cache. - * - * @param array $contentPath Array of the name of the target value - * @param mixed $default Return value on cache miss - * - * @return mixed cached value or default - */ - public function getCachedTableContent(array $contentPath, $default = null) - { - return Util::getValueByKey($this->_table_cache, $contentPath, $default); - } - - /** - * Set an item in table cache using dot notation. - * - * @param array $contentPath Array with the target path - * @param mixed $value Target value - * - * @return void - */ - public function cacheTableContent(array $contentPath, $value): void - { - $loc = &$this->_table_cache; - - if (! isset($contentPath)) { - $loc = $value; - return; - } - - while (count($contentPath) > 1) { - $key = array_shift($contentPath); - - // If the key doesn't exist at this depth, we will just create an empty - // array to hold the next value, allowing us to create the arrays to hold - // final values at the correct depth. Then we'll keep digging into the - // array. - if (! isset($loc[$key]) || ! is_array($loc[$key])) { - $loc[$key] = []; - } - $loc = &$loc[$key]; - } - - $loc[array_shift($contentPath)] = $value; - } - - /** - * Clear the table cache. - * - * @return void - */ - public function clearTableCache(): void - { - $this->_table_cache = []; - } - - /** - * Caches table data so Table does not require to issue - * SHOW TABLE STATUS again - * - * @param array $tables information for tables of some databases - * @param string|bool $table table name - * - * @return void - */ - private function _cacheTableData(array $tables, $table): void - { - // Note: I don't see why we would need array_merge_recursive() here, - // as it creates double entries for the same table (for example a double - // entry for Comment when changing the storage engine in Operations) - // Note 2: Instead of array_merge(), simply use the + operator because - // array_merge() renumbers numeric keys starting with 0, therefore - // we would lose a db name that consists only of numbers - - foreach ($tables as $one_database => $its_tables) { - if (isset($this->_table_cache[$one_database])) { - // the + operator does not do the intended effect - // when the cache for one table already exists - if ($table - && isset($this->_table_cache[$one_database][$table]) - ) { - unset($this->_table_cache[$one_database][$table]); - } - $this->_table_cache[$one_database] - += $tables[$one_database]; - } else { - $this->_table_cache[$one_database] = $tables[$one_database]; - } - } - } - - /** - * Stores query data into session data for debugging purposes - * - * @param string $query Query text - * @param mixed $link link type - * @param object|boolean $result Query result - * @param integer|float $time Time to execute query - * - * @return void - */ - private function _dbgQuery(string $query, $link, $result, $time): void - { - $dbgInfo = []; - $error_message = $this->getError($link); - if ($result == false && is_string($error_message)) { - $dbgInfo['error'] - = '<span class="color_red">' - . htmlspecialchars($error_message) . '</span>'; - } - $dbgInfo['query'] = htmlspecialchars($query); - $dbgInfo['time'] = $time; - // Get and slightly format backtrace, this is used - // in the javascript console. - // Strip call to _dbgQuery - $dbgInfo['trace'] = Error::processBacktrace( - array_slice(debug_backtrace(), 1) - ); - $dbgInfo['hash'] = md5($query); - - $_SESSION['debug']['queries'][] = $dbgInfo; - } - - /** - * runs a query and returns the result - * - * @param string $query query to run - * @param mixed $link link type - * @param integer $options query options - * @param bool $cache_affected_rows whether to cache affected row - * - * @return mixed - */ - public function tryQuery( - string $query, - $link = DatabaseInterface::CONNECT_USER, - int $options = 0, - bool $cache_affected_rows = true - ) { - $debug = isset($GLOBALS['cfg']['DBG']) ? $GLOBALS['cfg']['DBG']['sql'] : false; - if (! isset($this->_links[$link])) { - return false; - } - - if ($debug) { - $time = microtime(true); - } - - $result = $this->_extension->realQuery($query, $this->_links[$link], $options); - - if ($cache_affected_rows) { - $GLOBALS['cached_affected_rows'] = $this->affectedRows($link, false); - } - - if ($debug) { - $time = microtime(true) - $time; - $this->_dbgQuery($query, $link, $result, $time); - if ($GLOBALS['cfg']['DBG']['sqllog']) { - $warningsCount = ''; - if (($options & DatabaseInterface::QUERY_STORE) == DatabaseInterface::QUERY_STORE) { - if (isset($this->_links[$link]->warning_count)) { - $warningsCount = $this->_links[$link]->warning_count; - } - } - - openlog('phpMyAdmin', LOG_NDELAY | LOG_PID, LOG_USER); - - syslog( - LOG_INFO, - 'SQL[' . basename($_SERVER['SCRIPT_NAME']) . ']: ' - . sprintf('%0.3f', $time) . '(W:' . $warningsCount . ') > ' . $query - ); - closelog(); - } - } - - if ($result !== false && Tracker::isActive()) { - Tracker::handleQuery($query); - } - - return $result; - } - - /** - * Run multi query statement and return results - * - * @param string $multiQuery multi query statement to execute - * @param int $linkIndex index of the opened database link - * - * @return mysqli_result[]|boolean (false) - */ - public function tryMultiQuery( - string $multiQuery = '', - $linkIndex = DatabaseInterface::CONNECT_USER - ) { - if (! isset($this->_links[$linkIndex])) { - return false; - } - return $this->_extension->realMultiQuery($this->_links[$linkIndex], $multiQuery); - } - - /** - * returns array with table names for given db - * - * @param string $database name of database - * @param mixed $link mysql link resource|object - * - * @return array tables names - */ - public function getTables(string $database, $link = DatabaseInterface::CONNECT_USER): array - { - $tables = $this->fetchResult( - 'SHOW TABLES FROM ' . Util::backquote($database) . ';', - null, - 0, - $link, - self::QUERY_STORE - ); - if ($GLOBALS['cfg']['NaturalOrder']) { - usort($tables, 'strnatcasecmp'); - } - return $tables; - } - - - /** - * returns - * - * @param string $database name of database - * @param array $tables list of tables to search for for relations - * @param int $link mysql link resource|object - * - * @return array array of found foreign keys - */ - public function getForeignKeyConstrains(string $database, array $tables, $link = DatabaseInterface::CONNECT_USER): array - { - $tablesListForQuery = ''; - foreach ($tables as $table) { - $tablesListForQuery .= "'" . $this->escapeString($table) . "',"; - } - $tablesListForQuery = rtrim($tablesListForQuery, ','); - - $foreignKeyConstrains = $this->fetchResult( - "SELECT" - . " TABLE_NAME," - . " COLUMN_NAME," - . " REFERENCED_TABLE_NAME," - . " REFERENCED_COLUMN_NAME" - . " FROM information_schema.key_column_usage" - . " WHERE referenced_table_name IS NOT NULL" - . " AND TABLE_SCHEMA = '" . $this->escapeString($database) . "'" - . " AND TABLE_NAME IN (" . $tablesListForQuery . ")" - . " AND REFERENCED_TABLE_NAME IN (" . $tablesListForQuery . ");", - null, - null, - $link, - self::QUERY_STORE - ); - return $foreignKeyConstrains; - } - - /** - * returns a segment of the SQL WHERE clause regarding table name and type - * - * @param array|string $table table(s) - * @param boolean $tbl_is_group $table is a table group - * @param string $table_type whether table or view - * - * @return string a segment of the WHERE clause - */ - private function _getTableCondition( - $table, - bool $tbl_is_group, - ?string $table_type - ): string { - // get table information from information_schema - if ($table) { - if (is_array($table)) { - $sql_where_table = 'AND t.`TABLE_NAME` ' - . Util::getCollateForIS() . ' IN (\'' - . implode( - '\', \'', - array_map( - [ - $this, - 'escapeString', - ], - $table - ) - ) - . '\')'; - } elseif (true === $tbl_is_group) { - $sql_where_table = 'AND t.`TABLE_NAME` LIKE \'' - . Util::escapeMysqlWildcards( - $this->escapeString($table) - ) - . '%\''; - } else { - $sql_where_table = 'AND t.`TABLE_NAME` ' - . Util::getCollateForIS() . ' = \'' - . $this->escapeString($table) . '\''; - } - } else { - $sql_where_table = ''; - } - - if ($table_type) { - if ($table_type == 'view') { - $sql_where_table .= " AND t.`TABLE_TYPE` NOT IN ('BASE TABLE', 'SYSTEM VERSIONED')"; - } elseif ($table_type == 'table') { - $sql_where_table .= " AND t.`TABLE_TYPE` IN ('BASE TABLE', 'SYSTEM VERSIONED')"; - } - } - return $sql_where_table; - } - - /** - * returns the beginning of the SQL statement to fetch the list of tables - * - * @param string[] $this_databases databases to list - * @param string $sql_where_table additional condition - * - * @return string the SQL statement - */ - private function _getSqlForTablesFull($this_databases, string $sql_where_table): string - { - return ' - SELECT *, - `TABLE_SCHEMA` AS `Db`, - `TABLE_NAME` AS `Name`, - `TABLE_TYPE` AS `TABLE_TYPE`, - `ENGINE` AS `Engine`, - `ENGINE` AS `Type`, - `VERSION` AS `Version`, - `ROW_FORMAT` AS `Row_format`, - `TABLE_ROWS` AS `Rows`, - `AVG_ROW_LENGTH` AS `Avg_row_length`, - `DATA_LENGTH` AS `Data_length`, - `MAX_DATA_LENGTH` AS `Max_data_length`, - `INDEX_LENGTH` AS `Index_length`, - `DATA_FREE` AS `Data_free`, - `AUTO_INCREMENT` AS `Auto_increment`, - `CREATE_TIME` AS `Create_time`, - `UPDATE_TIME` AS `Update_time`, - `CHECK_TIME` AS `Check_time`, - `TABLE_COLLATION` AS `Collation`, - `CHECKSUM` AS `Checksum`, - `CREATE_OPTIONS` AS `Create_options`, - `TABLE_COMMENT` AS `Comment` - FROM `information_schema`.`TABLES` t - WHERE `TABLE_SCHEMA` ' . Util::getCollateForIS() . ' - IN (\'' . implode("', '", $this_databases) . '\') - ' . $sql_where_table; - } - - /** - * returns array of all tables in given db or dbs - * this function expects unquoted names: - * RIGHT: my_database - * WRONG: `my_database` - * WRONG: my\_database - * if $tbl_is_group is true, $table is used as filter for table names - * - * <code> - * $dbi->getTablesFull('my_database'); - * $dbi->getTablesFull('my_database', 'my_table')); - * $dbi->getTablesFull('my_database', 'my_tables_', true)); - * </code> - * - * @param string $database database - * @param string|array $table table name(s) - * @param boolean $tbl_is_group $table is a table group - * @param integer $limit_offset zero-based offset for the count - * @param boolean|integer $limit_count number of tables to return - * @param string $sort_by table attribute to sort by - * @param string $sort_order direction to sort (ASC or DESC) - * @param string $table_type whether table or view - * @param mixed $link link type - * - * @todo move into Table - * - * @return array list of tables in given db(s) - */ - public function getTablesFull( - string $database, - $table = '', - bool $tbl_is_group = false, - int $limit_offset = 0, - $limit_count = false, - string $sort_by = 'Name', - string $sort_order = 'ASC', - ?string $table_type = null, - $link = DatabaseInterface::CONNECT_USER - ): array { - if (true === $limit_count) { - $limit_count = $GLOBALS['cfg']['MaxTableList']; - } - // prepare and check parameters - if (! is_array($database)) { - $databases = [$database]; - } else { - $databases = $database; - } - - $tables = []; - - if (! $GLOBALS['cfg']['Server']['DisableIS']) { - $sql_where_table = $this->_getTableCondition( - $table, - $tbl_is_group, - $table_type - ); - - // for PMA bc: - // `SCHEMA_FIELD_NAME` AS `SHOW_TABLE_STATUS_FIELD_NAME` - // - // on non-Windows servers, - // added BINARY in the WHERE clause to force a case sensitive - // comparison (if we are looking for the db Aa we don't want - // to find the db aa) - $this_databases = array_map( - [ - $this, - 'escapeString', - ], - $databases - ); - - $sql = $this->_getSqlForTablesFull($this_databases, $sql_where_table); - - // Sort the tables - $sql .= " ORDER BY $sort_by $sort_order"; - - if ($limit_count) { - $sql .= ' LIMIT ' . $limit_count . ' OFFSET ' . $limit_offset; - } - - $tables = $this->fetchResult( - $sql, - [ - 'TABLE_SCHEMA', - 'TABLE_NAME', - ], - null, - $link - ); - - if ($sort_by == 'Name' && $GLOBALS['cfg']['NaturalOrder']) { - // here, the array's first key is by schema name - foreach ($tables as $one_database_name => $one_database_tables) { - uksort($one_database_tables, 'strnatcasecmp'); - - if ($sort_order == 'DESC') { - $one_database_tables = array_reverse($one_database_tables); - } - $tables[$one_database_name] = $one_database_tables; - } - } elseif ($sort_by == 'Data_length') { - // Size = Data_length + Index_length - foreach ($tables as $one_database_name => $one_database_tables) { - uasort( - $one_database_tables, - function ($a, $b) { - $aLength = $a['Data_length'] + $a['Index_length']; - $bLength = $b['Data_length'] + $b['Index_length']; - return $aLength <=> $bLength; - } - ); - - if ($sort_order == 'DESC') { - $one_database_tables = array_reverse($one_database_tables); - } - $tables[$one_database_name] = $one_database_tables; - } - } - } // end (get information from table schema) - - // If permissions are wrong on even one database directory, - // information_schema does not return any table info for any database - // this is why we fall back to SHOW TABLE STATUS even for MySQL >= 50002 - if (empty($tables)) { - foreach ($databases as $each_database) { - if ($table || (true === $tbl_is_group) || ! empty($table_type)) { - $sql = 'SHOW TABLE STATUS FROM ' - . Util::backquote($each_database) - . ' WHERE'; - $needAnd = false; - if ($table || (true === $tbl_is_group)) { - if (is_array($table)) { - $sql .= ' `Name` IN (\'' - . implode( - '\', \'', - array_map( - [ - $this, - 'escapeString', - ], - $table, - $link - ) - ) . '\')'; - } else { - $sql .= " `Name` LIKE '" - . Util::escapeMysqlWildcards( - $this->escapeString($table, $link) - ) - . "%'"; - } - $needAnd = true; - } - if (! empty($table_type)) { - if ($needAnd) { - $sql .= " AND"; - } - if ($table_type == 'view') { - $sql .= " `Comment` = 'VIEW'"; - } elseif ($table_type == 'table') { - $sql .= " `Comment` != 'VIEW'"; - } - } - } else { - $sql = 'SHOW TABLE STATUS FROM ' - . Util::backquote($each_database); - } - - $each_tables = $this->fetchResult($sql, 'Name', null, $link); - - // Sort naturally if the config allows it and we're sorting - // the Name column. - if ($sort_by == 'Name' && $GLOBALS['cfg']['NaturalOrder']) { - uksort($each_tables, 'strnatcasecmp'); - - if ($sort_order == 'DESC') { - $each_tables = array_reverse($each_tables); - } - } else { - // Prepare to sort by creating array of the selected sort - // value to pass to array_multisort - - // Size = Data_length + Index_length - if ($sort_by == 'Data_length') { - foreach ($each_tables as $table_name => $table_data) { - ${$sort_by}[$table_name] = strtolower( - $table_data['Data_length'] - + $table_data['Index_length'] - ); - } - } else { - foreach ($each_tables as $table_name => $table_data) { - ${$sort_by}[$table_name] - = strtolower($table_data[$sort_by]); - } - } - - if (! empty($$sort_by)) { - if ($sort_order == 'DESC') { - array_multisort($$sort_by, SORT_DESC, $each_tables); - } else { - array_multisort($$sort_by, SORT_ASC, $each_tables); - } - } - - // cleanup the temporary sort array - unset($$sort_by); - } - - if ($limit_count) { - $each_tables = array_slice( - $each_tables, - $limit_offset, - $limit_count - ); - } - - foreach ($each_tables as $table_name => $each_table) { - if (! isset($each_tables[$table_name]['Type']) - && isset($each_tables[$table_name]['Engine']) - ) { - // pma BC, same parts of PMA still uses 'Type' - $each_tables[$table_name]['Type'] - =& $each_tables[$table_name]['Engine']; - } elseif (! isset($each_tables[$table_name]['Engine']) - && isset($each_tables[$table_name]['Type']) - ) { - // old MySQL reports Type, newer MySQL reports Engine - $each_tables[$table_name]['Engine'] - =& $each_tables[$table_name]['Type']; - } - - // Compatibility with INFORMATION_SCHEMA output - $each_tables[$table_name]['TABLE_SCHEMA'] - = $each_database; - $each_tables[$table_name]['TABLE_NAME'] - =& $each_tables[$table_name]['Name']; - $each_tables[$table_name]['ENGINE'] - =& $each_tables[$table_name]['Engine']; - $each_tables[$table_name]['VERSION'] - =& $each_tables[$table_name]['Version']; - $each_tables[$table_name]['ROW_FORMAT'] - =& $each_tables[$table_name]['Row_format']; - $each_tables[$table_name]['TABLE_ROWS'] - =& $each_tables[$table_name]['Rows']; - $each_tables[$table_name]['AVG_ROW_LENGTH'] - =& $each_tables[$table_name]['Avg_row_length']; - $each_tables[$table_name]['DATA_LENGTH'] - =& $each_tables[$table_name]['Data_length']; - $each_tables[$table_name]['MAX_DATA_LENGTH'] - =& $each_tables[$table_name]['Max_data_length']; - $each_tables[$table_name]['INDEX_LENGTH'] - =& $each_tables[$table_name]['Index_length']; - $each_tables[$table_name]['DATA_FREE'] - =& $each_tables[$table_name]['Data_free']; - $each_tables[$table_name]['AUTO_INCREMENT'] - =& $each_tables[$table_name]['Auto_increment']; - $each_tables[$table_name]['CREATE_TIME'] - =& $each_tables[$table_name]['Create_time']; - $each_tables[$table_name]['UPDATE_TIME'] - =& $each_tables[$table_name]['Update_time']; - $each_tables[$table_name]['CHECK_TIME'] - =& $each_tables[$table_name]['Check_time']; - $each_tables[$table_name]['TABLE_COLLATION'] - =& $each_tables[$table_name]['Collation']; - $each_tables[$table_name]['CHECKSUM'] - =& $each_tables[$table_name]['Checksum']; - $each_tables[$table_name]['CREATE_OPTIONS'] - =& $each_tables[$table_name]['Create_options']; - $each_tables[$table_name]['TABLE_COMMENT'] - =& $each_tables[$table_name]['Comment']; - - if (strtoupper($each_tables[$table_name]['Comment']) === 'VIEW' - && $each_tables[$table_name]['Engine'] == null - ) { - $each_tables[$table_name]['TABLE_TYPE'] = 'VIEW'; - } elseif ($each_database == 'information_schema') { - $each_tables[$table_name]['TABLE_TYPE'] = 'SYSTEM VIEW'; - } else { - /** - * @todo difference between 'TEMPORARY' and 'BASE TABLE' - * but how to detect? - */ - $each_tables[$table_name]['TABLE_TYPE'] = 'BASE TABLE'; - } - } - - $tables[$each_database] = $each_tables; - } - } - - // cache table data - // so Table does not require to issue SHOW TABLE STATUS again - $this->_cacheTableData($tables, $table); - - if (is_array($database)) { - return $tables; - } - - if (isset($tables[$database])) { - return $tables[$database]; - } - - if (isset($tables[mb_strtolower($database)])) { - // on windows with lower_case_table_names = 1 - // MySQL returns - // with SHOW DATABASES or information_schema.SCHEMATA: `Test` - // but information_schema.TABLES gives `test` - // see https://github.com/phpmyadmin/phpmyadmin/issues/8402 - return $tables[mb_strtolower($database)]; - } - - return $tables; - } - - /** - * Get VIEWs in a particular database - * - * @param string $db Database name to look in - * - * @return array Set of VIEWs inside the database - */ - public function getVirtualTables(string $db): array - { - $tables_full = $this->getTablesFull($db); - $views = []; - - foreach ($tables_full as $table => $tmp) { - $_table = $this->getTable($db, (string) $table); - if ($_table->isView()) { - $views[] = $table; - } - } - - return $views; - } - - - /** - * returns array with databases containing extended infos about them - * - * @param string $database database - * @param boolean $force_stats retrieve stats also for MySQL < 5 - * @param integer $link link type - * @param string $sort_by column to order by - * @param string $sort_order ASC or DESC - * @param integer $limit_offset starting offset for LIMIT - * @param bool|int $limit_count row count for LIMIT or true - * for $GLOBALS['cfg']['MaxDbList'] - * - * @todo move into ListDatabase? - * - * @return array - */ - public function getDatabasesFull( - ?string $database = null, - bool $force_stats = false, - $link = DatabaseInterface::CONNECT_USER, - string $sort_by = 'SCHEMA_NAME', - string $sort_order = 'ASC', - int $limit_offset = 0, - $limit_count = false - ): array { - $sort_order = strtoupper($sort_order); - - if (true === $limit_count) { - $limit_count = $GLOBALS['cfg']['MaxDbList']; - } - - $apply_limit_and_order_manual = true; - - if (! $GLOBALS['cfg']['Server']['DisableIS']) { - /** - * if $GLOBALS['cfg']['NaturalOrder'] is enabled, we cannot use LIMIT - * cause MySQL does not support natural ordering, - * we have to do it afterward - */ - $limit = ''; - if (! $GLOBALS['cfg']['NaturalOrder']) { - if ($limit_count) { - $limit = ' LIMIT ' . $limit_count . ' OFFSET ' . $limit_offset; - } - - $apply_limit_and_order_manual = false; - } - - // get table information from information_schema - if (! empty($database)) { - $sql_where_schema = 'WHERE `SCHEMA_NAME` LIKE \'' - . $this->escapeString($database, $link) . '\''; - } else { - $sql_where_schema = ''; - } - - $sql = 'SELECT *, - CAST(BIN_NAME AS CHAR CHARACTER SET utf8) AS SCHEMA_NAME - FROM ('; - $sql .= 'SELECT - BINARY s.SCHEMA_NAME AS BIN_NAME, - s.DEFAULT_COLLATION_NAME'; - if ($force_stats) { - $sql .= ', - COUNT(t.TABLE_SCHEMA) AS SCHEMA_TABLES, - SUM(t.TABLE_ROWS) AS SCHEMA_TABLE_ROWS, - SUM(t.DATA_LENGTH) AS SCHEMA_DATA_LENGTH, - SUM(t.MAX_DATA_LENGTH) AS SCHEMA_MAX_DATA_LENGTH, - SUM(t.INDEX_LENGTH) AS SCHEMA_INDEX_LENGTH, - SUM(t.DATA_LENGTH + t.INDEX_LENGTH) - AS SCHEMA_LENGTH, - SUM(IF(t.ENGINE <> \'InnoDB\', t.DATA_FREE, 0)) - AS SCHEMA_DATA_FREE'; - } - $sql .= ' - FROM `information_schema`.SCHEMATA s '; - if ($force_stats) { - $sql .= ' - LEFT JOIN `information_schema`.TABLES t - ON BINARY t.TABLE_SCHEMA = BINARY s.SCHEMA_NAME'; - } - $sql .= $sql_where_schema . ' - GROUP BY BINARY s.SCHEMA_NAME, s.DEFAULT_COLLATION_NAME - ORDER BY '; - if ($sort_by == 'SCHEMA_NAME' - || $sort_by == 'DEFAULT_COLLATION_NAME' - ) { - $sql .= 'BINARY '; - } - $sql .= Util::backquote($sort_by) - . ' ' . $sort_order - . $limit; - $sql .= ') a'; - - $databases = $this->fetchResult($sql, 'SCHEMA_NAME', null, $link); - - $mysql_error = $this->getError($link); - if (! count($databases) && $GLOBALS['errno']) { - Util::mysqlDie($mysql_error, $sql); - } - - // display only databases also in official database list - // f.e. to apply hide_db and only_db - $drops = array_diff( - array_keys($databases), - (array) $GLOBALS['dblist']->databases - ); - foreach ($drops as $drop) { - unset($databases[$drop]); - } - } else { - $databases = []; - foreach ($GLOBALS['dblist']->databases as $database_name) { - // Compatibility with INFORMATION_SCHEMA output - $databases[$database_name]['SCHEMA_NAME'] = $database_name; - - $databases[$database_name]['DEFAULT_COLLATION_NAME'] - = $this->getDbCollation($database_name); - - |
