Passed
Push — main ( ddd1a4...b98cb8 )
by Michiel
08:47
created

DefaultPDOQuerySplitter   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Test Coverage

Coverage 97.92%

Importance

Changes 0
Metric Value
wmc 20
eloc 49
dl 0
loc 122
rs 10
c 0
b 0
f 0
ccs 47
cts 48
cp 0.9792

2 Methods

Rating   Name   Duplication   Size   Complexity  
D nextQuery() 0 84 19
A __construct() 0 4 1
1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 *
19
 * @package phing.tasks.ext.pdo
20
 */
21
22
namespace Phing\Task\System\Pdo;
23
24
use Phing\Io\Reader;
25
use Phing\Util\StringHelper;
26
27
/**
28
 * Splits SQL source into queries using simple regular expressions
29
 *
30
 * Extracted from PDOSQLExecTask::runStatements()
31
 *
32
 * @author  Hans Lellelid <[email protected]>
33
 * @author  Alexey Borzov <[email protected]>
34
 * @package phing.tasks.ext.pdo
35
 */
36
class DefaultPDOQuerySplitter extends PDOQuerySplitter
37
{
38
    /**
39
     * Delimiter type, one of PDOSQLExecTask::DELIM_ROW or PDOSQLExecTask::DELIM_NORMAL
40
     *
41
     * @var string
42
     */
43
    private $delimiterType;
44
45
    /**
46
     * Leftover SQL from previous line
47
     *
48
     * @var string
49
     */
50
    private $sqlBacklog = '';
51
52
    /**
53
     * Constructor, sets the parent task, reader with SQL source and delimiter type
54
     *
55
     * @param PDOSQLExecTask $parent
56
     * @param Reader $reader
57
     * @param string $delimiterType
58
     */
59 2
    public function __construct(PDOSQLExecTask $parent, Reader $reader, $delimiterType = PDOSQLExecTask::DELIM_NORMAL)
60
    {
61 2
        parent::__construct($parent, $reader);
62 2
        $this->delimiterType = $delimiterType;
63 2
    }
64
65
    /**
66
     * Returns next query from SQL source, null if no more queries left
67
     *
68
     * In case of "row" delimiter type this searches for strings containing only
69
     * delimiters. In case of "normal" delimiter type, this uses simple regular
70
     * expression logic to search for delimiters.
71
     *
72
     * @return string|null
73
     */
74 2
    public function nextQuery()
75
    {
76 2
        $sql = "";
77 2
        $hasQuery = false;
78
79 2
        while (($line = $this->sqlReader->readLine()) !== null) {
80 2
            $delimiter = $this->parent->getDelimiter();
81 2
            $project = $this->parent->getOwningTarget()->getProject();
82 2
            $line = $project->replaceProperties(trim($line));
83
84
            if (
85 2
                ($line != $delimiter)
86 2
                && (StringHelper::startsWith("//", $line)
87 2
                    || StringHelper::startsWith("--", $line)
88 2
                    || StringHelper::startsWith("#", $line))
89
            ) {
90 2
                continue;
91
            }
92
93
            if (
94 2
                strlen($line) > 4
95 2
                && strtoupper(substr($line, 0, 4)) === "REM "
96
            ) {
97
                continue;
98
            }
99
100
            // MySQL supports defining new delimiters
101 2
            if (preg_match('/DELIMITER [\'"]?([^\'" $]+)[\'"]?/i', $line, $matches)) {
102 1
                $this->parent->setDelimiter($matches[1]);
103 1
                continue;
104
            }
105
106 2
            if ($this->sqlBacklog !== "") {
107 1
                $sql = $this->sqlBacklog;
108 1
                $this->sqlBacklog = "";
109
            }
110
111 2
            $sql .= " " . $line . "\n";
112
113
            // SQL defines "--" as a comment to EOL
114
            // and in Oracle it may contain a hint
115
            // so we cannot just remove it, instead we must end it
116 2
            if (strpos($line, "--") !== false) {
117 2
                $sql .= "\n";
118
            }
119
120
            // DELIM_ROW doesn't need this (as far as i can tell)
121 2
            if ($this->delimiterType == PDOSQLExecTask::DELIM_NORMAL) {
122 1
                $reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($delimiter) . ")#";
123
124 1
                $sqlParts = preg_split($reg, $sql, 0, PREG_SPLIT_DELIM_CAPTURE);
125 1
                $this->sqlBacklog = "";
126 1
                foreach ($sqlParts as $sqlPart) {
127
                    // we always want to append, even if it's a delim (which will be stripped off later)
128 1
                    $this->sqlBacklog .= $sqlPart;
129
130
                    // we found a single (not enclosed by ' or ") delimiter, so we can use all stuff before the delim as the actual query
131 1
                    if ($sqlPart === $delimiter) {
132 1
                        $sql = $this->sqlBacklog;
133 1
                        $this->sqlBacklog = "";
134 1
                        $hasQuery = true;
135
                    }
136
                }
137
            }
138
139 2
            if ($hasQuery || ($this->delimiterType == PDOSQLExecTask::DELIM_ROW && $line == $delimiter)) {
140
                // this assumes there is always a delimter on the end of the SQL statement.
141 2
                $sql = StringHelper::substring(
142 2
                    $sql,
143 2
                    0,
144 2
                    strlen($sql) - strlen($delimiter)
145 2
                    - ($this->delimiterType == PDOSQLExecTask::DELIM_ROW ? 2 : 1)
146
                );
147
148 2
                return $sql;
149
            }
150
        }
151
152
        // Catch any statements not followed by ;
153 2
        if ($sql !== "") {
154 2
            return $sql;
155
        }
156
157 2
        return null;
158
    }
159
}
160