Passed
Push — master ( 9dbdd9...d5a428 )
by Alexander
04:15
created

framework/db/sqlite/Command.php (2 issues)

1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\db\sqlite;
9
10
use yii\db\SqlToken;
11
use yii\helpers\StringHelper;
12
13
/**
14
 * Command represents an SQLite's SQL statement to be executed against a database.
15
 *
16
 * {@inheritdoc}
17
 *
18
 * @author Sergey Makinen <[email protected]>
19
 * @since 2.0.14
20
 */
21
class Command extends \yii\db\Command
22
{
23
    /**
24
     * {@inheritdoc}
25
     */
26 224
    public function execute()
27
    {
28 224
        $sql = $this->getSql();
29 224
        $params = $this->params;
30 224
        $statements = $this->splitStatements($sql, $params);
31 224
        if ($statements === false) {
0 ignored issues
show
The condition $statements === false is always true.
Loading history...
32 219
            return parent::execute();
33
        }
34
35 12
        $result = null;
36 12
        foreach ($statements as $statement) {
37 12
            list($statementSql, $statementParams) = $statement;
38 12
            $this->setSql($statementSql)->bindValues($statementParams);
39 12
            $result = parent::execute();
40
        }
41 12
        $this->setSql($sql)->bindValues($params);
42 12
        return $result;
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 547
    protected function queryInternal($method, $fetchMode = null)
49
    {
50 547
        $sql = $this->getSql();
51 547
        $params = $this->params;
52 547
        $statements = $this->splitStatements($sql, $params);
53 547
        if ($statements === false) {
0 ignored issues
show
The condition $statements === false is always true.
Loading history...
54 547
            return parent::queryInternal($method, $fetchMode);
55
        }
56
57 1
        list($lastStatementSql, $lastStatementParams) = array_pop($statements);
58 1
        foreach ($statements as $statement) {
59 1
            list($statementSql, $statementParams) = $statement;
60 1
            $this->setSql($statementSql)->bindValues($statementParams);
61 1
            parent::execute();
62
        }
63 1
        $this->setSql($lastStatementSql)->bindValues($lastStatementParams);
64 1
        $result = parent::queryInternal($method, $fetchMode);
65 1
        $this->setSql($sql)->bindValues($params);
66 1
        return $result;
67
    }
68
69
    /**
70
     * Splits the specified SQL code into individual SQL statements and returns them
71
     * or `false` if there's a single statement.
72
     * @param string $sql
73
     * @param array $params
74
     * @return string[]|false
75
     */
76 566
    private function splitStatements($sql, $params)
77
    {
78 566
        $semicolonIndex = strpos($sql, ';');
79 566
        if ($semicolonIndex === false || $semicolonIndex === StringHelper::byteLength($sql) - 1) {
80 566
            return false;
81
        }
82
83 12
        $tokenizer = new SqlTokenizer($sql);
84 12
        $codeToken = $tokenizer->tokenize();
85 12
        if (count($codeToken->getChildren()) === 1) {
86
            return false;
87
        }
88
89 12
        $statements = [];
90 12
        foreach ($codeToken->getChildren() as $statement) {
91 12
            $statements[] = [$statement->getSql(), $this->extractUsedParams($statement, $params)];
92
        }
93 12
        return $statements;
94
    }
95
96
    /**
97
     * Returns named bindings used in the specified statement token.
98
     * @param SqlToken $statement
99
     * @param array $params
100
     * @return array
101
     */
102 12
    private function extractUsedParams(SqlToken $statement, $params)
103
    {
104 12
        preg_match_all('/(?P<placeholder>[:][a-zA-Z0-9_]+)/', $statement->getSql(), $matches, PREG_SET_ORDER);
105 12
        $result = [];
106 12
        foreach ($matches as $match) {
107 12
            $phName = ltrim($match['placeholder'], ':');
108 12
            if (isset($params[$phName])) {
109 1
                $result[$phName] = $params[$phName];
110 11
            } elseif (isset($params[':' . $phName])) {
111 12
                $result[':' . $phName] = $params[':' . $phName];
112
            }
113
        }
114 12
        return $result;
115
    }
116
}
117