CC-2166: Packaging Improvements. Moved the Zend app into airtime_mvc. It is now installed to /var/www/airtime. Storage is now set to /srv/airtime/stor. Utils are now installed to /usr/lib/airtime/utils/. Added install/airtime-dircheck.php as a simple test to see if everything is install/uninstalled correctly.

This commit is contained in:
Paul Baranowski 2011-04-14 18:55:04 -04:00
parent 514777e8d2
commit b11cbd8159
4546 changed files with 138 additions and 51 deletions

View file

@ -0,0 +1,84 @@
<?php
/**
* $Id: PDOResultFormatter.php 905 2010-10-05 16:28:03Z mrook $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://phing.info>.
*/
require_once 'phing/system/io/PhingFile.php';
/**
* Abstract
*
* @author Hans Lellelid <hans@xmpl.org>
* @package phing.tasks.ext.pdo
* @since 2.3.0
*/
abstract class PDOResultFormatter
{
/**
* Output writer.
*
* @var Writer
*/
protected $out;
/**
* Sets the output writer.
*
* @param Writer $out
*/
public function setOutput(Writer $out) {
$this->out = $out;
}
/**
* Gets the output writer.
*
* @return Writer
*/
public function getOutput() {
return $this->out;
}
/**
* Gets the preferred output filename for this formatter.
* @return string
*/
abstract public function getPreferredOutfile();
/**
* Perform any initialization.
*/
public function initialize() {
}
/**
* Processes a specific row from PDO result set.
*
* @param array $row Row of PDO result set.
*/
abstract public function processRow($row);
/**
* Perform any final tasks and Close the writer.
*/
public function close() {
$this->out->close();
}
}

View file

@ -0,0 +1,312 @@
<?php
/**
* $Id: PDOSQLExecFormatterElement.php 905 2010-10-05 16:28:03Z mrook $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://phing.info>.
*/
require_once 'phing/system/io/PhingFile.php';
require_once 'phing/tasks/ext/pdo/PlainPDOResultFormatter.php';
require_once 'phing/tasks/ext/pdo/XMLPDOResultFormatter.php';
/**
* A class to represent the nested <formatter> element for PDO SQL results.
*
* This class is inspired by the similarly-named class in the PHPUnit tasks.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package phing.tasks.ext.pdo
* @since 2.3.0
*/
class PDOSQLExecFormatterElement
{
/**
* @var PDOResultFormatter
*/
private $formatter;
/**
* The type of the formatter (used for built-in formatter classes).
* @var string
*/
private $type = "";
/**
* Whether to use file (or write output to phing log).
* @var boolean
*/
private $useFile = true;
/**
* Output file for formatter.
* @var PhingFile
*/
private $outfile;
/**
* Print header columns.
* @var boolean
*/
private $showheaders = true;
/**
* Whether to format XML output.
* @var boolean
*/
private $formatoutput = true;
/**
* Encoding for XML output.
* @var string
*/
private $encoding;
/**
* Column delimiter.
* Defaults to ','
* @var string
*/
private $coldelimiter = ",";
/**
* Row delimiter.
* Defaults to PHP_EOL.
* @var string
*/
private $rowdelimiter = PHP_EOL;
/**
* Append to an existing file or overwrite it?
* @var boolean
*/
private $append = false;
/**
* Parameters for a custom formatter.
* @var array Parameter[]
*/
private $formatterParams = array();
/**
* @var PDOSQLExecTask
*/
private $parentTask;
/**
* Construct a new PDOSQLExecFormatterElement with parent task.
* @param PDOSQLExecTask $parentTask
*/
public function __construct(PDOSQLExecTask $parentTask)
{
$this->parentTask = $parentTask;
}
/**
* Supports nested <param> element (for custom formatter classes).
* @return Parameter
*/
public function createParam() {
$num = array_push($this->parameters, new Parameter());
return $this->parameters[$num-1];
}
/**
* Gets a configured output writer.
* @return Writer
*/
private function getOutputWriter()
{
if ($this->useFile) {
$of = $this->getOutfile();
if (!$of) {
$of = new PhingFile($this->formatter->getPreferredOutfile());
}
return new FileWriter($of, $this->append);
} else {
return $this->getDefaultOutput();
}
}
/**
* Configures wrapped formatter class with any attributes on this element.
*/
public function prepare() {
if (!$this->formatter) {
throw new BuildException("No formatter specified (use type or classname attribute)", $this->getLocation());
}
$out = $this->getOutputWriter();
print "Setting output writer to: " . get_class($out) . "\n";
$this->formatter->setOutput($out);
if ($this->formatter instanceof PlainPDOResultFormatter) {
// set any options that apply to the plain formatter
$this->formatter->setShowheaders($this->showheaders);
$this->formatter->setRowdelim($this->rowdelimiter);
$this->formatter->setColdelim($this->coldelimiter);
} elseif ($this->formatter instanceof XMLPDOResultFormatter) {
// set any options that apply to the xml formatter
$this->formatter->setEncoding($this->encoding);
$this->formatter->setFormatOutput($this->formatoutput);
}
foreach($this->formatterParams as $param) {
$param = new Parameter();
$method = 'set' . $param->getName();
if (!method_exists($this->formatter, $param->getName())) {
throw new BuildException("Formatter " . get_class($this->formatter) . " does not have a $method method.", $this->getLocation());
}
call_user_func(array($this->formatter, $method), $param->getValue());
}
}
/**
* Sets the formatter type.
* @param string $type
*/
function setType($type) {
$this->type = $type;
if ($this->type == "xml") {
$this->formatter = new XMLPDOResultFormatter();
} elseif ($this->type == "plain") {
$this->formatter = new PlainPDOResultFormatter();
} else {
throw new BuildException("Formatter '" . $this->type . "' not implemented");
}
}
/**
* Set classname for a custom formatter (must extend PDOResultFormatter).
* @param string $className
*/
function setClassName($className) {
$classNameNoDot = Phing::import($className);
$this->formatter = new $classNameNoDot();
}
/**
* Set whether to write formatter results to file.
* @param boolean $useFile
*/
function setUseFile($useFile) {
$this->useFile = (boolean) $useFile;
}
/**
* Return whether to write formatter results to file.
* @return boolean
*/
function getUseFile() {
return $this->useFile;
}
/**
* Sets the output file for the formatter results.
* @param PhingFile $outFile
*/
function setOutfile(PhingFile $outfile) {
$this->outfile = $outfile;
}
/**
* Get the output file.
* @return PhingFile
*/
function getOutfile() {
return $this->outfile;
/*
} else {
return new PhingFile($this->formatter->getPreferredOutfile());
}*/
}
/**
* whether output should be appended to or overwrite
* an existing file. Defaults to false.
* @param boolean $append
*/
public function setAppend($append) {
$this->append = (boolean) $append;
}
/**
* Whether output should be appended to file.
* @return boolean
*/
public function getAppend() {
return $this->append;
}
/**
* Print headers for result sets from the
* statements; optional, default true.
* @param boolean $showheaders
*/
public function setShowheaders($showheaders) {
$this->showheaders = (boolean) $showheaders;
}
/**
* Sets the column delimiter.
* @param string $v
*/
public function setColdelim($v) {
$this->coldelimiter = $v;
}
/**
* Sets the row delimiter.
* @param string $v
*/
public function setRowdelim($v) {
$this->rowdelimiter = $v;
}
/**
* Set the DOM document encoding.
* @param string $v
*/
public function setEncoding($v) {
$this->encoding = $v;
}
/**
* @param boolean $v
*/
public function setFormatOutput($v) {
$this->formatOutput = (boolean) $v;
}
/**
* Gets a default output writer for this task.
* @return Writer
*/
private function getDefaultOutput()
{
return new LogWriter($this->parentTask);
}
/**
* Gets the formatter that has been configured based on this element.
* @return PDOResultFormatter
*/
function getFormatter() {
return $this->formatter;
}
}

View file

@ -0,0 +1,646 @@
<?php
/*
* $Id: PDOSQLExecTask.php 905 2010-10-05 16:28:03Z mrook $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://phing.info>.
*/
require_once 'phing/tasks/ext/pdo/PDOTask.php';
include_once 'phing/system/io/StringReader.php';
include_once 'phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php';
/**
* Executes a series of SQL statements on a database using PDO.
*
* <p>Statements can
* either be read in from a text file using the <i>src</i> attribute or from
* between the enclosing SQL tags.</p>
*
* <p>Multiple statements can be provided, separated by semicolons (or the
* defined <i>delimiter</i>). Individual lines within the statements can be
* commented using either --, // or REM at the start of the line.</p>
*
* <p>The <i>autocommit</i> attribute specifies whether auto-commit should be
* turned on or off whilst executing the statements. If auto-commit is turned
* on each statement will be executed and committed. If it is turned off the
* statements will all be executed as one transaction.</p>
*
* <p>The <i>onerror</i> attribute specifies how to proceed when an error occurs
* during the execution of one of the statements.
* The possible values are: <b>continue</b> execution, only show the error;
* <b>stop</b> execution and commit transaction;
* and <b>abort</b> execution and transaction and fail task.</p>
*
* @author Hans Lellelid <hans@xmpl.org> (Phing)
* @author Jeff Martin <jeff@custommonkey.org> (Ant)
* @author Michael McCallum <gholam@xtra.co.nz> (Ant)
* @author Tim Stephenson <tim.stephenson@sybase.com> (Ant)
* @package phing.tasks.ext.pdo
* @version $Revision: 905 $
*/
class PDOSQLExecTask extends PDOTask {
/**
* Count of how many statements were executed successfully.
* @var int
*/
private $goodSql = 0;
/**
* Count of total number of SQL statements.
* @var int
*/
private $totalSql = 0;
const DELIM_ROW = "row";
const DELIM_NORMAL = "normal";
/**
* Database connection
* @var PDO
*/
private $conn = null;
/**
* Files to load
* @var array FileSet[]
*/
private $filesets = array();
/**
* Files to load
* @var array FileList[]
*/
private $filelists = array();
/**
* Formatter elements.
* @var array PDOSQLExecFormatterElement[]
*/
private $formatters = array();
/**
* SQL statement
* @var PDOStatement
*/
private $statement;
/**
* SQL input file
* @var PhingFile
*/
private $srcFile;
/**
* SQL input command
* @var string
*/
private $sqlCommand = "";
/**
* SQL transactions to perform
*/
private $transactions = array();
/**
* SQL Statement delimiter (for parsing files)
* @var string
*/
private $delimiter = ";";
/**
* The delimiter type indicating whether the delimiter will
* only be recognized on a line by itself
*/
private $delimiterType = "normal"; // can't use constant just defined
/**
* Action to perform if an error is found
**/
private $onError = "abort";
/**
* Encoding to use when reading SQL statements from a file
*/
private $encoding = null;
/**
* Fetch mode for PDO select queries.
* @var int
*/
private $fetchMode;
/**
* Set the name of the SQL file to be run.
* Required unless statements are enclosed in the build file
*/
public function setSrc(PhingFile $srcFile) {
$this->srcFile = $srcFile;
}
/**
* Set an inline SQL command to execute.
* NB: Properties are not expanded in this text.
*/
public function addText($sql) {
$this->sqlCommand .= $sql;
}
/**
* Adds a set of files (nested fileset attribute).
*/
public function addFileset(FileSet $set) {
$this->filesets[] = $set;
}
/**
* Adds a set of files (nested filelist attribute).
*/
public function addFilelist(FileList $list) {
$this->filelists[] = $list;
}
/**
* Creates a new PDOSQLExecFormatterElement for <formatter> element.
* @return PDOSQLExecFormatterElement
*/
public function createFormatter()
{
$fe = new PDOSQLExecFormatterElement($this);
$this->formatters[] = $fe;
return $fe;
}
/**
* Add a SQL transaction to execute
*/
public function createTransaction() {
$t = new PDOSQLExecTransaction($this);
$this->transactions[] = $t;
return $t;
}
/**
* Set the file encoding to use on the SQL files read in
*
* @param encoding the encoding to use on the files
*/
public function setEncoding($encoding) {
$this->encoding = $encoding;
}
/**
* Set the statement delimiter.
*
* <p>For example, set this to "go" and delimitertype to "ROW" for
* Sybase ASE or MS SQL Server.</p>
*
* @param delimiter
*/
public function setDelimiter($delimiter)
{
$this->delimiter = $delimiter;
}
/**
* Set the Delimiter type for this sql task. The delimiter type takes two
* values - normal and row. Normal means that any occurence of the delimiter
* terminate the SQL command whereas with row, only a line containing just
* the delimiter is recognized as the end of the command.
*
* @param string $delimiterType
*/
public function setDelimiterType($delimiterType)
{
$this->delimiterType = $delimiterType;
}
/**
* Action to perform when statement fails: continue, stop, or abort
* optional; default &quot;abort&quot;
*/
public function setOnerror($action) {
$this->onError = $action;
}
/**
* Sets the fetch mode to use for the PDO resultset.
* @param mixed $mode The PDO fetchmode integer or constant name.
*/
public function setFetchmode($mode) {
if (is_numeric($mode)) {
$this->fetchMode = (int) $mode;
} else {
if (defined($mode)) {
$this->fetchMode = constant($mode);
} else {
throw new BuildException("Invalid PDO fetch mode specified: " . $mode, $this->getLocation());
}
}
}
/**
* Gets a default output writer for this task.
* @return Writer
*/
private function getDefaultOutput()
{
return new LogWriter($this);
}
/**
* Load the sql file and then execute it
* @throws BuildException
*/
public function main() {
// Set a default fetchmode if none was specified
// (We're doing that here to prevent errors loading the class is PDO is not available.)
if ($this->fetchMode === null) {
$this->fetchMode = PDO::FETCH_BOTH;
}
// Initialize the formatters here. This ensures that any parameters passed to the formatter
// element get passed along to the actual formatter object
foreach($this->formatters as $fe) {
$fe->prepare();
}
$savedTransaction = array();
for($i=0,$size=count($this->transactions); $i < $size; $i++) {
$savedTransaction[] = clone $this->transactions[$i];
}
$savedSqlCommand = $this->sqlCommand;
$this->sqlCommand = trim($this->sqlCommand);
try {
if ($this->srcFile === null && $this->sqlCommand === ""
&& empty($this->filesets) && empty($this->filelists)
&& count($this->transactions) === 0) {
throw new BuildException("Source file or fileset/filelist, "
. "transactions or sql statement "
. "must be set!", $this->location);
}
if ($this->srcFile !== null && !$this->srcFile->exists()) {
throw new BuildException("Source file does not exist!", $this->location);
}
// deal with the filesets
foreach($this->filesets as $fs) {
$ds = $fs->getDirectoryScanner($this->project);
$srcDir = $fs->getDir($this->project);
$srcFiles = $ds->getIncludedFiles();
// Make a transaction for each file
foreach($srcFiles as $srcFile) {
$t = $this->createTransaction();
$t->setSrc(new PhingFile($srcDir, $srcFile));
}
}
// process filelists
foreach($this->filelists as $fl) {
$srcDir = $fl->getDir($this->project);
$srcFiles = $fl->getFiles($this->project);
// Make a transaction for each file
foreach($srcFiles as $srcFile) {
$t = $this->createTransaction();
$t->setSrc(new PhingFile($srcDir, $srcFile));
}
}
// Make a transaction group for the outer command
$t = $this->createTransaction();
if ($this->srcFile) $t->setSrc($this->srcFile);
$t->addText($this->sqlCommand);
$this->conn = $this->getConnection();
try {
$this->statement = null;
// Initialize the formatters.
$this->initFormatters();
try {
// Process all transactions
for ($i=0,$size=count($this->transactions); $i < $size; $i++) {
if (!$this->isAutocommit()) {
$this->log("Beginning transaction", Project::MSG_VERBOSE);
$this->conn->beginTransaction();
}
$this->transactions[$i]->runTransaction();
if (!$this->isAutocommit()) {
$this->log("Commiting transaction", Project::MSG_VERBOSE);
$this->conn->commit();
}
}
} catch (Exception $e) {
throw $e;
}
} catch (IOException $e) {
if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") {
try {
$this->conn->rollback();
} catch (PDOException $ex) {}
}
throw new BuildException($e->getMessage(), $this->location);
} catch (PDOException $e){
if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") {
try {
$this->conn->rollback();
} catch (PDOException $ex) {}
}
throw new BuildException($e->getMessage(), $this->location);
}
// Close the formatters.
$this->closeFormatters();
$this->log($this->goodSql . " of " . $this->totalSql .
" SQL statements executed successfully");
} catch (Exception $e) {
$this->transactions = $savedTransaction;
$this->sqlCommand = $savedSqlCommand;
throw $e;
}
// finally {
$this->transactions = $savedTransaction;
$this->sqlCommand = $savedSqlCommand;
}
/**
* read in lines and execute them
* @throws PDOException, IOException
*/
public function runStatements(Reader $reader) {
$sql = "";
$line = "";
$sqlBacklog = "";
$hasQuery = false;
$in = new BufferedReader($reader);
try {
while (($line = $in->readLine()) !== null) {
$line = trim($line);
$line = ProjectConfigurator::replaceProperties($this->project, $line,
$this->project->getProperties());
if (($line != $this->delimiter) && (
StringHelper::startsWith("//", $line) ||
StringHelper::startsWith("--", $line) ||
StringHelper::startsWith("#", $line))) {
continue;
}
if (strlen($line) > 4
&& strtoupper(substr($line,0, 4)) == "REM ") {
continue;
}
// MySQL supports defining new delimiters
if (preg_match('/DELIMITER [\'"]?([^\'" $]+)[\'"]?/i', $line, $matches)) {
$this->setDelimiter($matches[1]);
continue;
}
if ($sqlBacklog !== "") {
$sql = $sqlBacklog;
$sqlBacklog = "";
}
$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 (strpos($line, "--") !== false) {
$sql .= "\n";
}
// DELIM_ROW doesn't need this (as far as i can tell)
if ($this->delimiterType == self::DELIM_NORMAL) {
$reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($this->delimiter) . ")#";
$sqlParts = preg_split($reg, $sql, 0, PREG_SPLIT_DELIM_CAPTURE);
$sqlBacklog = "";
foreach ($sqlParts as $sqlPart) {
// we always want to append, even if it's a delim (which will be stripped off later)
$sqlBacklog .= $sqlPart;
// we found a single (not enclosed by ' or ") delimiter, so we can use all stuff before the delim as the actual query
if ($sqlPart === $this->delimiter) {
$sql = $sqlBacklog;
$sqlBacklog = "";
$hasQuery = true;
}
}
}
if ($hasQuery || ($this->delimiterType == self::DELIM_ROW && $line == $this->delimiter)) {
// this assumes there is always a delimter on the end of the SQL statement.
$sql = StringHelper::substring($sql, 0, strlen($sql) - 1 - strlen($this->delimiter));
$this->log("SQL: " . $sql, Project::MSG_VERBOSE);
$this->execSQL($sql);
$sql = "";
$hasQuery = false;
}
}
// Catch any statements not followed by ;
if ($sql !== "") {
$this->execSQL($sql);
}
} catch (PDOException $e) {
throw $e;
}
}
/**
* Whether the passed-in SQL statement is a SELECT statement.
* This does a pretty simple match, checking to see if statement starts with
* 'select' (but not 'select into').
*
* @param string $sql
* @return boolean Whether specified SQL looks like a SELECT query.
*/
protected function isSelectSql($sql)
{
$sql = trim($sql);
return (stripos($sql, 'select') === 0 && stripos($sql, 'select into ') !== 0);
}
/**
* Exec the sql statement.
* @throws PDOException
*/
protected function execSQL($sql) {
// Check and ignore empty statements
if (trim($sql) == "") {
return;
}
try {
$this->totalSql++;
$this->statement = $this->conn->prepare($sql);
$this->statement->execute();
$this->log($this->statement->rowCount() . " rows affected", Project::MSG_VERBOSE);
// only call processResults() for statements that return actual data (such as 'select')
if ($this->statement->columnCount() > 0)
{
$this->processResults();
}
$this->statement->closeCursor();
$this->statement = null;
$this->goodSql++;
} catch (PDOException $e) {
$this->log("Failed to execute: " . $sql, Project::MSG_ERR);
if ($this->onError != "continue") {
throw new BuildException("Failed to execute SQL", $e);
}
$this->log($e->getMessage(), Project::MSG_ERR);
}
}
/**
* Returns configured PDOResultFormatter objects (which were created from PDOSQLExecFormatterElement objects).
* @return array PDOResultFormatter[]
*/
protected function getConfiguredFormatters()
{
$formatters = array();
foreach ($this->formatters as $fe) {
$formatters[] = $fe->getFormatter();
}
return $formatters;
}
/**
* Initialize the formatters.
*/
protected function initFormatters() {
$formatters = $this->getConfiguredFormatters();
foreach ($formatters as $formatter) {
$formatter->initialize();
}
}
/**
* Run cleanup and close formatters.
*/
protected function closeFormatters() {
$formatters = $this->getConfiguredFormatters();
foreach ($formatters as $formatter) {
$formatter->close();
}
}
/**
* Passes results from query to any formatters.
* @throw PDOException
*/
protected function processResults() {
try {
$this->log("Processing new result set.", Project::MSG_VERBOSE);
$formatters = $this->getConfiguredFormatters();
while ($row = $this->statement->fetch($this->fetchMode)) {
foreach ($formatters as $formatter) {
$formatter->processRow($row);
}
}
} catch (Exception $x) {
$this->log("Error processing reults: " . $x->getMessage(), Project::MSG_ERR);
foreach ($formatters as $formatter) {
$formatter->close();
}
throw $x;
}
}
}
/**
* "Inner" class that contains the definition of a new transaction element.
* Transactions allow several files or blocks of statements
* to be executed using the same JDBC connection and commit
* operation in between.
*
* @package phing.tasks.ext.pdo
*/
class PDOSQLExecTransaction {
private $tSrcFile = null;
private $tSqlCommand = "";
private $parent;
function __construct($parent)
{
// Parent is required so that we can log things ...
$this->parent = $parent;
}
public function setSrc(PhingFile $src)
{
$this->tSrcFile = $src;
}
public function addText($sql)
{
$this->tSqlCommand .= $sql;
}
/**
* @throws IOException, PDOException
*/
public function runTransaction()
{
if (!empty($this->tSqlCommand)) {
$this->parent->log("Executing commands", Project::MSG_INFO);
$this->parent->runStatements(new StringReader($this->tSqlCommand));
}
if ($this->tSrcFile !== null) {
$this->parent->log("Executing file: " . $this->tSrcFile->getAbsolutePath(),
Project::MSG_INFO);
$reader = new FileReader($this->tSrcFile);
$this->parent->runStatements($reader);
$reader->close();
}
}
}

View file

@ -0,0 +1,217 @@
<?php
/*
* $Id: PDOTask.php 905 2010-10-05 16:28:03Z mrook $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://phing.info>.
*/
require_once 'phing/Task.php';
include_once 'phing/types/Reference.php';
/**
* Handles PDO configuration needed by SQL type tasks.
*
* @author Hans Lellelid <hans@xmpl.org> (Phing)
* @author Nick Chalko <nick@chalko.com> (Ant)
* @author Jeff Martin <jeff@custommonkey.org> (Ant)
* @author Michael McCallum <gholam@xtra.co.nz> (Ant)
* @author Tim Stephenson <tim.stephenson@sybase.com> (Ant)
* @version $Revision: 905 $
* @package phing.tasks.system
*/
abstract class PDOTask extends Task {
private $caching = true;
/**
* Autocommit flag. Default value is false
*/
private $autocommit = false;
/**
* DB url.
*/
private $url;
/**
* User name.
*/
private $userId;
/**
* Password
*/
private $password;
/**
* RDBMS Product needed for this SQL.
**/
private $rdbms;
/**
* Initialize CreoleTask.
* This method includes any necessary Creole libraries and triggers
* appropriate error if they cannot be found. This is not done in header
* because we may want this class to be loaded w/o triggering an error.
*/
function init() {
if (!class_exists('PDO')) {
throw new Exception("PDOTask depends on PDO feature being included in PHP.");
}
}
/**
* Caching loaders / driver. This is to avoid
* getting an OutOfMemoryError when calling this task
* multiple times in a row; default: true
* @param $enable
*/
public function setCaching($enable) {
$this->caching = $enable;
}
/**
* Sets the database connection URL; required.
* @param url The url to set
*/
public function setUrl($url) {
$this->url = $url;
}
/**
* Sets the password; required.
* @param password The password to set
*/
public function setPassword($password) {
$this->password = $password;
}
/**
* Auto commit flag for database connection;
* optional, default false.
* @param autocommit The autocommit to set
*/
public function setAutocommit($autocommit) {
$this->autocommit = $autocommit;
}
/**
* Sets the version string, execute task only if
* rdbms version match; optional.
* @param version The version to set
*/
public function setVersion($version) {
$this->version = $version;
}
protected function getLoaderMap() {
return self::$loaderMap;
}
/**
* Creates a new Connection as using the driver, url, userid and password specified.
* The calling method is responsible for closing the connection.
* @return Connection the newly created connection.
* @throws BuildException if the UserId/Password/Url is not set or there is no suitable driver or the driver fails to load.
*/
protected function getConnection() {
if ($this->url === null) {
throw new BuildException("Url attribute must be set!", $this->location);
}
try {
$this->log("Connecting to " . $this->getUrl(), Project::MSG_VERBOSE);
$user = null;
$pass = null;
if ($this->userId) {
$user = $this->getUserId();
}
if ($this->password) {
$pass = $this->getPassword();
}
$conn = new PDO($this->getUrl(), $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if ($this->autocommit) {
try {
$conn->setAttribute(PDO::ATTR_AUTOCOMMIT, $this->autocommit);
} catch (PDOException $pe) {
$this->log("Unable to enable auto-commit for this database: " . $pe->getMessage(), Project::MSG_WARN);
}
}
return $conn;
} catch (SQLException $e) {
throw new BuildException($e->getMessage(), $this->location);
}
}
public function isCaching($value) {
$this->caching = $value;
}
/**
* Gets the autocommit.
* @return Returns a boolean
*/
public function isAutocommit() {
return $this->autocommit;
}
/**
* Gets the url.
* @return Returns a String
*/
public function getUrl() {
return $this->url;
}
/**
* Gets the userId.
* @return Returns a String
*/
public function getUserId() {
return $this->userId;
}
/**
* Set the user name for the connection; required.
* @param userId The userId to set
*/
public function setUserid($userId) {
$this->userId = $userId;
}
/**
* Gets the password.
* @return Returns a String
*/
public function getPassword() {
return $this->password;
}
}

View file

@ -0,0 +1,130 @@
<?php
/**
* $Id: PlainPDOResultFormatter.php 905 2010-10-05 16:28:03Z mrook $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://phing.info>.
*/
require_once 'phing/system/io/PhingFile.php';
require_once 'phing/tasks/ext/pdo/PDOResultFormatter.php';
/**
* Plain text formatter for PDO results.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package phing.tasks.ext.pdo
* @since 2.3.0
*/
class PlainPDOResultFormatter extends PDOResultFormatter
{
/**
* Have column headers been printed?
* @var boolean
*/
private $colsprinted = false;
/**
* Whether to show headers.
* @var boolean
*/
private $showheaders = true;
/**
* Column delimiter.
* Defaults to ','
* @var string
*/
private $coldelimiter = ",";
/**
* Row delimiter.
* Defaults to PHP_EOL.
* @var string
*/
private $rowdelimiter = PHP_EOL;
/**
* Set the showheaders attribute.
* @param boolean $v
*/
public function setShowheaders($v) {
$this->showheaders = StringHelper::booleanValue($v);
}
/**
* Sets the column delimiter.
* @param string $v
*/
public function setColdelim($v) {
$this->coldelimiter = $v;
}
/**
* Sets the row delimiter.
* @param string $v
*/
public function setRowdelim($v) {
$this->rowdelimiter = $v;
}
/**
* Processes a specific row from PDO result set.
*
* @param array $row Row of PDO result set.
*/
public function processRow($row) {
if (!$this->colsprinted && $this->showheaders) {
$first = true;
foreach($row as $fieldName => $ignore) {
if ($first) $first = false; else $line .= ",";
$line .= $fieldName;
}
$this->out->write($line);
$this->out->write(PHP_EOL);
$line = "";
$colsprinted = true;
} // if show headers
$first = true;
foreach($row as $columnValue) {
if ($columnValue != null) {
$columnValue = trim($columnValue);
}
if ($first) {
$first = false;
} else {
$line .= $this->coldelimiter;
}
$line .= $columnValue;
}
$this->out->write($line);
$this->out->write($this->rowdelimiter);
}
public function getPreferredOutfile()
{
return new PhingFile('results.txt');
}
}

View file

@ -0,0 +1,141 @@
<?php
/**
* $Id: XMLPDOResultFormatter.php 905 2010-10-05 16:28:03Z mrook $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://phing.info>.
*/
require_once 'phing/system/io/PhingFile.php';
require_once 'phing/tasks/ext/pdo/PDOResultFormatter.php';
/**
* XML formatter for PDO results.
*
* This class reprsents the output of a query using a simple XML schema.
*
* <results>
* <row>
* <col name="id">value</col>
* <col name="name">value2</col>
* </row>
* <row>
* <col name="id">value</col>
* <col name="name">value2</col>
* </row>
* </results>
*
* The actual names of the colums will depend on the fetchmode that was used
* with PDO.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package phing.tasks.ext.pdo
* @since 2.3.0
*/
class XMLPDOResultFormatter extends PDOResultFormatter {
/**
* The XML document being created.
* @var DOMDocument
*/
private $doc;
/**
* @var DOMElement
*/
private $rootNode;
/**
* XML document encoding
*
* @var string
*/
private $encoding;
/**
* @var boolean
*/
private $formatOutput = true;
/**
* Set the DOM document encoding.
* @param string $v
*/
public function setEncoding($v) {
$this->encoding = $v;
}
/**
* @param boolean $v
*/
public function setFormatOutput($v) {
$this->formatOutput = (boolean) $v;
}
public function initialize() {
$this->doc = new DOMDocument("1.0", $this->encoding);
$this->rootNode = $this->doc->createElement('results');
$this->doc->appendChild($this->rootNode);
$this->doc->formatOutput = $this->formatOutput;
}
/**
* Processes a specific row from PDO result set.
*
* @param array $row Row of PDO result set.
*/
public function processRow($row) {
$rowNode = $this->doc->createElement('row');
$this->rootNode->appendChild($rowNode);
foreach($row as $columnName => $columnValue) {
$colNode = $this->doc->createElement('column');
$colNode->setAttribute('name', $columnName);
if ($columnValue != null) {
$columnValue = trim($columnValue);
$colNode->nodeValue = $columnValue;
}
$rowNode->appendChild($colNode);
}
}
/**
* Gets a preferred filename for an output file.
*
* If no filename is specified, this is where the results will be placed
* (unless usefile=false).
*
* @return string
*/
public function getPreferredOutfile()
{
return new PhingFile('results.xml');
}
/**
* Write XML to file and free the DOM objects.
*/
public function close() {
$this->out->write($this->doc->saveXML());
$this->rootNode = null;
$this->doc = null;
parent::close();
}
}