Система управления «Сайт PRO»
Версия 20240107

Класс SQLite

Объект $Data: Cms\Root\Data\SQLite наследует Cms\Site\Data\Base

Драйвер для работы с базой данных SQLite.

Исходный код
class SQLite extends \Cms\Site\Data\Base { … }

Методы

init()

$Data->init();

Открытие соединения с базой данных

Возвращает: true; null

Исходный код
    function init() {
        $root = $this->root();
        $Conf = $this->Conf();
        if (!extension_loaded('PDO_sqlite')) {
            $this->addError('Невозможно открыть базу данных');
            return;
        }
        $database = $Conf->get('sql_database', 'sqlite:' . $root . '/cms/database');
        try {
            $this->data = new \PDO($database);
        } catch (\PDOException $e) {
            $this->addError('Невозможно открыть базу данных');
            $this->addError($e->getMessage());
            return;
        }
        $this->database = $database;
        if (!function_exists('sqlite_rand')) {
            function sqlite_rand() {
                return mt_rand(0, 1000000) / 1000000;
            }
        }
        $this->data->sqliteCreateFunction('rand', '\\Cms\\Root\\Data\\sqlite_rand');
        $this->data->query("PRAGMA SYNCHRONOUS=NORMAL");
        return true;
    }

quote()

$Data->quote($text, $stringNull=true);

Экранирование специальных символов в строке и добавление кавычек

Параметры:

ИмяОписание
$text

строка

$stringNull

конвертировать NULL в пустую строку ''

Возвращает: string

Исходный код
    function quote($text, $stringNull = true) {
        if ($text === null && !$stringNull) return 'NULL';
        if ($this->data instanceof \PDO) return $this->data->quote(strval($text));
        return $this->quoteSQLite(strval($text));
    }

query()

$Data->query($q);

Выполнение запроса и получение результата

Параметры:

ИмяОписание
$q

запрос

Возвращает: object; false

Исходный код
    function query($q) {
        if ($this->data instanceof \PDO) {
            $this->clearError();
            if (func_num_args() > 1) {
                $args = func_get_args();
                array_shift($args);
                $q = $this->queryParamsArraySQLite($q, $args);
            }
            $this->query = $q;
            try {
                $result = $this->data->query($q);
            } catch (\PDOException $e) {
                $this->addError('Ошибка запроса «' . $q . '»');
                $this->addError($e->getMessage());
                return false;
            }
            if (!$result) {
                $this->addError('Ошибка запроса «' . $q . '»');
                $this->addError(implode(' ', $this->data->errorInfo()));
            }
            return $result;
        }
        return false;
    }

queryParamsArray()

$Data->queryParamsArray($query, $params);

Добавление параметров к запросу

Параметры:

ИмяОписание
$query

запрос

$params

параметры

Возвращает: string

Исходный код
    function queryParamsArray($query, $params) {
        return $this->queryParamsArraySQLite($query, $params);
    }

numRows()

$Data->numRows(&$result);

Количество строк результата запроса

Параметры:

ИмяОписание
$result

результат запроса

Возвращает: int

Исходный код
    function numRows(&$result) {
        if ($result instanceof \PDOStatement) return $this->numRowsSQLite($result);
        if (is_array($result)) return count($result);
        return 0;
    }

fetch()

$Data->fetch(&$result);

Получение следующей строки результата запроса

Параметры:

ИмяОписание
$result

результат запроса

Возвращает: array; false; null

Исходный код
    function fetch(&$result) {
        if ($result instanceof \PDOStatement) {
            # 2016-02-04
            # Запросы вида SELECT `field` возвращают имя поля "`field`" вместо "field". Исправляем
            if (is_array($row = $result->fetch(\PDO::FETCH_ASSOC))) {
                foreach ($row as $k => $v) if (($_k = trim($k, '`"')) != $k) {
                    $row[$_k] = $v;
                    unset($row[$k]);
                }
            }
            return $row;
        }
        if (is_array($result)) return array_shift($result);
        return false;
    }

fetchArray()

$Data->fetchArray(&$result);

Получение следующей строки результата запроса

Параметры:

ИмяОписание
$result

результат запроса

Возвращает: array; false; null

Исходный код
    function fetchArray(&$result) {
        if ($result instanceof \PDOStatement) return $result->fetch(\PDO::FETCH_NUM);
        if (is_array($result)) return array_values(array_shift($result));
        return false;
    }

numRowsSQLite()

$Data->numRowsSQLite($result);

Реализация подсчета строк результата запроса для SQLite.

Параметры:

ИмяОписание
$result

Результат запроса

Возвращает: int

Исходный код
    function numRowsSQLite($result) {
        $query = trim($result->queryString);
        if (strtoupper(substr($query, 0, 6)) === 'SELECT') {
            $q = "SELECT COUNT(*) FROM ( $query ) `query`";
            if ($_result = $this->data->query($q)) {
                if ($row = $_result->fetch()) {
                    return $row[0];
                }
            }
        }
        return $result->rowCount();
    }

tables()

$Data->tables();

Список таблиц и их определений

Возвращает: array

Исходный код
    function tables() {
        $r = array();
        if ($result = $this->query("SELECT `name`, `sql` FROM `sqlite_master` WHERE `type`='table'")) {
            while ($row = $this->fetch($result)) {
                $r[$row['name']] = $row['sql'];
            }
        }
        return $r;
    }

fields()

$Data->fields($result);

Получение полей запроса

Параметры:

ИмяОписание
$result

результат запроса

Возвращает: array

Исходный код
    function fields($result) {
        $r = array();
        if (is_array($result)) return array_keys(array_shift(array_values($result)));
        if (!$result instanceof \PDOStatement) $result = $this->query("SELECT * FROM `$result` LIMIT 0");
        if ($result) {
            if ($count = $result->columnCount()) for ($i = 0; $i < $count; $i ++) {
                if ($a = $result->getColumnMeta($i)) {
                    $r[] = $a['name'];
                }
            }
        }
        return $r;
    }

tableExists()

$Data->tableExists(Table $Table);
Исходный код
    function tableExists(Table $Table) {
        if ($this->query("SELECT * FROM `{$Table->getName()}` LIMIT 0")) return true;
        return false;
    }

tableFieldExists()

$Data->tableFieldExists(Field $Field);
Исходный код
    function tableFieldExists(Field $Field) {
        if ($this->query("SELECT `{$Field->getName()}` FROM `{$Field->getTable()}` LIMIT 0")) return true;
        return false;
    }

tablePrimaryKey()

$Data->tablePrimaryKey(Table $Table);
Исходный код
    function tablePrimaryKey(Table $Table) {
        $r = array();
        foreach ($this->getRows("PRAGMA table_info(`{$Table->getName()}`)") as $row) if ($row['pk']) {
            $r[$row['pk']] = $row['name'];
        }
        if ($r) {
            ksort($r);
            $r = array_values($r);
        }
        switch (count($r)) {
            case 0:
                return;
            case 1:
                return $r[0];
            default:
                return $r;
        }
    }

tableUniqueExists()

$Data->tableUniqueExists(Field $Field);
Исходный код
    function tableUniqueExists(Field $Field) {
        $name = $Field->getTable() . '_' . $Field->getName() . '_index';
        foreach ($this->getRows("PRAGMA index_list(`{$Field->getTable()}`)") as $row) {
            if ($row['name'] === $name) return $row['unique'] ? true : false;
        }
        return false;
    }

tableIndexExists()

$Data->tableIndexExists(Field $Field);
Исходный код
    function tableIndexExists(Field $Field) {
        $name = $Field->getTable() . '_' . $Field->getName() . '_index';
        foreach ($this->getRows("PRAGMA index_list(`{$Field->getTable()}`)") as $row) {
            if ($row['name'] === $name) return true;
        }
        return false;
    }

tableCreate()

$Data->tableCreate(Table $Table);
Исходный код
    function tableCreate(Table $Table) {
        $query = array();
        foreach ($Table->getEnabledFieldList() as $Field) {
            $_query = array( "`{$Field->getName()}`" );
            if ($type = $Field->getType()) {
                switch ($type) {
                    case 'decimal':
                        $_query[] = 'real';
                        break;
                    case 'varbinary':
                        $_query[] = 'varchar';
                        break;
                    default:
                        $_query[] = $type;
                }
            }
            if (!$Field->isNull()) {
                $default = strval($Field->getDefault());
                if ($default !== 'AUTO_INCREMENT') $_query[] = 'NOT NULL';
                if ($default === 'N') {
                    $_query[] = "DEFAULT 0";
                } elseif ($default === 'ID') {
                    $_query[] = "DEFAULT ''";
                } elseif ($default === 'UUID') {
                    $_query[] = "DEFAULT ''";
                } elseif ($default === 'URL') {
                    $_query[] = "DEFAULT ''";
                } elseif ($default === 'VERSION') {
                    $_query[] = "DEFAULT 1";
                } elseif ($default === 'ORDER') {
                    $_query[] = "DEFAULT 0";
                } elseif ($default === 'LOGIN') {
                    $_query[] = "DEFAULT ''";
                } elseif ($default === 'NOW') {
                    $_query[] = "DEFAULT '0000-00-00 00:00:00'";
                } elseif ($default === 'AUTO_INCREMENT') {
                    $_query[] = $default;
                } elseif ($default === 'CURRENT_TIMESTAMP') {
                    $_query[] = 'DEFAULT ' . $default;
                } elseif ($type === 'int' || $type === 'bigint') {
                    $_query[] = 'DEFAULT ' . (strlen($default) ? $default : '0');
                } elseif ($type === 'float' || $type === 'double' || $type === 'decimal') {
                    $_query[] = 'DEFAULT ' . (strlen($default) ? $default : '0.0');
                } else {
                    $_query[] = 'DEFAULT ' . $this->quote($default);
                }
            }
            if ($type === 'varbinary') $_query[] = 'COLLATE BINARY';
            $query[] = implode(' ', $_query);
        }
        if ($primary = $Table->getPrimaryKey()) {
            if (is_array($primary)) $query[] = "PRIMARY KEY (`" . implode("`, `", $primary) . "`)";
            else $query[] = "PRIMARY KEY (`" . $primary . "`)";
        }
        $query = "CREATE TABLE `{$Table->getName()}` (\n  " . implode(",\n  ", $query) . "\n)";
        if ($this->query($query)) {
            foreach ($Table->getEnabledFieldList() as $Field) {
                if ($Field->isUnique()) {
                    if (!$this->tableAlterUniqueAdd($Field)) return false;
                } elseif ($Field->isIndex()) {
                    if (!$this->tableAlterIndexAdd($Field)) return false;
                }
            }
            return true;
        }
        return false;
    }

tableAlter()

$Data->tableAlter(Table $Table);
Исходный код
    function tableAlter(Table $Table) {
        foreach ($Table->getEnabledFieldList() as $Field) {
            if ($this->tableFieldExists($Field)) {
                $this->tableAlterFieldChange($Field);
            } else {
                if (!$this->tableAlterFieldAdd($Field)) return false;
            }
        }
        if ($primary = $Table->getPrimaryKey()) {
            if ($_primary = $this->tablePrimaryKey($Table)) {
                if ($primary !== $_primary) {
                    if (!$this->tableAlterPrimaryKeyDrop($Table)) return false;
                    if (!$this->tableAlterPrimaryKeyAdd($Table)) return false;
                }
            } else {
                if (!$this->tableAlterPrimaryKeyAdd($Table)) return false;
            }
        } else {
            if ($_primary = $this->tablePrimaryKey($Table)) {
                if (!$this->tableAlterPrimaryKeyDrop($Table)) return false;
            }
        }
        foreach ($Table->getEnabledFieldList() as $Field) {
            if ($Field->isUnique()) {
                if (!$this->tableUniqueExists($Field)) {
                    if ($this->tableIndexExists($Field)) {
                        if (!$this->tableAlterIndexDrop($Field)) return false;
                    }
                    if (!$this->tableAlterUniqueAdd($Field)) return false;
                }
            } elseif ($Field->isIndex()) {
                if ($this->tableUniqueExists($Field)) {
                    if (!$this->tableAlterUniqueDrop($Field)) return false;
                }
                if (!$this->tableIndexExists($Field)) {
                    if (!$this->tableAlterIndexAdd($Field)) return false;
                }
            } else {
                if ($this->tableUniqueExists($Field)) {
                    if (!$this->tableAlterUniqueDrop($Field)) return false;
                }
                if ($this->tableIndexExists($Field)) {
                    if (!$this->tableAlterIndexDrop($Field)) return false;
                }
            }
        }
        return true;
    }

tableAlterFieldAdd()

$Data->tableAlterFieldAdd(Field $Field);
Исходный код
    function tableAlterFieldAdd(Field $Field) {
        $_query = array( "`{$Field->getName()}`" );
        if ($type = $Field->getType()) {
            switch ($type) {
                case 'decimal':
                    $_query[] = 'real';
                    break;
                case 'varbinary':
                    $_query[] = 'varchar';
                    break;
                default:
                    $_query[] = $type;
            }
        }
        if (!$Field->isNull()) {
            $default = strval($Field->getDefault());
            if ($default !== 'AUTO_INCREMENT') $_query[] = 'NOT NULL';
            if ($default === 'N') {
                $_query[] = "DEFAULT 0";
            } elseif ($default === 'ID') {
                $_query[] = "DEFAULT ''";
            } elseif ($default === 'UUID') {
                $_query[] = "DEFAULT ''";
            } elseif ($default === 'URL') {
                $_query[] = "DEFAULT ''";
            } elseif ($default === 'VERSION') {
                $_query[] = "DEFAULT 1";
            } elseif ($default === 'ORDER') {
                $_query[] = "DEFAULT 0";
            } elseif ($default === 'LOGIN') {
                $_query[] = "DEFAULT ''";
            } elseif ($default === 'NOW') {
                $_query[] = "DEFAULT '0000-00-00 00:00:00'";
            } elseif ($default === 'AUTO_INCREMENT') {
                $_query[] = $default;
            } elseif ($default === 'CURRENT_TIMESTAMP') {
                $_query[] = 'DEFAULT ' . $default;
            } elseif ($type === 'int' || $type === 'bigint') {
                $_query[] = 'DEFAULT ' . (strlen($default) ? $default : '0');
            } elseif ($type === 'float' || $type === 'double' || $type === 'decimal') {
                $_query[] = 'DEFAULT ' . (strlen($default) ? $default : '0.0');
            } else {
                $_query[] = 'DEFAULT ' . $this->quote($default);
            }
        }
        if ($type === 'varbinary') $_query[] = 'COLLATE BINARY';
        $query = "ALTER TABLE `{$Field->getTable()}` ADD COLUMN " . implode(' ', $_query);
        if ($this->query($query)) return true;
        return false;
    }

tableAlterFieldChange()

$Data->tableAlterFieldChange(Field $Field);
Исходный код
    function tableAlterFieldChange(Field $Field) {
        return false;
    }

tableAlterFieldDrop()

$Data->tableAlterFieldDrop(Field $Field);
Исходный код
    function tableAlterFieldDrop(Field $Field) {
        if ($this->query("ALTER TABLE `{$Field->getTable()}` DROP COLUMN `{$Field->getName()}`")) return true;
        return false;
    }

tableAlterPrimaryKeyAdd()

$Data->tableAlterPrimaryKeyAdd(Table $Table);
Исходный код
    function tableAlterPrimaryKeyAdd(Table $Table) {
        return false;
    }

tableAlterPrimaryKeyDrop()

$Data->tableAlterPrimaryKeyDrop(Table $Table);
Исходный код
    function tableAlterPrimaryKeyDrop(Table $Table) {
        return false;
    }

tableAlterUniqueAdd()

$Data->tableAlterUniqueAdd(Field $Field);
Исходный код
    function tableAlterUniqueAdd(Field $Field) {
        if ($this->query("CREATE UNIQUE INDEX `{$Field->getTable()}_{$Field->getName()}_index` ON `{$Field->getTable()}` (`{$Field->getName()}`)")) return true;
        return false;
    }

tableAlterUniqueDrop()

$Data->tableAlterUniqueDrop(Field $Field);
Исходный код
    function tableAlterUniqueDrop(Field $Field) {
        if ($this->query("DROP INDEX `{$Field->getTable()}_{$Field->getName()}_index`")) return true;
        return false;
    }

tableAlterIndexAdd()

$Data->tableAlterIndexAdd(Field $Field);
Исходный код
    function tableAlterIndexAdd(Field $Field) {
        if ($this->query("CREATE INDEX `{$Field->getTable()}_{$Field->getName()}_index` ON `{$Field->getTable()}` (`{$Field->getName()}`)")) return true;
        return false;
    }

tableAlterIndexDrop()

$Data->tableAlterIndexDrop(Field $Field);
Исходный код
    function tableAlterIndexDrop(Field $Field) {
        if ($this->query("DROP INDEX `{$Field->getTable()}_{$Field->getName()}_index`")) return true;
        return false;
    }

tableDrop()

$Data->tableDrop(Table $Table);
Исходный код
    function tableDrop(Table $Table) {
        if ($this->query("ALTER TABLE `{$Table->getName()}` RENAME TO `{$Table->getName()}_" . date('YmdHis') . "`")) return true;
        return false;
    }