Completed
Push — master ( 20b0ec...0fa80a )
by Siad
15:26
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
eloc 49
c 0
b 0
f 0
dl 0
loc 122
ccs 47
cts 48
cp 0.9792
rs 10
wmc 20

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
D nextQuery() 0 84 19
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
/**
23
 * Splits SQL source into queries using simple regular expressions
24
 *
25
 * Extracted from PDOSQLExecTask::runStatements()
26
 *
27
 * @author  Hans Lellelid <[email protected]>
28
 * @author  Alexey Borzov <[email protected]>
29
 * @package phing.tasks.ext.pdo
30
 */
31
class DefaultPDOQuerySplitter extends PDOQuerySplitter
32
{
33
    /**
34
     * Delimiter type, one of PDOSQLExecTask::DELIM_ROW or PDOSQLExecTask::DELIM_NORMAL
35
     *
36
     * @var string
37
     */
38
    private $delimiterType;
39
40
    /**
41
     * Leftover SQL from previous line
42
     *
43
     * @var string
44
     */
45
    private $sqlBacklog = '';
46
47
    /**
48
     * Constructor, sets the parent task, reader with SQL source and delimiter type
49
     *
50
     * @param PDOSQLExecTask $parent
51
     * @param Reader $reader
52
     * @param string $delimiterType
53
     */
54 2
    public function __construct(PDOSQLExecTask $parent, Reader $reader, $delimiterType = PDOSQLExecTask::DELIM_NORMAL)
55
    {
56 2
        parent::__construct($parent, $reader);
57 2
        $this->delimiterType = $delimiterType;
58 2
    }
59
60
    /**
61
     * Returns next query from SQL source, null if no more queries left
62
     *
63
     * In case of "row" delimiter type this searches for strings containing only
64
     * delimiters. In case of "normal" delimiter type, this uses simple regular
65
     * expression logic to search for delimiters.
66
     *
67
     * @return string|null
68
     */
69 2
    public function nextQuery()
70
    {
71 2
        $sql = "";
72 2
        $hasQuery = false;
73
74 2
        while (($line = $this->sqlReader->readLine()) !== null) {
75 2
            $delimiter = $this->parent->getDelimiter();
76 2
            $project = $this->parent->getOwningTarget()->getProject();
77 2
            $line = $project->replaceProperties(trim($line));
78
79
            if (
80 2
                ($line != $delimiter)
81 2
                && (StringHelper::startsWith("//", $line)
82 2
                    || StringHelper::startsWith("--", $line)
83 2
                    || StringHelper::startsWith("#", $line))
84
            ) {
85 2
                continue;
86
            }
87
88
            if (
89 2
                strlen($line) > 4
90 2
                && strtoupper(substr($line, 0, 4)) == "REM "
91
            ) {
92
                continue;
93
            }
94
95
            // MySQL supports defining new delimiters
96 2
            if (preg_match('/DELIMITER [\'"]?([^\'" $]+)[\'"]?/i', $line, $matches)) {
97 1
                $this->parent->setDelimiter($matches[1]);
98 1
                continue;
99
            }
100
101 2
            if ($this->sqlBacklog !== "") {
102 1
                $sql = $this->sqlBacklog;
103 1
                $this->sqlBacklog = "";
104
            }
105
106 2
            $sql .= " " . $line . "\n";
107
108
            // SQL defines "--" as a comment to EOL
109
            // and in Oracle it may contain a hint
110
            // so we cannot just remove it, instead we must end it
111 2
            if (strpos($line, "--") !== false) {
112 2
                $sql .= "\n";
113
            }
114
115
            // DELIM_ROW doesn't need this (as far as i can tell)
116 2
            if ($this->delimiterType == PDOSQLExecTask::DELIM_NORMAL) {
117 1
                $reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($delimiter) . ")#";
118
119 1
                $sqlParts = preg_split($reg, $sql, 0, PREG_SPLIT_DELIM_CAPTURE);
120 1
                $this->sqlBacklog = "";
121 1
                foreach ($sqlParts as $sqlPart) {
122
                    // we always want to append, even if it's a delim (which will be stripped off later)
123 1
                    $this->sqlBacklog .= $sqlPart;
124
125
                    // we found a single (not enclosed by ' or ") delimiter, so we can use all stuff before the delim as the actual query
126 1
                    if ($sqlPart === $delimiter) {
127 1
                        $sql = $this->sqlBacklog;
128 1
                        $this->sqlBacklog = "";
129 1
                        $hasQuery = true;
130
                    }
131
                }
132
            }
133
134 2
            if ($hasQuery || ($this->delimiterType == PDOSQLExecTask::DELIM_ROW && $line == $delimiter)) {
135
                // this assumes there is always a delimter on the end of the SQL statement.
136 2
                $sql = StringHelper::substring(
137 2
                    $sql,
138 2
                    0,
139 2
                    strlen($sql) - strlen($delimiter)
140 2
                    - ($this->delimiterType == PDOSQLExecTask::DELIM_ROW ? 2 : 1)
141
                );
142
143 2
                return $sql;
144
            }
145
        }
146
147
        // Catch any statements not followed by ;
148 2
        if ($sql !== "") {
149 2
            return $sql;
150
        }
151
152 2
        return null;
153
    }
154
}
155