|
@@ -1,588 +0,0 @@
|
|
-<?php
|
|
|
|
-/**
|
|
|
|
- * This file is part of the ForkBB <https://github.com/forkbb>.
|
|
|
|
- *
|
|
|
|
- * @copyright (c) Visman <mio.visman@yandex.ru, https://github.com/MioVisman>
|
|
|
|
- * @license The MIT License (MIT)
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
-declare(strict_types=1);
|
|
|
|
-
|
|
|
|
-namespace ForkBB\Core\DB;
|
|
|
|
-
|
|
|
|
-use ForkBB\Core\DB;
|
|
|
|
-use PDO;
|
|
|
|
-use PDOStatement;
|
|
|
|
-use PDOException;
|
|
|
|
-
|
|
|
|
-class Mysql
|
|
|
|
-{
|
|
|
|
- /**
|
|
|
|
- * @var DB
|
|
|
|
- */
|
|
|
|
- protected $db;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Префикс для таблиц базы
|
|
|
|
- * @var string
|
|
|
|
- */
|
|
|
|
- protected $dbPrefix;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Массив замены типов полей таблицы
|
|
|
|
- * @var array
|
|
|
|
- */
|
|
|
|
- protected $dbTypeRepl = [
|
|
|
|
- '%^SERIAL$%i' => 'INT(10) UNSIGNED AUTO_INCREMENT',
|
|
|
|
- ];
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Подстановка типов полей для карты БД
|
|
|
|
- * @var array
|
|
|
|
- */
|
|
|
|
- protected $types = [
|
|
|
|
- 'bool' => 'b',
|
|
|
|
- 'boolean' => 'b',
|
|
|
|
- 'tinyint' => 'i',
|
|
|
|
- 'smallint' => 'i',
|
|
|
|
- 'mediumint' => 'i',
|
|
|
|
- 'int' => 'i',
|
|
|
|
- 'integer' => 'i',
|
|
|
|
- 'bigint' => 'i',
|
|
|
|
- 'decimal' => 'i',
|
|
|
|
- 'dec' => 'i',
|
|
|
|
- 'float' => 'i',
|
|
|
|
- 'double' => 'i',
|
|
|
|
- ];
|
|
|
|
-
|
|
|
|
- public function __construct(DB $db, string $prefix)
|
|
|
|
- {
|
|
|
|
- $this->db = $db;
|
|
|
|
-
|
|
|
|
- $this->testStr($prefix);
|
|
|
|
-
|
|
|
|
- $this->dbPrefix = $prefix;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Перехват неизвестных методов
|
|
|
|
- */
|
|
|
|
- public function __call(string $name, array $args)
|
|
|
|
- {
|
|
|
|
- throw new PDOException("Method '{$name}' not found in DB driver.");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Проверяет строку на допустимые символы
|
|
|
|
- */
|
|
|
|
- protected function testStr(string $str): void
|
|
|
|
- {
|
|
|
|
- if (\preg_match('%[^a-zA-Z0-9_]%', $str)) {
|
|
|
|
- throw new PDOException("Name '{$str}' have bad characters.");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Операции над полями индексов: проверка, замена
|
|
|
|
- */
|
|
|
|
- protected function replIdxs(array $arr): string
|
|
|
|
- {
|
|
|
|
- foreach ($arr as &$value) {
|
|
|
|
- if (\preg_match('%^(.*)\s*(\(\d+\))$%', $value, $matches)) {
|
|
|
|
- $this->testStr($matches[1]);
|
|
|
|
-
|
|
|
|
- $value = "`{$matches[1]}`{$matches[2]}";
|
|
|
|
- } else {
|
|
|
|
- $this->testStr($value);
|
|
|
|
-
|
|
|
|
- $value = "`{$value}`";
|
|
|
|
- }
|
|
|
|
- unset($value);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return \implode(',', $arr);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Замена типа поля в соответствии с dbTypeRepl
|
|
|
|
- */
|
|
|
|
- protected function replType(string $type): string
|
|
|
|
- {
|
|
|
|
- return \preg_replace(\array_keys($this->dbTypeRepl), \array_values($this->dbTypeRepl), $type);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Конвертирует данные в строку для DEFAULT
|
|
|
|
- */
|
|
|
|
- protected function convToStr(/* mixed */ $data): string
|
|
|
|
- {
|
|
|
|
- if (\is_string($data)) {
|
|
|
|
- return $this->db->quote($data);
|
|
|
|
- } elseif (\is_numeric($data)) {
|
|
|
|
- return (string) $data;
|
|
|
|
- } elseif (\is_bool($data)) {
|
|
|
|
- return $data ? 'true' : 'false';
|
|
|
|
- } else {
|
|
|
|
- throw new PDOException('Invalid data type for DEFAULT.');
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Проверяет наличие таблицы в базе
|
|
|
|
- */
|
|
|
|
- public function tableExists(string $table, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- try {
|
|
|
|
- $vars = [
|
|
|
|
- ':table' => $table,
|
|
|
|
- ];
|
|
|
|
- $query = 'SELECT 1
|
|
|
|
- FROM INFORMATION_SCHEMA.TABLES
|
|
|
|
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?s:table';
|
|
|
|
-
|
|
|
|
- $stmt = $this->db->query($query, $vars);
|
|
|
|
- $result = $stmt->fetch();
|
|
|
|
- $stmt->closeCursor();
|
|
|
|
- } catch (PDOException $e) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return ! empty($result);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Проверяет наличие поля в таблице
|
|
|
|
- */
|
|
|
|
- public function fieldExists(string $table, string $field, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- try {
|
|
|
|
- $vars = [
|
|
|
|
- ':table' => $table,
|
|
|
|
- ':field' => $field,
|
|
|
|
- ];
|
|
|
|
- $query = 'SELECT 1
|
|
|
|
- FROM INFORMATION_SCHEMA.COLUMNS
|
|
|
|
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?s:table AND COLUMN_NAME = ?s:field';
|
|
|
|
-
|
|
|
|
- $stmt = $this->db->query($query, $vars);
|
|
|
|
- $result = $stmt->fetch();
|
|
|
|
- $stmt->closeCursor();
|
|
|
|
- } catch (PDOException $e) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return ! empty($result);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Проверяет наличие индекса в таблице
|
|
|
|
- */
|
|
|
|
- public function indexExists(string $table, string $index, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
- $index = 'PRIMARY' == $index ? $index : $table . '_' . $index;
|
|
|
|
-
|
|
|
|
- try {
|
|
|
|
- $vars = [
|
|
|
|
- ':table' => $table,
|
|
|
|
- ':index' => $index,
|
|
|
|
- ];
|
|
|
|
- $query = 'SELECT 1
|
|
|
|
- FROM INFORMATION_SCHEMA.STATISTICS
|
|
|
|
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?s:table AND INDEX_NAME = ?s:index';
|
|
|
|
-
|
|
|
|
- $stmt = $this->db->query($query, $vars);
|
|
|
|
- $result = $stmt->fetch();
|
|
|
|
- $stmt->closeCursor();
|
|
|
|
- } catch (PDOException $e) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return ! empty($result);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Создает таблицу
|
|
|
|
- */
|
|
|
|
- public function createTable(string $table, array $schema, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($table);
|
|
|
|
-
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- $query = "CREATE TABLE IF NOT EXISTS `{$table}` (";
|
|
|
|
- foreach ($schema['FIELDS'] as $field => $data) {
|
|
|
|
- $this->testStr($field);
|
|
|
|
- // имя и тип
|
|
|
|
- $query .= "`{$field}` " . $this->replType($data[0]);
|
|
|
|
- // сравнение
|
|
|
|
- if (\preg_match('%^(?:CHAR|VARCHAR|TINYTEXT|TEXT|MEDIUMTEXT|LONGTEXT|ENUM|SET)%i', $data[0])) {
|
|
|
|
- $query .= ' CHARACTER SET utf8mb4 COLLATE utf8mb4_';
|
|
|
|
- if (
|
|
|
|
- isset($data[3])
|
|
|
|
- && \is_string($data[3])
|
|
|
|
- ) {
|
|
|
|
- $this->testStr($data[3]);
|
|
|
|
- $query .= $data[3];
|
|
|
|
- } else {
|
|
|
|
- $query .= 'unicode_ci';
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- // не NULL
|
|
|
|
- if (empty($data[1])) {
|
|
|
|
- $query .= ' NOT NULL';
|
|
|
|
- }
|
|
|
|
- // значение по умолчанию
|
|
|
|
- if (isset($data[2])) {
|
|
|
|
- $query .= ' DEFAULT ' . $this->convToStr($data[2]);
|
|
|
|
- }
|
|
|
|
- $query .= ', ';
|
|
|
|
- }
|
|
|
|
- if (isset($schema['PRIMARY KEY'])) {
|
|
|
|
- $query .= 'PRIMARY KEY (' . $this->replIdxs($schema['PRIMARY KEY']) . '), ';
|
|
|
|
- }
|
|
|
|
- if (isset($schema['UNIQUE KEYS'])) {
|
|
|
|
- foreach ($schema['UNIQUE KEYS'] as $key => $fields) {
|
|
|
|
- $this->testStr($key);
|
|
|
|
-
|
|
|
|
- $query .= "UNIQUE `{$table}_{$key}` (" . $this->replIdxs($fields) . '), ';
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (isset($schema['INDEXES'])) {
|
|
|
|
- foreach ($schema['INDEXES'] as $index => $fields) {
|
|
|
|
- $this->testStr($index);
|
|
|
|
-
|
|
|
|
- $query .= "INDEX `{$table}_{$index}` (" . $this->replIdxs($fields) . '), ';
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (isset($schema['ENGINE'])) {
|
|
|
|
- $engine = $schema['ENGINE'];
|
|
|
|
- } else {
|
|
|
|
- // при отсутствии типа таблицы он определяется на основании типов других таблиц в базе
|
|
|
|
- $prefix = \str_replace('_', '\\_', $this->dbPrefix);
|
|
|
|
- $stmt = $this->db->query("SHOW TABLE STATUS LIKE '{$prefix}%'");
|
|
|
|
- $engine = [];
|
|
|
|
- while ($row = $stmt->fetch()) {
|
|
|
|
- if (isset($engine[$row['Engine']])) {
|
|
|
|
- ++$engine[$row['Engine']];
|
|
|
|
- } else {
|
|
|
|
- $engine[$row['Engine']] = 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- // в базе нет таблиц
|
|
|
|
- if (empty($engine)) {
|
|
|
|
- $engine = 'MyISAM';
|
|
|
|
- } else {
|
|
|
|
- \arsort($engine);
|
|
|
|
- // берем тип наиболее часто встречаемый у имеющихся таблиц
|
|
|
|
- $engine = \array_keys($engine);
|
|
|
|
- $engine = \array_shift($engine);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- $this->testStr($engine);
|
|
|
|
- $query = \rtrim($query, ', ') . ") ENGINE={$engine} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec($query);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Удаляет таблицу
|
|
|
|
- */
|
|
|
|
- public function dropTable(string $table, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($table);
|
|
|
|
-
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec("DROP TABLE IF EXISTS `{$table}`");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Переименовывает таблицу
|
|
|
|
- */
|
|
|
|
- public function renameTable(string $old, string $new, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($old);
|
|
|
|
- $this->testStr($new);
|
|
|
|
-
|
|
|
|
- if (
|
|
|
|
- $this->tableExists($new, $noPrefix)
|
|
|
|
- && ! $this->tableExists($old, $noPrefix)
|
|
|
|
- ) {
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $old = ($noPrefix ? '' : $this->dbPrefix) . $old;
|
|
|
|
- $new = ($noPrefix ? '' : $this->dbPrefix) . $new;
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec("ALTER TABLE `{$old}` RENAME TO `{$new}`");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Добавляет поле в таблицу
|
|
|
|
- */
|
|
|
|
- public function addField(string $table, string $field, string $type, bool $allowNull, /* mixed */ $default = null, string $after = null, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($table);
|
|
|
|
- $this->testStr($field);
|
|
|
|
-
|
|
|
|
- if ($this->fieldExists($table, $field, $noPrefix)) {
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- $query = "ALTER TABLE `{$table}` ADD `{$field}` " . $this->replType($type);
|
|
|
|
- if (! $allowNull) {
|
|
|
|
- $query .= ' NOT NULL';
|
|
|
|
- }
|
|
|
|
- if (null !== $default) {
|
|
|
|
- $query .= ' DEFAULT ' . $this->convToStr($default);
|
|
|
|
- }
|
|
|
|
- if (null !== $after) {
|
|
|
|
- $this->testStr($after);
|
|
|
|
-
|
|
|
|
- $query .= " AFTER `{$after}`";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec($query);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Модифицирует поле в таблице
|
|
|
|
- */
|
|
|
|
- public function alterField(string $table, string $field, string $type, bool $allowNull, /* mixed */ $default = null, string $after = null, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($table);
|
|
|
|
- $this->testStr($field);
|
|
|
|
-
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- $query = "ALTER TABLE `{$table}` MODIFY `{$field}` " . $this->replType($type);
|
|
|
|
- if (! $allowNull) {
|
|
|
|
- $query .= ' NOT NULL';
|
|
|
|
- }
|
|
|
|
- if (null !== $default) {
|
|
|
|
- $query .= ' DEFAULT ' . $this->convToStr($default);
|
|
|
|
- }
|
|
|
|
- if (null !== $after) {
|
|
|
|
- $this->testStr($after);
|
|
|
|
-
|
|
|
|
- $query .= " AFTER `{$after}`";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec($query);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Удаляет поле из таблицы
|
|
|
|
- */
|
|
|
|
- public function dropField(string $table, string $field, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($table);
|
|
|
|
- $this->testStr($field);
|
|
|
|
-
|
|
|
|
- if (! $this->fieldExists($table, $field, $noPrefix)) {
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec("ALTER TABLE `{$table}` DROP COLUMN `{$field}`");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Переименование поля в таблице
|
|
|
|
- */
|
|
|
|
- public function renameField(string $table, string $old, string $new, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($table);
|
|
|
|
- $this->testStr($old);
|
|
|
|
- $this->testStr($new);
|
|
|
|
-
|
|
|
|
- if (
|
|
|
|
- ! $this->fieldExists($table, $old, $noPrefix)
|
|
|
|
- || $this->fieldExists($table, $new, $noPrefix)
|
|
|
|
- ) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- try {
|
|
|
|
- $vars = [
|
|
|
|
- ':table' => $table,
|
|
|
|
- ':field' => $old,
|
|
|
|
- ];
|
|
|
|
- $query = 'SELECT COLUMN_DEFAULT, IS_NULLABLE, COLUMN_TYPE
|
|
|
|
- FROM INFORMATION_SCHEMA.COLUMNS
|
|
|
|
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?s:table AND COLUMN_NAME = ?s:field';
|
|
|
|
-
|
|
|
|
- $stmt = $this->db->query($query, $vars);
|
|
|
|
- $result = $stmt->fetch();
|
|
|
|
- $stmt->closeCursor();
|
|
|
|
-
|
|
|
|
- $type = $result['COLUMN_TYPE'];
|
|
|
|
- $allowNull = 'YES' == $result['IS_NULLABLE'];
|
|
|
|
- $default = $result['COLUMN_DEFAULT'];
|
|
|
|
- } catch (PDOException $e) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $query = "ALTER TABLE `{$table}` CHANGE COLUMN `{$old}` `{$new}` " . $this->replType($type);
|
|
|
|
- if (! $allowNull) {
|
|
|
|
- $query .= ' NOT NULL';
|
|
|
|
- }
|
|
|
|
- if (null !== $default) {
|
|
|
|
- $query .= ' DEFAULT ' . $this->convToStr($default);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec($query);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Добавляет индекс в таблицу
|
|
|
|
- */
|
|
|
|
- public function addIndex(string $table, string $index, array $fields, bool $unique = false, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($table);
|
|
|
|
-
|
|
|
|
- if ($this->indexExists($table, $index, $noPrefix)) {
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- $query = "ALTER TABLE `{$table}` ADD ";
|
|
|
|
- if ('PRIMARY' == $index) {
|
|
|
|
- $query .= 'PRIMARY KEY';
|
|
|
|
- } else {
|
|
|
|
- $index = $table . '_' . $index;
|
|
|
|
-
|
|
|
|
- $this->testStr($index);
|
|
|
|
-
|
|
|
|
- if ($unique) {
|
|
|
|
- $query .= "UNIQUE `{$index}`";
|
|
|
|
- } else {
|
|
|
|
- $query .= "INDEX `{$index}`";
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- $query .= ' (' . $this->replIdxs($fields) . ')';
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec($query);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Удаляет индекс из таблицы
|
|
|
|
- */
|
|
|
|
- public function dropIndex(string $table, string $index, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($table);
|
|
|
|
-
|
|
|
|
- if (! $this->indexExists($table, $index, $noPrefix)) {
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- $query = "ALTER TABLE `{$table}` ";
|
|
|
|
- if ('PRIMARY' == $index) {
|
|
|
|
- $query .= "DROP PRIMARY KEY";
|
|
|
|
- } else {
|
|
|
|
- $index = $table . '_' . $index;
|
|
|
|
-
|
|
|
|
- $this->testStr($index);
|
|
|
|
-
|
|
|
|
- $query .= "DROP INDEX `{$index}`";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec($query);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Очищает таблицу
|
|
|
|
- */
|
|
|
|
- public function truncateTable(string $table, bool $noPrefix = false): bool
|
|
|
|
- {
|
|
|
|
- $this->testStr($table);
|
|
|
|
-
|
|
|
|
- $table = ($noPrefix ? '' : $this->dbPrefix) . $table;
|
|
|
|
-
|
|
|
|
- return false !== $this->db->exec("TRUNCATE TABLE `{$table}`");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Возвращает статистику
|
|
|
|
- */
|
|
|
|
- public function statistics(): array
|
|
|
|
- {
|
|
|
|
- $prefix = str_replace('_', '\\_', $this->dbPrefix);
|
|
|
|
- $stmt = $this->db->query("SHOW TABLE STATUS LIKE '{$prefix}%'");
|
|
|
|
- $records = $size = 0;
|
|
|
|
- $engine = [];
|
|
|
|
-
|
|
|
|
- while ($row = $stmt->fetch()) {
|
|
|
|
- $records += $row['Rows'];
|
|
|
|
- $size += $row['Data_length'] + $row['Index_length'];
|
|
|
|
- if (isset($engine[$row['Engine']])) {
|
|
|
|
- ++$engine[$row['Engine']];
|
|
|
|
- } else {
|
|
|
|
- $engine[$row['Engine']] = 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- \arsort($engine);
|
|
|
|
-
|
|
|
|
- $tmp = [];
|
|
|
|
-
|
|
|
|
- foreach ($engine as $key => $val) {
|
|
|
|
- $tmp[] = "{$key}({$val})";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $other = [];
|
|
|
|
- $stmt = $this->db->query("SHOW VARIABLES LIKE 'character\\_set\\_%'");
|
|
|
|
-
|
|
|
|
- while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
|
|
|
|
- $other[$row[0]] = $row[1];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return [
|
|
|
|
- 'db' => 'MySQL (PDO) ' . $this->db->getAttribute(PDO::ATTR_SERVER_VERSION) . ' : ' . implode(', ', $tmp),
|
|
|
|
- 'records' => $records,
|
|
|
|
- 'size' => $size,
|
|
|
|
- 'server info' => $this->db->getAttribute(PDO::ATTR_SERVER_INFO),
|
|
|
|
- ] + $other;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Формирует карту базы данных
|
|
|
|
- */
|
|
|
|
- public function getMap(): array
|
|
|
|
- {
|
|
|
|
- $vars = [
|
|
|
|
- "{$this->dbPrefix}%",
|
|
|
|
- ];
|
|
|
|
- $query = 'SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE
|
|
|
|
- FROM INFORMATION_SCHEMA.COLUMNS
|
|
|
|
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME LIKE ?s';
|
|
|
|
-
|
|
|
|
- $stmt = $this->db->query($query, $vars);
|
|
|
|
- $result = [];
|
|
|
|
- $table = null;
|
|
|
|
- while ($row = $stmt->fetch()) {
|
|
|
|
- if ($table !== $row['TABLE_NAME']) {
|
|
|
|
- $table = $row['TABLE_NAME'];
|
|
|
|
- $tableNoPref = \substr($table, \strlen($this->dbPrefix));
|
|
|
|
- $result[$tableNoPref] = [];
|
|
|
|
- }
|
|
|
|
- $type = \strtolower($row['DATA_TYPE']);
|
|
|
|
- $result[$tableNoPref][$row['COLUMN_NAME']] = $this->types[$type] ?? 's';
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return $result;
|
|
|
|
- }
|
|
|
|
-}
|
|
|