| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 | <?php/** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */namespace yii\db\sqlite;use yii\db\SqlToken;use yii\helpers\StringHelper;/** * Command represents an SQLite's SQL statement to be executed against a database. * * {@inheritdoc} * * @author Sergey Makinen <sergey@makinen.ru> * @since 2.0.14 */class Command extends \yii\db\Command{    /**     * {@inheritdoc}     */    public function execute()    {        $sql = $this->getSql();        $params = $this->params;        $statements = $this->splitStatements($sql, $params);        if ($statements === false) {            return parent::execute();        }        $result = null;        foreach ($statements as $statement) {            list($statementSql, $statementParams) = $statement;            $this->setSql($statementSql)->bindValues($statementParams);            $result = parent::execute();        }        $this->setSql($sql)->bindValues($params);        return $result;    }    /**     * {@inheritdoc}     */    protected function queryInternal($method, $fetchMode = null)    {        $sql = $this->getSql();        $params = $this->params;        $statements = $this->splitStatements($sql, $params);        if ($statements === false) {            return parent::queryInternal($method, $fetchMode);        }        list($lastStatementSql, $lastStatementParams) = array_pop($statements);        foreach ($statements as $statement) {            list($statementSql, $statementParams) = $statement;            $this->setSql($statementSql)->bindValues($statementParams);            parent::execute();        }        $this->setSql($lastStatementSql)->bindValues($lastStatementParams);        $result = parent::queryInternal($method, $fetchMode);        $this->setSql($sql)->bindValues($params);        return $result;    }    /**     * Splits the specified SQL code into individual SQL statements and returns them     * or `false` if there's a single statement.     * @param string $sql     * @param array $params     * @return string[]|false     */    private function splitStatements($sql, $params)    {        $semicolonIndex = strpos($sql, ';');        if ($semicolonIndex === false || $semicolonIndex === StringHelper::byteLength($sql) - 1) {            return false;        }        $tokenizer = new SqlTokenizer($sql);        $codeToken = $tokenizer->tokenize();        if (count($codeToken->getChildren()) === 1) {            return false;        }        $statements = [];        foreach ($codeToken->getChildren() as $statement) {            $statements[] = [$statement->getSql(), $this->extractUsedParams($statement, $params)];        }        return $statements;    }    /**     * Returns named bindings used in the specified statement token.     * @param SqlToken $statement     * @param array $params     * @return array     */    private function extractUsedParams(SqlToken $statement, $params)    {        preg_match_all('/(?P<placeholder>[:][a-zA-Z0-9_]+)/', $statement->getSql(), $matches, PREG_SET_ORDER);        $result = [];        foreach ($matches as $match) {            $phName = ltrim($match['placeholder'], ':');            if (isset($params[$phName])) {                $result[$phName] = $params[$phName];            } elseif (isset($params[':' . $phName])) {                $result[':' . $phName] = $params[':' . $phName];            }        }        return $result;    }}
 |