aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/libraries/classes/DatabaseInterface.php
diff options
context:
space:
mode:
authorCharles Cabergs <me@cacharle.xyz>2020-07-27 10:05:23 +0200
committerCharles Cabergs <me@cacharle.xyz>2020-07-27 10:05:23 +0200
commit5bf66662a9bdd62c5bccab15e607cd95cfb8fcab (patch)
tree39a1a4629749056191c05dfd899f931701b7acf3 /srcs/phpmyadmin/libraries/classes/DatabaseInterface.php
parent5afd237bbd22028b85532b8c0b3fcead49a00764 (diff)
downloadft_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.php3187
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);
-
-