edde-framework/edde-framework

View on GitHub
src/Edde/Ext/Database/Sqlite/SqliteDriver.php

Summary

Maintainability
A
35 mins
Test Coverage
<?php
    declare(strict_types=1);

    namespace Edde\Ext\Database\Sqlite;

    use Edde\Api\Config\IConfigurable;
    use Edde\Api\Container\LazyContainerTrait;
    use Edde\Api\Database\DriverException;
    use Edde\Api\Query\IQuery;
    use Edde\Api\Query\IStaticQuery;
    use Edde\Api\Query\IStaticQueryFactory;
    use Edde\Common\Config\ConfigurableTrait;
    use Edde\Common\Database\AbstractDriver;
    use Edde\Common\Storage\UniqueException;
    use Edde\Common\Storage\UnknownSourceException;
    use PDO;

    /**
     * Sqlite database support.
     */
    class SqliteDriver extends AbstractDriver implements IConfigurable {
        use LazyContainerTrait;
        use ConfigurableTrait;
        /**
         * @var PDO
         */
        public $pdo;
        /**
         * @var IStaticQueryFactory
         */
        protected $staticQueryFactory;

        /**
         * @inheritdoc
         */
        public function start(bool $exclusive = false) {
            $this->pdo->beginTransaction();
            return $this;
        }

        /**
         * @inheritdoc
         */
        public function commit() {
            $this->pdo->commit();
            return $this;
        }

        /**
         * @inheritdoc
         */
        public function rollback() {
            $this->pdo->rollBack();
            return $this;
        }

        /**
         * @inheritdoc
         */
        public function delimite(string $delimite): string {
            return '"' . str_replace('"', '""', $delimite) . '"';
        }

        /**
         * @inheritdoc
         */
        public function quote(string $quote): string {
            return $this->pdo->quote($quote);
        }

        /**
         * @inheritdoc
         * @throws DriverException
         */
        public function type(string $type): string {
            if (isset($this->typeList[$type]) === false) {
                throw new DriverException(sprintf('Unknown type [%s] for driver [%s].', $type, static::class));
            }
            return $this->typeList[$type];
        }

        /**
         * @inheritdoc
         * @throws UniqueException
         * @throws UnknownSourceException
         * @throws \PDOException
         */
        public function execute(IQuery $query): \PDOStatement {
            return $this->native($this->staticQueryFactory->create($query));
        }

        /**
         * @inheritdoc
         * @throws UnknownSourceException
         * @throws UniqueException
         * @throws \PDOException
         */
        public function native(IStaticQuery $staticQuery) {
            try {
                $statement = $this->pdo->prepare($staticQuery->getQuery());
                $statement->setFetchMode(PDO::FETCH_ASSOC);
                $statement->execute($staticQuery->getParameterList());
                return $statement;
            } catch (\PDOException $exception) {
                if (strpos($message = $exception->getMessage(), 'no such table') !== false) {
                    throw new UnknownSourceException($exception->getMessage(), 0, $exception);
                } else if (strpos($message, 'UNIQUE constraint failed') !== false) {
                    throw new UniqueException($exception->getMessage(), 0, $exception);
                }
                throw $exception;
            }
        }

        /**
         * close this sqlite connection
         *
         * @return $this
         */
        public function close() {
            $this->pdo = null;
            return $this;
        }

        /**
         * @inheritdoc
         * @throws DriverException
         */
        protected function handleInit() {
            parent::handleInit();
            $this->setTypeList([
                null       => 'TEXT',
                'int'      => 'INTEGER',
                'bool'     => 'INTEGER',
                'float'    => 'FLOAT',
                'long'     => 'INTEGER',
                'string'   => 'TEXT',
                'text'     => 'TEXT',
                'datetime' => 'TIMESTAMP',
            ]);
            $this->container->setup();
            $this->staticQueryFactory = $this->container->create(SqliteQueryFactory::class, [$this], __METHOD__);
        }

        protected function handleSetup() {
            parent::handleSetup();
            if (extension_loaded('pdo_sqlite') === false) {
                throw new DriverException('Sqlite PDO is not available, oops!');
            }
            $this->pdo = new PDO($this->dsn->getDsn());
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
            $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
            $this->pdo->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
            $this->pdo->setAttribute(PDO::ATTR_TIMEOUT, 120);
        }
    }