diff --git a/etc/phing-grammar.rng b/etc/phing-grammar.rng index a023957d51..3714ede900 100644 --- a/etc/phing-grammar.rng +++ b/etc/phing-grammar.rng @@ -4908,6 +4908,16 @@ + + + + + + + + + + @@ -4958,6 +4968,11 @@ + + + + + diff --git a/src/Phing/Task/System/Pdo/DefaultPDOQuerySplitter.php b/src/Phing/Task/System/Pdo/DefaultPDOQuerySplitter.php index 9f584398e4..f44283f547 100644 --- a/src/Phing/Task/System/Pdo/DefaultPDOQuerySplitter.php +++ b/src/Phing/Task/System/Pdo/DefaultPDOQuerySplitter.php @@ -75,10 +75,16 @@ public function nextQuery(): ?string while (($line = $this->sqlReader->readLine()) !== null) { $delimiter = $this->parent->getDelimiter(); $project = $this->parent->getOwningTarget()->getProject(); - $line = $project->replaceProperties(trim($line)); + if (!$this->keepformat) { + $line = trim($line); + } + if ($this->expandProperties) { + $line = $project->replaceProperties($line); + } if ( - ($line != $delimiter) + !$this->keepformat + && ($line !== $delimiter) && (StringHelper::startsWith('//', $line) || StringHelper::startsWith('--', $line) || StringHelper::startsWith('#', $line)) @@ -88,7 +94,7 @@ public function nextQuery(): ?string if ( strlen($line) > 4 - && 'REM ' === strtoupper(substr($line, 0, 4)) + && stripos($line, 'REM ') === 0 ) { continue; } @@ -110,13 +116,13 @@ public function nextQuery(): ?string // SQL defines "--" as a comment to EOL // and in Oracle it may contain a hint // so we cannot just remove it, instead we must end it - if (false !== strpos((string) $line, '--')) { + if (!$this->keepformat && false !== strpos((string) $line, '--')) { $sql .= "\n"; } // DELIM_ROW doesn't need this (as far as i can tell) - if (PDOSQLExecTask::DELIM_NORMAL == $this->delimiterType) { - $reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($delimiter) . ')#'; + if (PDOSQLExecTask::DELIM_NORMAL === $this->delimiterType) { + $reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($delimiter, null) . ')#'; $sqlParts = preg_split($reg, $sql, 0, PREG_SPLIT_DELIM_CAPTURE); $this->sqlBacklog = ''; @@ -133,13 +139,13 @@ public function nextQuery(): ?string } } - if ($hasQuery || (PDOSQLExecTask::DELIM_ROW == $this->delimiterType && $line == $delimiter)) { + if ($hasQuery || (PDOSQLExecTask::DELIM_ROW === $this->delimiterType && $line === $delimiter)) { // this assumes there is always a delimter on the end of the SQL statement. return StringHelper::substring( $sql, 0, strlen($sql) - strlen($delimiter) - - (PDOSQLExecTask::DELIM_ROW == $this->delimiterType ? 2 : 1) + - (PDOSQLExecTask::DELIM_ROW === $this->delimiterType ? 2 : 1) ); } } diff --git a/src/Phing/Task/System/Pdo/DummyPDOQuerySplitter.php b/src/Phing/Task/System/Pdo/DummyPDOQuerySplitter.php index 566cd25437..03fa3fb612 100644 --- a/src/Phing/Task/System/Pdo/DummyPDOQuerySplitter.php +++ b/src/Phing/Task/System/Pdo/DummyPDOQuerySplitter.php @@ -42,10 +42,16 @@ public function nextQuery(): ?string while (($line = $this->sqlReader->readLine()) !== null) { $delimiter = $this->parent->getDelimiter(); $project = $this->parent->getOwningTarget()->getProject(); - $line = $project->replaceProperties(trim($line)); + if (!$this->keepformat) { + $line = trim($line); + } + if ($this->expandProperties) { + $line = $project->replaceProperties($line); + } if ( - ($line != $delimiter) + !$this->keepformat + && ($line !== $delimiter) && (StringHelper::startsWith('//', $line) || StringHelper::startsWith('--', $line) || StringHelper::startsWith('#', $line)) @@ -55,8 +61,15 @@ public function nextQuery(): ?string $sql .= ' ' . $line . "\n"; + // SQL defines "--" as a comment to EOL + // and in Oracle it may contain a hint + // so we cannot just remove it, instead we must end it + if (!$this->keepformat && strpos($line, '--') !== false) { + $sql .= "\n"; + } + /* - * fix issue with PDO and wrong formated multistatements + * fix issue with PDO and wrong formatted multi statements * * @issue 1108 */ diff --git a/src/Phing/Task/System/Pdo/PDOQuerySplitter.php b/src/Phing/Task/System/Pdo/PDOQuerySplitter.php index 89a90c409b..f667a9a055 100644 --- a/src/Phing/Task/System/Pdo/PDOQuerySplitter.php +++ b/src/Phing/Task/System/Pdo/PDOQuerySplitter.php @@ -44,6 +44,9 @@ abstract class PDOQuerySplitter */ protected $sqlReader; + protected $keepformat = false; + protected $expandProperties = true; + /** * Constructor, sets the parent task and reader with SQL source. */ @@ -53,6 +56,16 @@ public function __construct(PDOSQLExecTask $parent, Reader $reader) $this->sqlReader = new BufferedReader($reader); } + public function setKeepformat(bool $keepformat): void + { + $this->keepformat = $keepformat; + } + + public function setExpandProperties(bool $expandProps): void + { + $this->expandProperties = $expandProps; + } + /** * Returns next query from SQL source, null if no more queries left. * diff --git a/src/Phing/Task/System/Pdo/PDOSQLExecFormatterElement.php b/src/Phing/Task/System/Pdo/PDOSQLExecFormatterElement.php index e592c27d72..e515326750 100644 --- a/src/Phing/Task/System/Pdo/PDOSQLExecFormatterElement.php +++ b/src/Phing/Task/System/Pdo/PDOSQLExecFormatterElement.php @@ -75,6 +75,13 @@ class PDOSQLExecFormatterElement */ private $showheaders = true; + /** + * Print trailer. + * + * @var bool + */ + private $showtrailers = true; + /** * Whether to format XML output. * @@ -173,6 +180,10 @@ public function prepare(Location $location): void if ($this->formatter instanceof PlainPDOResultFormatter) { // set any options that apply to the plain formatter $this->formatter->setShowheaders($this->showheaders); + if ($this->showtrailers) { + $this->formatter->setStatementCounter($this->parentTask->getGoodSQL()); + $this->formatter->setShowtrailers($this->showtrailers); + } $this->formatter->setRowdelim($this->rowdelimiter); $this->formatter->setColdelim($this->coldelimiter); } elseif ($this->formatter instanceof XMLPDOResultFormatter) { @@ -274,7 +285,7 @@ public function getOutfile(): ?File */ public function setAppend(bool $append): void { - $this->append = (bool) $append; + $this->append = $append; } /** @@ -298,6 +309,11 @@ public function setShowheaders($showheaders): void $this->showheaders = (bool) $showheaders; } + public function setShowtrailers($showtrailers): void + { + $this->showtrailers = (bool) $showtrailers; + } + /** * Sets the column delimiter. * diff --git a/src/Phing/Task/System/Pdo/PDOSQLExecTask.php b/src/Phing/Task/System/Pdo/PDOSQLExecTask.php index c015f9e84c..234bc89d86 100644 --- a/src/Phing/Task/System/Pdo/PDOSQLExecTask.php +++ b/src/Phing/Task/System/Pdo/PDOSQLExecTask.php @@ -176,6 +176,16 @@ class PDOSQLExecTask extends PDOTask implements Condition */ private $statementCountProperty; + /** + * @var bool + */ + private $keepformat = false; + + /** + * @var bool + */ + private $expandProperties = true; + /** * Set the name of the SQL file to be run. * Required unless statements are enclosed in the build file. @@ -297,6 +307,11 @@ public function setFetchmode($mode): void } } + public function getGoodSQL() + { + return $this->goodSql; + } + /** * Property to set to "true" if a statement throws an error. * @@ -317,6 +332,16 @@ public function setStatementCountProperty(string $statementCountProperty): void $this->statementCountProperty = $statementCountProperty; } + public function setKeepformat(bool $keepformat): void + { + $this->keepformat = $keepformat; + } + + public function setExpandProperties(bool $expandProps): void + { + $this->expandProperties = $expandProps; + } + /** * Load the sql file and then execute it. * @@ -462,6 +487,9 @@ public function runStatements(Reader $reader): void $splitter = new DefaultPDOQuerySplitter($this, $reader, $this->delimiterType); } + $splitter->setExpandProperties($this->expandProperties); + $splitter->setKeepformat($this->keepformat); + try { while (null !== ($query = $splitter->nextQuery())) { $this->log('SQL: ' . $query, Project::MSG_VERBOSE); @@ -553,7 +581,7 @@ protected function execSQL($sql): void $this->log('Failed to execute: ' . $sql, Project::MSG_ERR); $this->setErrorProp(); if ('abort' !== $this->onError) { - $this->log((string)$e, Project::MSG_ERR); + $this->log((string) $e, Project::MSG_ERR); } if ('continue' !== $this->onError) { throw new BuildException('Failed to execute SQL', $e); @@ -572,7 +600,11 @@ protected function getConfiguredFormatters(): array { $formatters = []; foreach ($this->formatters as $fe) { - $formatters[] = $fe->getFormatter(); + $formatter = $fe->getFormatter(); + if ($formatter instanceof PlainPDOResultFormatter) { + $formatter->setStatementCounter($this->goodSql); + } + $formatters[] = $formatter; } return $formatters; @@ -665,7 +697,7 @@ private function setProperty(?string $name, string $value): void */ private function closeQuietly(): void { - if (!$this->isAutocommit() && null !== $this->conn && 'abort' === $this->onError) { + if (null !== $this->conn && 'abort' === $this->onError && !$this->isAutocommit()) { try { $this->conn->rollback(); } catch (PDOException $ex) { diff --git a/src/Phing/Task/System/Pdo/PlainPDOResultFormatter.php b/src/Phing/Task/System/Pdo/PlainPDOResultFormatter.php index 1253f73b52..dc0efba946 100644 --- a/src/Phing/Task/System/Pdo/PlainPDOResultFormatter.php +++ b/src/Phing/Task/System/Pdo/PlainPDOResultFormatter.php @@ -45,6 +45,7 @@ class PlainPDOResultFormatter extends PDOResultFormatter * @var bool */ private $showheaders = true; + private $showtrailers = false; /** * Column delimiter. @@ -61,6 +62,7 @@ class PlainPDOResultFormatter extends PDOResultFormatter * @var string */ private $rowdelimiter = PHP_EOL; + private $statementcounter = 0; /** * Set the showheaders attribute. @@ -72,6 +74,21 @@ public function setShowheaders($v) $this->showheaders = StringHelper::booleanValue($v); } + /** + * Set the showtrailers attribute. + * + * @param bool $v + */ + public function setShowtrailers($v) + { + $this->showtrailers = StringHelper::booleanValue($v); + } + + public function setStatementCounter($count) + { + $this->statementcounter = $count; + } + /** * Sets the column delimiter. * @@ -101,6 +118,10 @@ public function processRow($row) { $line = ''; + if ($this->showtrailers) { + $this->out->write('# ' . $this->statementcounter . ' statement(s) successful executed.' . PHP_EOL); + } + if (!$this->colsprinted && $this->showheaders) { $first = true; foreach ($row as $fieldName => $ignore) { diff --git a/tests/Phing/Task/Optional/PDOTaskTest.php b/tests/Phing/Task/Optional/PDOTaskTest.php index a524d96cc8..d8b8958bf9 100644 --- a/tests/Phing/Task/Optional/PDOTaskTest.php +++ b/tests/Phing/Task/Optional/PDOTaskTest.php @@ -79,4 +79,12 @@ public function testStatementCountProp(): void $this->executeTarget(__FUNCTION__); $this->assertPropertyEquals('statement.count', 2); } + + public function testOptionalAttributes(): void + { + $this->executeTarget(__FUNCTION__); + $this->assertFileExists('result.txt'); + $this->assertStringContainsString('# 3 statement(s) successful executed.', file_get_contents('result.txt')); + @unlink('result.txt'); + } } diff --git a/tests/etc/tasks/ext/pdo/test.xml b/tests/etc/tasks/ext/pdo/test.xml index ee78b296cb..9ef4f079c6 100644 --- a/tests/etc/tasks/ext/pdo/test.xml +++ b/tests/etc/tasks/ext/pdo/test.xml @@ -67,4 +67,26 @@ )]]> + + + DROP TABLE IF EXISTS xxxxx + + + + + +