summaryrefslogtreecommitdiffstats
path: root/3dparty/MDB2/Schema/Tool.php
diff options
context:
space:
mode:
Diffstat (limited to '3dparty/MDB2/Schema/Tool.php')
-rw-r--r--3dparty/MDB2/Schema/Tool.php560
1 files changed, 560 insertions, 0 deletions
diff --git a/3dparty/MDB2/Schema/Tool.php b/3dparty/MDB2/Schema/Tool.php
new file mode 100644
index 00000000000..9689a0f6d73
--- /dev/null
+++ b/3dparty/MDB2/Schema/Tool.php
@@ -0,0 +1,560 @@
+<?php
+/**
+ * PHP versions 4 and 5
+ *
+ * Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,
+ * Stig. S. Bakken, Lukas Smith, Igor Feghali
+ * All rights reserved.
+ *
+ * MDB2_Schema enables users to maintain RDBMS independant schema files
+ * in XML that can be used to manipulate both data and database schemas
+ * This LICENSE is in the BSD license style.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,
+ * Lukas Smith, Igor Feghali nor the names of his contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * 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
+ * REGENTS 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.
+ *
+ * Author: Christian Weiske <cweiske@php.net>
+ * $Id: Tool.php,v 1.6 2008/12/13 00:26:07 clockwerx Exp $
+ *
+ * @category Database
+ * @package MDB2_Schema
+ * @author Christian Weiske <cweiske@php.net>
+ * @license BSD http://www.opensource.org/licenses/bsd-license.php
+ * @version CVS: $Id: Tool.php,v 1.6 2008/12/13 00:26:07 clockwerx Exp $
+ * @link http://pear.php.net/packages/MDB2_Schema
+ */
+
+require_once 'MDB2/Schema.php';
+require_once 'MDB2/Schema/Tool/ParameterException.php';
+
+/**
+* Command line tool to work with database schemas
+*
+* Functionality:
+* - dump a database schema to stdout
+* - import schema into database
+* - create a diff between two schemas
+* - apply diff to database
+*
+ * @category Database
+ * @package MDB2_Schema
+ * @author Christian Weiske <cweiske@php.net>
+ * @license BSD http://www.opensource.org/licenses/bsd-license.php
+ * @link http://pear.php.net/packages/MDB2_Schema
+ */
+class MDB2_Schema_Tool
+{
+ /**
+ * Run the schema tool
+ *
+ * @param array $args Array of command line arguments
+ */
+ public function __construct($args)
+ {
+ $strAction = $this->getAction($args);
+ try {
+ $this->{'do' . ucfirst($strAction)}($args);
+ } catch (MDB2_Schema_Tool_ParameterException $e) {
+ $this->{'doHelp' . ucfirst($strAction)}($e->getMessage());
+ }
+ }//public function __construct($args)
+
+
+
+ /**
+ * Runs the tool with command line arguments
+ *
+ * @return void
+ */
+ public static function run()
+ {
+ $args = $GLOBALS['argv'];
+ array_shift($args);
+
+ try {
+ $tool = new MDB2_Schema_Tool($args);
+ } catch (Exception $e) {
+ self::toStdErr($e->getMessage() . "\n");
+ }
+ }//public static function run()
+
+
+
+ /**
+ * Reads the first parameter from the argument array and
+ * returns the action.
+ *
+ * @param array &$args Command line parameters
+ *
+ * @return string Action to execute
+ */
+ protected function getAction(&$args)
+ {
+ if (count($args) == 0) {
+ return 'help';
+ }
+ $arg = array_shift($args);
+ switch ($arg) {
+ case 'h':
+ case 'help':
+ case '-h':
+ case '--help':
+ return 'help';
+ case 'd':
+ case 'dump':
+ case '-d':
+ case '--dump':
+ return 'dump';
+ case 'l':
+ case 'load':
+ case '-l':
+ case '--load':
+ return 'load';
+ case 'i':
+ case 'diff':
+ case '-i':
+ case '--diff':
+ return 'diff';
+ case 'a':
+ case 'apply':
+ case '-a':
+ case '--apply':
+ return 'apply';
+ case 'n':
+ case 'init':
+ case '-i':
+ case '--init':
+ return 'init';
+ default:
+ throw new MDB2_Schema_Tool_ParameterException("Unknown mode \"$arg\"");
+ }
+ }//protected function getAction(&$args)
+
+
+
+ /**
+ * Writes the message to stderr
+ *
+ * @param string $msg Message to print
+ *
+ * @return void
+ */
+ protected static function toStdErr($msg)
+ {
+ file_put_contents('php://stderr', $msg);
+ }//protected static function toStdErr($msg)
+
+
+
+ /**
+ * Displays generic help to stdout
+ *
+ * @return void
+ */
+ protected function doHelp()
+ {
+ self::toStdErr(<<<EOH
+Usage: mdb2_schematool mode parameters
+
+Works with database schemas
+
+mode: (- and -- are optional)
+ h, help Show this help screen
+ d, dump Dump a schema to stdout
+ l, load Load a schema into database
+ i, diff Create a diff between two schemas and dump it to stdout
+ a, apply Apply a diff to a database
+ n, init Initialize a database with data
+
+EOH
+ );
+ }//protected function doHelp()
+
+
+
+ /**
+ * Displays the help screen for "dump" command
+ *
+ * @return void
+ */
+ protected function doHelpDump()
+ {
+ self::toStdErr( <<<EOH
+Usage: mdb2_schematool dump [all|data|schema] [-p] DSN
+
+Dumps a database schema to stdout
+
+If dump type is not specified, defaults to "schema".
+
+DSN: Data source name in the form of
+ driver://user:password@host/database
+
+User and password may be omitted.
+Using -p reads password from stdin which is more secure than passing it in the parameter.
+
+EOH
+ );
+ }//protected function doHelpDump()
+
+
+
+ /**
+ * Displays the help screen for "init" command
+ *
+ * @return void
+ */
+ protected function doHelpInit()
+ {
+ self::toStdErr( <<<EOH
+Usage: mdb2_schematool init source [-p] destination
+
+Initializes a database with data
+ (Inserts data on a previous created database at destination)
+
+source should be a schema file containing data,
+destination should be a DSN
+
+DSN: Data source name in the form of
+ driver://user:password@host/database
+
+User and password may be omitted.
+Using -p reads password from stdin which is more secure than passing it in the parameter.
+
+EOH
+ );
+ }//protected function doHelpInit()
+
+
+
+ /**
+ * Displays the help screen for "load" command
+ *
+ * @return void
+ */
+ protected function doHelpLoad()
+ {
+ self::toStdErr( <<<EOH
+Usage: mdb2_schematool load [-p] source [-p] destination
+
+Loads a database schema from source to destination
+ (Creates the database schema at destination)
+
+source can be a DSN or a schema file,
+destination should be a DSN
+
+DSN: Data source name in the form of
+ driver://user:password@host/database
+
+User and password may be omitted.
+Using -p reads password from stdin which is more secure than passing it in the parameter.
+
+EOH
+ );
+ }//protected function doHelpLoad()
+
+
+
+ /**
+ * Returns an array of options for MDB2_Schema constructor
+ *
+ * @return array Options for MDB2_Schema constructor
+ */
+ protected function getSchemaOptions()
+ {
+ $options = array(
+ 'log_line_break' => '<br>',
+ 'idxname_format' => '%s',
+ 'debug' => true,
+ 'quote_identifier' => true,
+ 'force_defaults' => false,
+ 'portability' => true,
+ 'use_transactions' => false,
+ );
+ return $options;
+ }//protected function getSchemaOptions()
+
+
+
+ /**
+ * Checks if the passed parameter is a PEAR_Error object
+ * and throws an exception in that case.
+ *
+ * @param mixed $object Some variable to check
+ * @param string $location Where the error occured
+ *
+ * @return void
+ */
+ protected function throwExceptionOnError($object, $location = '')
+ {
+ if (PEAR::isError($object)) {
+ //FIXME: exception class
+ //debug_print_backtrace();
+ throw new Exception('Error ' . $location
+ . "\n" . $object->getMessage()
+ . "\n" . $object->getUserInfo()
+ );
+ }
+ }//protected function throwExceptionOnError($object, $location = '')
+
+
+
+ /**
+ * Loads a file or a dsn from the arguments
+ *
+ * @param array &$args Array of arguments to the program
+ *
+ * @return array Array of ('file'|'dsn', $value)
+ */
+ protected function getFileOrDsn(&$args)
+ {
+ if (count($args) == 0) {
+ throw new MDB2_Schema_Tool_ParameterException('File or DSN expected');
+ }
+
+ $arg = array_shift($args);
+ if ($arg == '-p') {
+ $bAskPassword = true;
+ $arg = array_shift($args);
+ } else {
+ $bAskPassword = false;
+ }
+
+ if (strpos($arg, '://') === false) {
+ if (file_exists($arg)) {
+ //File
+ return array('file', $arg);
+ } else {
+ throw new Exception('Schema file does not exist');
+ }
+ }
+
+ //read password if necessary
+ if ($bAskPassword) {
+ $password = $this->readPasswordFromStdin($arg);
+ $arg = self::setPasswordIntoDsn($arg, $password);
+ self::toStdErr($arg);
+ }
+ return array('dsn', $arg);
+ }//protected function getFileOrDsn(&$args)
+
+
+
+ /**
+ * Takes a DSN data source name and integrates the given
+ * password into it.
+ *
+ * @param string $dsn Data source name
+ * @param string $password Password
+ *
+ * @return string DSN with password
+ */
+ protected function setPasswordIntoDsn($dsn, $password)
+ {
+ //simple try to integrate password
+ if (strpos($dsn, '@') === false) {
+ //no @ -> no user and no password
+ return str_replace('://', '://:' . $password . '@', $dsn);
+ } else if (preg_match('|://[^:]+@|', $dsn)) {
+ //user only, no password
+ return str_replace('@', ':' . $password . '@', $dsn);
+ } else if (strpos($dsn, ':@') !== false) {
+ //abstract version
+ return str_replace(':@', ':' . $password . '@', $dsn);
+ }
+
+ return $dsn;
+ }//protected function setPasswordIntoDsn($dsn, $password)
+
+
+
+ /**
+ * Reads a password from stdin
+ *
+ * @param string $dsn DSN name to put into the message
+ *
+ * @return string Password
+ */
+ protected function readPasswordFromStdin($dsn)
+ {
+ $stdin = fopen('php://stdin', 'r');
+ self::toStdErr('Please insert password for ' . $dsn . "\n");
+ $password = '';
+ $breakme = false;
+ while (false !== ($char = fgetc($stdin))) {
+ if (ord($char) == 10 || $char == "\n" || $char == "\r") {
+ break;
+ }
+ $password .= $char;
+ }
+ fclose($stdin);
+
+ return trim($password);
+ }//protected function readPasswordFromStdin()
+
+
+
+ /**
+ * Creates a database schema dump and sends it to stdout
+ *
+ * @param array $args Command line arguments
+ *
+ * @return void
+ */
+ protected function doDump($args)
+ {
+ $dump_what = MDB2_SCHEMA_DUMP_STRUCTURE;
+ $arg = '';
+ if (count($args)) {
+ $arg = $args[0];
+ }
+
+ switch (strtolower($arg)) {
+ case 'all':
+ $dump_what = MDB2_SCHEMA_DUMP_ALL;
+ array_shift($args);
+ break;
+ case 'data':
+ $dump_what = MDB2_SCHEMA_DUMP_CONTENT;
+ array_shift($args);
+ break;
+ case 'schema':
+ array_shift($args);
+ }
+
+ list($type, $dsn) = $this->getFileOrDsn($args);
+ if ($type == 'file') {
+ throw new MDB2_Schema_Tool_ParameterException(
+ 'Dumping a schema file as a schema file does not make much sense'
+ );
+ }
+
+ $schema = MDB2_Schema::factory($dsn, $this->getSchemaOptions());
+ $this->throwExceptionOnError($schema);
+
+ $definition = $schema->getDefinitionFromDatabase();
+ $this->throwExceptionOnError($definition);
+
+
+ $dump_options = array(
+ 'output_mode' => 'file',
+ 'output' => 'php://stdout',
+ 'end_of_line' => "\r\n"
+ );
+ $op = $schema->dumpDatabase(
+ $definition, $dump_options, $dump_what
+ );
+ $this->throwExceptionOnError($op);
+
+ $schema->disconnect();
+ }//protected function doDump($args)
+
+
+
+ /**
+ * Loads a database schema
+ *
+ * @param array $args Command line arguments
+ *
+ * @return void
+ */
+ protected function doLoad($args)
+ {
+ list($typeSource, $dsnSource) = $this->getFileOrDsn($args);
+ list($typeDest, $dsnDest) = $this->getFileOrDsn($args);
+
+ if ($typeDest == 'file') {
+ throw new MDB2_Schema_Tool_ParameterException(
+ 'A schema can only be loaded into a database, not a file'
+ );
+ }
+
+
+ $schemaDest = MDB2_Schema::factory($dsnDest, $this->getSchemaOptions());
+ $this->throwExceptionOnError($schemaDest);
+
+ //load definition
+ if ($typeSource == 'file') {
+ $definition = $schemaDest->parseDatabaseDefinitionFile($dsnSource);
+ $where = 'loading schema file';
+ } else {
+ $schemaSource = MDB2_Schema::factory($dsnSource, $this->getSchemaOptions());
+ $this->throwExceptionOnError($schemaSource, 'connecting to source database');
+
+ $definition = $schemaSource->getDefinitionFromDatabase();
+ $where = 'loading definition from database';
+ }
+ $this->throwExceptionOnError($definition, $where);
+
+
+ //create destination database from definition
+ $simulate = false;
+ $op = $schemaDest->createDatabase($definition, array(), $simulate);
+ $this->throwExceptionOnError($op, 'creating the database');
+ }//protected function doLoad($args)
+
+
+
+ /**
+ * Initializes a database with data
+ *
+ * @param array $args Command line arguments
+ *
+ * @return void
+ */
+ protected function doInit($args)
+ {
+ list($typeSource, $dsnSource) = $this->getFileOrDsn($args);
+ list($typeDest, $dsnDest) = $this->getFileOrDsn($args);
+
+ if ($typeSource != 'file') {
+ throw new MDB2_Schema_Tool_ParameterException(
+ 'Data must come from a source file'
+ );
+ }
+
+ if ($typeDest != 'dsn') {
+ throw new MDB2_Schema_Tool_ParameterException(
+ 'A schema can only be loaded into a database, not a file'
+ );
+ }
+
+ $schemaDest = MDB2_Schema::factory($dsnDest, $this->getSchemaOptions());
+ $this->throwExceptionOnError($schemaDest, 'connecting to destination database');
+
+ $definition = $schemaDest->getDefinitionFromDatabase();
+ $this->throwExceptionOnError($definition, 'loading definition from database');
+
+ $op = $schemaDest->writeInitialization($dsnSource, $definition);
+ $this->throwExceptionOnError($op, 'initializing database');
+ }//protected function doInit($args)
+
+
+}//class MDB2_Schema_Tool
+
+?>