MDB2
[ class tree: MDB2 ] [ index: MDB2 ] [ all elements ]

Source for file Schema.php

Documentation is available at Schema.php

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP versions 4 and 5                                                 |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  6. // | Stig. S. Bakken, Lukas Smith                                         |
  7. // | All rights reserved.                                                 |
  8. // +----------------------------------------------------------------------+
  9. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
  10. // | API as well as database abstraction for PHP applications.            |
  11. // | This LICENSE is in the BSD license style.                            |
  12. // |                                                                      |
  13. // | Redistribution and use in source and binary forms, with or without   |
  14. // | modification, are permitted provided that the following conditions   |
  15. // | are met:                                                             |
  16. // |                                                                      |
  17. // | Redistributions of source code must retain the above copyright       |
  18. // | notice, this list of conditions and the following disclaimer.        |
  19. // |                                                                      |
  20. // | Redistributions in binary form must reproduce the above copyright    |
  21. // | notice, this list of conditions and the following disclaimer in the  |
  22. // | documentation and/or other materials provided with the distribution. |
  23. // |                                                                      |
  24. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25. // | Lukas Smith nor the names of his contributors may be used to endorse |
  26. // | or promote products derived from this software without specific prior|
  27. // | written permission.                                                  |
  28. // |                                                                      |
  29. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41. // +----------------------------------------------------------------------+
  42. // | Author: Lukas Smith <smith@backendmedia.com>                         |
  43. // +----------------------------------------------------------------------+
  44. //
  45. // $Id: Schema.php,v 1.4 2005/04/07 08:23:59 lsmith Exp $
  46. //
  47.  
  48. require_once 'MDB2.php';
  49.  
  50. define('MDB2_MANAGER_DUMP_ALL',          0);
  51. define('MDB2_MANAGER_DUMP_STRUCTURE',    1);
  52. define('MDB2_MANAGER_DUMP_CONTENT',      2);
  53.  
  54. /**
  55.  * The database manager is a class that provides a set of database
  56.  * management services like installing, altering and dumping the data
  57.  * structures of databases.
  58.  *
  59.  * @package MDB2
  60.  * @category Database
  61.  * @author  Lukas Smith <smith@backendmedia.com>
  62.  */
  63. class MDB2_Schema extends PEAR
  64. {
  65.     // {{{ properties
  66.  
  67.     var $db;
  68.  
  69.     var $warnings = array();
  70.  
  71.     var $options = array(
  72.         'fail_on_invalid_names' => true,
  73.     );
  74.  
  75.     var $invalid_names = array(
  76.         'user' => array(),
  77.         'is' => array(),
  78.         'file' => array(
  79.             'oci8' => array(),
  80.         ),
  81.         'notify' => array(
  82.             'pgsql' => array()
  83.         ),
  84.         'restrict' => array(
  85.             'mysql' => array()
  86.         ),
  87.         'password' => array(
  88.             'ibase' => array()
  89.         )
  90.     );
  91.  
  92.     var $database_definition = array(
  93.         'name' => '',
  94.         'create' => 0,
  95.         'tables' => array()
  96.     );
  97.  
  98.     // }}}
  99.     // {{{ apiVersion()
  100.  
  101.     /**
  102.      * Return the MDB2 API version
  103.      *
  104.      * @return string     the MDB2 API version number
  105.      * @access public
  106.      */
  107.     function apiVersion()
  108.     {
  109.         return '@package_version@';
  110.     }
  111.  
  112.     // }}}
  113.     // {{{ raiseError()
  114.  
  115.     /**
  116.      * This method is used to communicate an error and invoke error
  117.      * callbacks etc.  Basically a wrapper for PEAR::raiseError
  118.      * without the message string.
  119.      *
  120.      * @param mixed $code integer error code, or a PEAR error object (all
  121.      *       other parameters are ignored if this parameter is an object
  122.      * @param int $mode error mode, see PEAR_Error docs
  123.      * @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the
  124.      *       error level (E_USER_NOTICE etc).  If error mode is
  125.      *       PEAR_ERROR_CALLBACK, this is the callback function, either as a
  126.      *       function name, or as an array of an object and method name. For
  127.      *       other error modes this parameter is ignored.
  128.      * @param string $userinfo Extra debug information.  Defaults to the last
  129.      *       query and native error code.
  130.      * @param mixed $nativecode Native error code, integer or string depending
  131.      *       the backend.
  132.      * @return object PEAR error object
  133.      * @access public
  134.      * @see PEAR_Error
  135.      */
  136.     function &raiseError($code = null$mode = null$options = null$userinfo = null)
  137.     {
  138.         return PEAR::raiseError(null$code$mode$options$userinfo'MDB2_Error'true);
  139.     }
  140.  
  141.     // }}}
  142.     // {{{ debugOutput()
  143.  
  144.     /**
  145.      * output debug info
  146.      *
  147.      * @return string content of the debug_output class variable
  148.      * @access public
  149.      */
  150.     function debugOutput()
  151.     {
  152.         return $this->db->debugOutput();
  153.     }
  154.  
  155.     // }}}
  156.     // {{{ resetWarnings()
  157.  
  158.     /**
  159.      * reset the warning array
  160.      *
  161.      * @access public
  162.      */
  163.     function resetWarnings()
  164.     {
  165.         $this->warnings = array();
  166.     }
  167.  
  168.     // }}}
  169.     // {{{ getWarnings()
  170.  
  171.     /**
  172.      * get all warnings in reverse order.
  173.      * This means that the last warning is the first element in the array
  174.      *
  175.      * @return array with warnings
  176.      * @access public
  177.      * @see resetWarnings()
  178.      */
  179.     function getWarnings()
  180.     {
  181.         return array_reverse($this->warnings);
  182.     }
  183.  
  184.     // }}}
  185.     // {{{ setOption()
  186.  
  187.     /**
  188.      * set the option for the db class
  189.      *
  190.      * @param string $option option name
  191.      * @param mixed $value value for the option
  192.      * @return mixed MDB2_OK or MDB2 Error Object
  193.      * @access public
  194.      */
  195.     function setOption($option$value)
  196.     {
  197.         if (isset($this->options[$option])) {
  198.             if (is_null($value)) {
  199.                 return $this->raiseError(MDB2_ERRORnullnull,
  200.                     'may not set an option to value null');
  201.             }
  202.             $this->options[$option$value;
  203.             return MDB2_OK;
  204.         }
  205.         return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  206.             "unknown option $option");
  207.     }
  208.  
  209.     // }}}
  210.     // {{{ getOption()
  211.  
  212.     /**
  213.      * returns the value of an option
  214.      *
  215.      * @param string $option option name
  216.      * @return mixed the option value or error object
  217.      * @access public
  218.      */
  219.     function getOption($option)
  220.     {
  221.         if (isset($this->options[$option])) {
  222.             return $this->options[$option];
  223.         }
  224.         return $this->raiseError(MDB2_ERROR_UNSUPPORTED,
  225.             nullnull"unknown option $option");
  226.     }
  227.  
  228.     // }}}
  229.     // {{{ connect()
  230.  
  231.     /**
  232.      * Create a new MDB2 connection object and connect to the specified
  233.      * database
  234.      *
  235.      * @param   mixed   $db       'data source name', see the MDB2::parseDSN
  236.      *                             method for a description of the dsn format.
  237.      *                             Can also be specified as an array of the
  238.      *                             format returned by MDB2::parseDSN.
  239.      *                             Finally you can also pass an existing db
  240.      *                             object to be used.
  241.      * @param   mixed   $options  An associative array of option names and
  242.      *                             their values.
  243.      * @return  mixed MDB2_OK on success, or a MDB2 error object
  244.      * @access  public
  245.      * @see     MDB2::parseDSN
  246.      */
  247.     function connect(&$db$options = false)
  248.     {
  249.         if (MDB2::isConnection($this->db)) {
  250.             $this->disconnect();
  251.         }
  252.         if (!MDB2::isConnection($db)) {
  253.             $db =MDB2::connect($db$options);
  254.         }
  255.         if (PEAR::isError($db)) {
  256.             return $db;
  257.         }
  258.         $this->db =$db;
  259.         if (is_array($options&& !empty($options)) {
  260.             $this->options = array_merge($this->options$options);
  261.         }
  262.         $this->db->loadModule('Manager');
  263.         return MDB2_OK;
  264.     }
  265.  
  266.     // }}}
  267.     // {{{ disconnect()
  268.  
  269.     /**
  270.      * Log out and disconnect from the database.
  271.      *
  272.      * @access public
  273.      */
  274.     function disconnect()
  275.     {
  276.         if (MDB2::isConnection($this->db)) {
  277.             $this->db->disconnect();
  278.             unset($this->db);
  279.         }
  280.     }
  281.  
  282.     // }}}
  283.     // {{{ setDatabase()
  284.  
  285.     /**
  286.      * Select a different database
  287.      *
  288.      * @param string $name name of the database that should be selected
  289.      * @return string name of the database previously connected to
  290.      * @access public
  291.      */
  292.     function setDatabase($name)
  293.     {
  294.         return $this->db->setDatabase($name);
  295.     }
  296.  
  297.     // }}}
  298.     // {{{ parseDatabaseDefinitionFile()
  299.  
  300.     /**
  301.      * Parse a database definition file by creating a Metabase schema format
  302.      * parser object and passing the file contents as parser input data stream.
  303.      *
  304.      * @param string $input_file the path of the database schema file.
  305.      * @param array $variables an associative array that the defines the text
  306.      *  string values that are meant to be used to replace the variables that are
  307.      *  used in the schema description.
  308.      * @param bool $fail_on_invalid_names (optional) make function fail on invalid
  309.      *  names
  310.      * @return mixed MDB2_OK on success, or a MDB2 error object
  311.      * @access public
  312.      */
  313.     function parseDatabaseDefinitionFile($input_file$variables$fail_on_invalid_names = true)
  314.     {
  315.         require_once 'MDB2/Schema/Parser.php';
  316.         $parser =new MDB2_Schema_Parser($variables$fail_on_invalid_names);
  317.         $result $parser->setInputFile($input_file);
  318.         if (PEAR::isError($result)) {
  319.             return $result;
  320.         }
  321.         $result $parser->parse();
  322.         if (PEAR::isError($result)) {
  323.             return $result;
  324.         }
  325.         if (!$result || PEAR::isError($parser->error)) {
  326.             return $parser->error;
  327.         }
  328.         return $parser->database_definition;
  329.     }
  330.  
  331.     // }}}
  332.     // {{{ getDefinitionFromDatabase()
  333.  
  334.     /**
  335.      * Attempt to reverse engineer a schema structure from an existing MDB2
  336.      * This method can be used if no xml schema file exists yet.
  337.      * The resulting xml schema file may need some manual adjustments.
  338.      *
  339.      * @return mixed MDB2_OK or array with all ambiguities on success, or a MDB2 error object
  340.      * @access public
  341.      */
  342.     function getDefinitionFromDatabase()
  343.     {
  344.         $this->db->loadModule('Reverse');
  345.         $database $this->db->database_name;
  346.         if (strlen($database== 0{
  347.             return $this->raiseError('it was not specified a valid database name');
  348.         }
  349.         $this->database_definition = array(
  350.             'name' => $database,
  351.             'create' => 1,
  352.             'tables' => array(),
  353.         );
  354.         $tables $this->db->manager->listTables();
  355.         if (PEAR::isError($tables)) {
  356.             return $tables;
  357.         }
  358.  
  359.         for ($table = 0; $table count($tables)$table++{
  360.             $table_name $tables[$table];
  361.             $fields $this->db->manager->listTableFields($table_name);
  362.             if (PEAR::isError($fields)) {
  363.                 return $fields;
  364.             }
  365.             $this->database_definition['tables'][$table_name= array('fields' => array());
  366.             $table_definition =$this->database_definition['tables'][$table_name];
  367.             for ($field = 0; $field count($fields)$field++{
  368.                 $field_name $fields[$field];
  369.                 $definition $this->db->reverse->getTableFieldDefinition($table_name$field_name);
  370.                 if (PEAR::isError($definition)) {
  371.                     return $definition;
  372.                 }
  373.                 $table_definition['fields'][$field_name$definition[0][0];
  374.                 $field_choices count($definition[0]);
  375.                 if ($field_choices > 1{
  376.                     $warning = "There are $field_choices type choices in the table"
  377.                         ."$table_name field $field_name (#1 is the default): ";
  378.                     $field_choice_cnt = 1;
  379.                     $table_definition['fields'][$field_name]['choices'= array();
  380.                     foreach ($definition[0as $field_choice{
  381.                         $table_definition['fields'][$field_name]['choices'][$field_choice;
  382.                         $warning .= 'choice #'.($field_choice_cnt).': '.serialize($field_choice);
  383.                         $field_choice_cnt++;
  384.                     }
  385.                     $this->warnings[$warning;
  386.                 }
  387.                 if (isset($definition[1])) {
  388.                     $sequence $definition[1]['definition'];
  389.                     $sequence_name $definition[1]['name'];
  390.                     $this->db->debug('Implicitly defining sequence: '.$sequence_name);
  391.                     if (!isset($this->database_definition['sequences'])) {
  392.                         $this->database_definition['sequences'= array();
  393.                     }
  394.                     $this->database_definition['sequences'][$sequence_name$sequence;
  395.                 }
  396.                 if (isset($definition[2])) {
  397.                     $index $definition[2]['definition'];
  398.                     $index_name $definition[2]['name'];
  399.                     $this->db->debug('Implicitly defining index: '.$index_name);
  400.                     if (!isset($table_definition['indexes'])) {
  401.                         $table_definition['indexes'= array();
  402.                     }
  403.                     $table_definition['indexes'][$index_name$index;
  404.                 }
  405.             }
  406.             $indexes $this->db->manager->listTableIndexes($table_name);
  407.             if (PEAR::isError($indexes)) {
  408.                 return $indexes;
  409.             }
  410.             if (is_array($indexes&& count($indexes> 0
  411.                 && !isset($table_definition['indexes'])
  412.             {
  413.                 $table_definition['indexes'= array();
  414.             }
  415.             for ($index = 0$index_cnt count($indexes)$index $index_cnt$index++{
  416.                 $index_name $indexes[$index];
  417.                 $definition $this->db->reverse->getTableIndexDefinition($table_name$index_name);
  418.                 if (PEAR::isError($definition)) {
  419.                     return $definition;
  420.                 }
  421.                $table_definition['indexes'][$index_name$definition;
  422.             }
  423.             // ensure that all fields that have an index on them are set to NOT NULL
  424.             if (isset($table_definition['indexes'])
  425.                 && is_array($table_definition['indexes'])
  426.                 && count($table_definition['indexes'])
  427.             {
  428.                 foreach ($table_definition['indexes'as $index_check_null{
  429.                     foreach ($index_check_null['fields'as $field_name_check_null => $field_check_null{
  430.                         $table_definition['fields'][$field_name_check_null]['notnull'= true;
  431.                     }
  432.                 }
  433.             }
  434.         }
  435.  
  436.         $sequences $this->db->manager->listSequences();
  437.         if (PEAR::isError($sequences)) {
  438.             return $sequences;
  439.         }
  440.         if (is_array($sequences&& count($sequences> 0
  441.             && !isset($this->database_definition['sequences'])
  442.         {
  443.             $this->database_definition['sequences'= array();
  444.         }
  445.         for ($sequence = 0; $sequence count($sequences)$sequence++{
  446.             $sequence_name $sequences[$sequence];
  447.             $definition $this->db->reverse->getSequenceDefinition($sequence_name);
  448.             if (PEAR::isError($definition)) {
  449.                 return $definition;
  450.             }
  451.             $this->database_definition['sequences'][$sequence_name$definition;
  452.         }
  453.         return MDB2_OK;
  454.     }
  455.  
  456.     // }}}
  457.     // {{{ createTableIndexes()
  458.  
  459.     /**
  460.      * create a indexes om a table
  461.      *
  462.      * @param string $table_name  name of the table
  463.      * @param array  $indexes     indexes to be created
  464.      * @return mixed MDB2_OK on success, or a MDB2 error object
  465.      * @param boolean $overwrite  determine if the table/index should be
  466.                                   overwritten if it already exists
  467.      * @access public
  468.      */
  469.     function createTableIndexes($table_name$indexes$overwrite)
  470.     {
  471.         if (!$this->db->supports('indexes')) {
  472.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  473.                 'indexes are not supported');
  474.         }
  475.         $result = MDB2_OK;
  476.         foreach ($indexes as $index_name => $index{
  477.             $this->expectError(MDB2_ERROR_ALREADY_EXISTS);
  478.             $result $this->db->manager->createIndex($table_name$index_name$index);
  479.             $this->popExpect();
  480.             if (PEAR::isError($result)) {
  481.                 if ($result->getCode(=== MDB2_ERROR_ALREADY_EXISTS{
  482.                     $this->warnings['Index already exists: '.$index_name;
  483.                     if ($overwrite{
  484.                         $this->db->debug('Overwritting Index');
  485.                         $result $this->db->manager->dropIndex($table_name$index_name);
  486.                         if (!PEAR::isError($result)) {
  487.                             $result $this->db->manager->createIndex($table_name$index_name$index);
  488.                         }
  489.                     else {
  490.                         $result = MDB2_OK;
  491.                     }
  492.                 }
  493.                 if (PEAR::isError($result)) {
  494.                     $this->db->debug('Create index error: '.$table_name);
  495.                     break;
  496.                 }
  497.             }
  498.         }
  499.         return $result;
  500.     }
  501.  
  502.     // }}}
  503.     // {{{ createTable()
  504.  
  505.     /**
  506.      * create a table and inititialize the table if data is available
  507.      *
  508.      * @param string $table_name  name of the table to be created
  509.      * @param array  $table       multi dimensional array that containts the
  510.      *                             structure and optional data of the table
  511.      * @param boolean $overwrite  determine if the table/index should be
  512.                                   overwritten if it already exists
  513.      * @return mixed MDB2_OK on success, or a MDB2 error object
  514.      * @access public
  515.      */
  516.     function createTable($table_name$table$overwrite = false)
  517.     {
  518.         $this->expectError(MDB2_ERROR_ALREADY_EXISTS);
  519.         $result $this->db->manager->createTable($table_name$table['fields']);
  520.         $this->popExpect();
  521.         if (PEAR::isError($result)) {
  522.             if ($result->getCode(=== MDB2_ERROR_ALREADY_EXISTS{
  523.                 $this->warnings['Table already exists: '.$table_name;
  524.                 if ($overwrite{
  525.                     $this->db->debug('Overwritting Table');
  526.                     $result $this->dropTable($table_name);
  527.                     if (!PEAR::isError($result)) {
  528.                         $result $this->db->manager->createTable($table_name$table['fields']);
  529.                     }
  530.                 else {
  531.                     $result = MDB2_OK;
  532.                 }
  533.             }
  534.             if (PEAR::isError($result)) {
  535.                 $this->db->debug('Create table error: '.$table_name);
  536.                 return $result;
  537.             }
  538.         }
  539.         if (isset($table['initialization']&& is_array($table['initialization'])) {
  540.             $result $this->initializeTable($table_name$table);
  541.         }
  542.         if (!PEAR::isError($result&& isset($table['indexes']&& is_array($table['indexes'])) {
  543.             $result $this->createTableIndexes($table_name$table['indexes']$overwrite);
  544.         }
  545.         if (PEAR::isError($result)) {
  546.             $result $this->dropTable($table_name);
  547.             if (PEAR::isError($result)) {
  548.                 $result $this->raiseError(MDB2_ERROR_MANAGERnullnull,
  549.                     'could not drop the table ('.$result->getMessage().
  550.                     ' ('.$result->getUserinfo().'))');
  551.             }
  552.             return $result;
  553.         }
  554.         return MDB2_OK;
  555.     }
  556.  
  557.     // }}}
  558.     // {{{ initializeTable()
  559.  
  560.     /**
  561.      * inititialize the table with data
  562.      *
  563.      * @param string $table_name        name of the table
  564.      * @param array  $table       multi dimensional array that containts the
  565.      *                             structure and optional data of the table
  566.      * @return mixed MDB2_OK on success, or a MDB2 error object
  567.      * @access public
  568.      */
  569.     function initializeTable($table_name$table)
  570.     {
  571.         $result = MDB2_OK;
  572.         foreach ($table['initialization'as $instruction{
  573.             switch ($instruction['type']{
  574.             case 'insert':
  575.                 $query_fields $query_values = array();
  576.                 if (isset($instruction['fields']&& is_array($instruction['fields'])) {
  577.                     foreach ($instruction['fields'as $field_name => $field{
  578.                         $query_fields[$field_name;
  579.                         $query_values['?';
  580.                         $query_types[$table['fields'][$field_name]['type'];
  581.                     }
  582.                     $query_fields implode(',',$query_fields);
  583.                     $query_values implode(',',$query_values);
  584.                     $stmt $this->db->prepare(
  585.                         "INSERT INTO $table_name ($query_fields) VALUES ($query_values)"$query_types);
  586.                     if (PEAR::isError($stmt)) {
  587.                         return $stmt;
  588.                     }
  589.                     $result $stmt->bindParamArray(array_values($instruction['fields']));
  590.                     if (PEAR::isError($result)) {
  591.                         return $result;
  592.                     }
  593.                     $result $stmt->execute();
  594.                     $stmt->free();
  595.                 }
  596.                 break;
  597.             }
  598.         }
  599.         return $result;
  600.     }
  601.  
  602.     // }}}
  603.     // {{{ dropTable()
  604.  
  605.     /**
  606.      * drop a table
  607.      *
  608.      * @param string $table_name    name of the table to be dropped
  609.      * @return mixed MDB2_OK on success, or a MDB2 error object
  610.      * @access public
  611.      */
  612.     function dropTable($table_name)
  613.     {
  614.         return $this->db->manager->dropTable($table_name);
  615.     }
  616.  
  617.     // }}}
  618.     // {{{ createSequence()
  619.  
  620.     /**
  621.      * create a sequence
  622.      *
  623.      * @param string $sequence_name  name of the sequence to be created
  624.      * @param array  $sequence       multi dimensional array that containts the
  625.      *                                structure and optional data of the table
  626.      * @param boolean $overwrite    determine if the sequence should be overwritten
  627.                                     if it already exists
  628.      * @return mixed MDB2_OK on success, or a MDB2 error object
  629.      * @access private
  630.      */
  631.     function createSequence($sequence_name$sequence$overwrite = false)
  632.     {
  633.         if (!$this->db->supports('sequences')) {
  634.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  635.                 'sequences are not supported');
  636.         }
  637.         if (!isset($sequence_name|| $sequence_name == ''{
  638.             return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  639.                 'no valid sequence name specified');
  640.         }
  641.         $this->db->debug('Create sequence: '.$sequence_name);
  642.         $start = 1;
  643.         if (isset($sequence['on'])) {
  644.             $table $sequence['on']['table'];
  645.             $field $sequence['on']['field'];
  646.             if ($this->db->supports('summary_functions')) {
  647.                 $query = "SELECT MAX($field) FROM $table";
  648.             else {
  649.                 $query = "SELECT $field FROM $table ORDER BY $field DESC";
  650.             }
  651.             $start $this->db->queryOne($query'integer');
  652.             if (PEAR::isError($start)) {
  653.                 return $start;
  654.             }
  655.             $start++;
  656.         elseif (isset($sequence['start']&& is_numeric($sequence['start'])) {
  657.             $start $sequence['start'];
  658.         }
  659.         $this->expectError(MDB2_ERROR_ALREADY_EXISTS);
  660.         $result $this->db->manager->createSequence($sequence_name$start);
  661.         $this->popExpect();
  662.         if (PEAR::isError($result)) {
  663.             if ($result->getCode(=== MDB2_ERROR_ALREADY_EXISTS{
  664.                 $this->warnings['Sequence already exists: '.$sequence_name;
  665.                 if ($overwrite{
  666.                     $this->db->debug('Overwritting Sequence');
  667.                     $result $this->dropSequence($sequence_name);
  668.                     if (!PEAR::isError($result)) {
  669.                         $result $this->db->manager->createSequence($sequence_name$start);
  670.                     }
  671.                     if (PEAR::isError($result)) {
  672.                         return $result;
  673.                     }
  674.                 else {
  675.                     return MDB2_OK;
  676.                 }
  677.             }
  678.             if (PEAR::isError($result)) {
  679.                 $this->db->debug('Create sequence error: '.$sequence_name);
  680.                 return $result;
  681.             }
  682.         }
  683.         return MDB2_OK;
  684.     }
  685.  
  686.     // }}}
  687.     // {{{ dropSequence()
  688.  
  689.     /**
  690.      * drop a table
  691.      *
  692.      * @param string $sequence_name    name of the sequence to be dropped
  693.      * @return mixed MDB2_OK on success, or a MDB2 error object
  694.      * @access public
  695.      */
  696.     function dropSequence($sequence_name)
  697.     {
  698.         if (!$this->db->supports('sequences')) {
  699.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  700.                 'sequences are not supported');
  701.         }
  702.         $this->db->debug('Dropping sequence: '.$sequence_name);
  703.         if (!isset($sequence_name|| $sequence_name == ''{
  704.             return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  705.                 'no valid sequence name specified');
  706.         }
  707.         return $this->db->manager->dropSequence($sequence_name);
  708.     }
  709.  
  710.     // }}}
  711.     // {{{ createDatabase()
  712.  
  713.     /**
  714.      * Create a database space within which may be created database objects
  715.      * like tables, indexes and sequences. The implementation of this function
  716.      * is highly DBMS specific and may require special permissions to run
  717.      * successfully. Consult the documentation or the DBMS drivers that you
  718.      * use to be aware of eventual configuration requirements.
  719.      *
  720.      * @return mixed MDB2_OK on success, or a MDB2 error object
  721.      * @access public
  722.      */
  723.     function createDatabase()
  724.     {
  725.         if (!isset($this->database_definition['name']|| !$this->database_definition['name']{
  726.             return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  727.                 'no valid database name specified');
  728.         }
  729.         $create (isset($this->database_definition['create']&& $this->database_definition['create']);
  730.         $overwrite (isset($this->database_definition['overwrite']&& $this->database_definition['overwrite']);
  731.         if ($create{
  732.             $this->db->debug('Create database: '.$this->database_definition['name']);
  733.             $this->expectError(MDB2_ERROR_ALREADY_EXISTS);
  734.             $result $this->db->manager->createDatabase($this->database_definition['name']);
  735.             $this->popExpect();
  736.             if (PEAR::isError($result)) {
  737.                 if ($result->getCode(=== MDB2_ERROR_ALREADY_EXISTS{
  738.                     $this->warnings['Database already exists: '.$this->database_definition['name'];
  739.                     if ($overwrite{
  740.                         $this->db->debug('Overwritting Database');
  741.                         $result $this->db->manager->dropDatabase($this->database_definition['name']);
  742.                         if (!PEAR::isError($result)) {
  743.                             $result $this->db->manager->createDatabase($this->database_definition['name']);
  744.                         }
  745.                         if (PEAR::isError($result)) {
  746.                             return $result;
  747.                         }
  748.                     else {
  749.                         $result = MDB2_OK;
  750.                     }
  751.                 }
  752.                 if (PEAR::isError($result)) {
  753.                     $this->db->debug('Create database error.');
  754.                     return $result;
  755.                 }
  756.             }
  757.         }
  758.         $previous_database_name $this->db->setDatabase($this->database_definition['name']);
  759.         if (($support_transactions $this->db->supports('transactions'))
  760.             && PEAR::isError($result $this->db->beginTransaction())
  761.         {
  762.             return $result;
  763.         }
  764.  
  765.         $created_objects = 0;
  766.         if (isset($this->database_definition['tables'])
  767.             && is_array($this->database_definition['tables'])
  768.         {
  769.             foreach ($this->database_definition['tables'as $table_name => $table{
  770.                 $result $this->createTable($table_name$table$overwrite);
  771.                 if (PEAR::isError($result)) {
  772.                     break;
  773.                 }
  774.                 $created_objects++;
  775.             }
  776.         }
  777.         if (!PEAR::isError($result)
  778.             && isset($this->database_definition['sequences'])
  779.             && is_array($this->database_definition['sequences'])
  780.         {
  781.             foreach ($this->database_definition['sequences'as $sequence_name => $sequence{
  782.                 $result $this->createSequence($sequence_name$sequencefalse$overwrite);
  783.  
  784.                 if (PEAR::isError($result)) {
  785.                     break;
  786.                 }
  787.                 $created_objects++;
  788.             }
  789.         }
  790.  
  791.         if (PEAR::isError($result)) {
  792.             if ($created_objects{
  793.                 if ($support_transactions{
  794.                     $res $this->db->rollback();
  795.                     if (PEAR::isError($res))
  796.                         $result $this->raiseError(MDB2_ERROR_MANAGERnullnull,
  797.                             'Could not rollback the partially created database alterations ('.
  798.                             $result->getMessage().' ('.$result->getUserinfo().'))');
  799.                 else {
  800.                     $result $this->raiseError(MDB2_ERROR_MANAGERnullnull,
  801.                         'the database was only partially created ('.
  802.                         $result->getMessage().' ('.$result->getUserinfo().'))');
  803.                 }
  804.             }
  805.         else {
  806.             if ($support_transactions{
  807.                 $res $this->db->commit();
  808.                 if (PEAR::isError($res))
  809.                     $result $this->raiseError(MDB2_ERROR_MANAGERnullnull,
  810.                         'Could not end transaction after successfully created the database ('.
  811.                         $res->getMessage().' ('.$res->getUserinfo().'))');
  812.             }
  813.         }
  814.  
  815.         $this->db->setDatabase($previous_database_name);
  816.  
  817.         if (PEAR::isError($result&& $create
  818.             && PEAR::isError($result2 $this->db->manager->dropDatabase($this->database_definition['name']))
  819.         {
  820.             return $this->raiseError(MDB2_ERROR_MANAGERnullnull,
  821.                 'Could not drop the created database after unsuccessful creation attempt ('.
  822.                 $result2->getMessage().' ('.$result2->getUserinfo().'))');
  823.         }
  824.  
  825.         return $result;
  826.     }
  827.  
  828.     // }}}
  829.     // {{{ compareDefinitions()
  830.  
  831.     /**
  832.      * compare a previous definition with the currenlty parsed definition
  833.      *
  834.      * @param array multi dimensional array that contains the previous definition
  835.      * @param array multi dimensional array that contains the current definition
  836.      * @return mixed array of changes on success, or a MDB2 error object
  837.      * @access public
  838.      */
  839.     function compareDefinitions($previous_definition$current_definition = null)
  840.     {
  841.         $current_definition $current_definition $current_definition $this->database_definition;
  842.         $changes = array();
  843.         if (isset($current_definition['tables']&& is_array($current_definition['tables'])) {
  844.             $defined_tables = array();
  845.             foreach ($current_definition['tables'as $table_name => $table{
  846.                 $previous_tables = array();
  847.                 if (isset($previous_definition['tables']&& is_array($previous_definition)) {
  848.                     $previous_tables $previous_definition['tables'];
  849.                 }
  850.                 $change $this->compareTableDefinitions($table_name$previous_tables$table$defined_tables);
  851.                 if (PEAR::isError($change)) {
  852.                     return $change;
  853.                 }
  854.                 if (!empty($change)) {
  855.                     $changes['tables'$change;
  856.                 }
  857.             }
  858.             if (isset($previous_definition['tables']&& is_array($previous_definition['tables'])) {
  859.                 foreach ($previous_definition['tables'as $table_name => $table{
  860.                     if (!isset($defined_tables[$table_name])) {
  861.                         $changes[$table_name]['remove'= true;
  862.                     }
  863.                 }
  864.             }
  865.         }
  866.         if (isset($current_definition['sequences']&& is_array($current_definition['sequences'])) {
  867.            $defined_sequences = array();
  868.             foreach ($current_definition['sequences'as $sequence_name => $sequence{
  869.                 $previous_sequences = array();
  870.                 if (isset($previous_definition['sequences']&& is_array($previous_definition)) {
  871.                     $previous_sequences $previous_definition['sequences'];
  872.                 }
  873.                 $change $this->compareSequenceDefinitions(
  874.                     $sequence_name,
  875.                     $previous_sequences,
  876.                     $sequence,
  877.                     $defined_sequences
  878.                 );
  879.                 if (PEAR::isError($change)) {
  880.                     return $change;
  881.                 }
  882.                 if (!empty($change)) {
  883.                     $changes['sequences'$change;
  884.                 }
  885.             }
  886.             if (isset($previous_definition['sequences']&& is_array($previous_definition['sequences'])) {
  887.                 foreach ($previous_definition['sequences'as $sequence_name => $sequence{
  888.                     if (!isset($defined_sequences[$sequence_name])) {
  889.                         $changes[$sequence_name]['remove'= true;
  890.                     }
  891.                 }
  892.             }
  893.         }
  894.         return $changes;
  895.     }
  896.  
  897.     // }}}
  898.     // {{{ compareTableFieldsDefinitions()
  899.  
  900.     /**
  901.      * compare a previous definition with the currenlty parsed definition
  902.      *
  903.      * @param string $table_name    name of the table
  904.      * @param array multi dimensional array that contains the previous definition
  905.      * @param array multi dimensional array that contains the current definition
  906.      * @return mixed array of changes on success, or a MDB2 error object
  907.      * @access public
  908.      */
  909.     function compareTableFieldsDefinitions($table_name$previous_definition,
  910.         $current_definition&$defined_fields)
  911.     {
  912.         $changes = array();
  913.         if (is_array($current_definition)) {
  914.             foreach ($current_definition as $field_name => $field{
  915.                 $was_field_name $field['was'];
  916.                 if (isset($previous_definition[$field_name])
  917.                     && isset($previous_definition[$field_name]['was'])
  918.                     && $previous_definition[$field_name]['was'== $was_field_name
  919.                 {
  920.                     $was_field_name $field_name;
  921.                 }
  922.                 if (isset($previous_definition[$was_field_name])) {
  923.                     if ($was_field_name != $field_name{
  924.                         $declaration $this->db->getDeclaration($field['type']$field_name$field);
  925.                         if (PEAR::isError($declaration)) {
  926.                             return $declaration;
  927.                         }
  928.                         $changes['renamed_fields'][$was_field_name= array(
  929.                             'name' => $field_name,
  930.                             'declaration' => $declaration,
  931.                         );
  932.                     }
  933.                     if (isset($defined_fields[$was_field_name])) {
  934.                         return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  935.                             'the field "'.$was_field_name.
  936.                             '" was specified as base of more than one field of table');
  937.                     }
  938.                     $defined_fields[$was_field_name= true;
  939.                     $change $this->db->compareDefinition($field$previous_definition[$was_field_name]);
  940.                     if (PEAR::isError($change)) {
  941.                         return $change;
  942.                     }
  943.                     if (!empty($change)) {
  944.                         $declaration $this->db->getDeclaration($field['type']$field_name$field);
  945.                         if (PEAR::isError($declaration)) {
  946.                             return $declaration;
  947.                         }
  948.                         $change['declaration'$declaration;
  949.                         $change['definition'$field;
  950.                         $changes['changed_fields'][$field_name$change;
  951.                     }
  952.                 else {
  953.                     if ($field_name != $was_field_name{
  954.                         return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  955.                             'it was specified a previous field name ("'.
  956.                             $was_field_name.'") for field "'.$field_name.'" of table "'.
  957.                             $table_name.'" that does not exist');
  958.                     }
  959.                     $declaration $this->db->getDeclaration($field['type']$field_name$field);
  960.                     if (PEAR::isError($declaration)) {
  961.                         return $declaration;
  962.                     }
  963.                     $change['declaration'$declaration;
  964.                     $changes['added_fields'][$field_name$change;
  965.                 }
  966.             }
  967.         }
  968.         if (isset($previous_definition&& is_array($previous_definition)) {
  969.             foreach ($previous_definition as $field_previous_name => $field_previous{
  970.                 if (!isset($defined_fields[$field_previous_name])) {
  971.                     $changes['removed_fields'][$field_previous_name= true;
  972.                 }
  973.             }
  974.         }
  975.         return $changes;
  976.     }
  977.  
  978.     // }}}
  979.     // {{{ compareTableIndexesDefinitions()
  980.  
  981.     /**
  982.      * compare a previous definition with the currenlty parsed definition
  983.      *
  984.      * @param string $table_name    name of the table
  985.      * @param array multi dimensional array that contains the previous definition
  986.      * @param array multi dimensional array that contains the current definition
  987.      * @return mixed array of changes on success, or a MDB2 error object
  988.      * @access public
  989.      */
  990.     function compareTableIndexesDefinitions($table_name$previous_definition,
  991.         $current_definition&$defined_indexes)
  992.     {
  993.         $changes = array();
  994.         if (is_array($current_definition)) {
  995.             foreach ($current_definition as $index_name => $index{
  996.                 $was_index_name $index['was'];
  997.                 if (isset($previous_definition[$index_name])
  998.                     && isset($previous_definition[$index_name]['was'])
  999.                     && $previous_definition[$index_name]['was'== $was_index_name
  1000.                 {
  1001.                     $was_index_name $index_name;
  1002.                 }
  1003.                 if (isset($previous_definition[$was_index_name])) {
  1004.                     $change = array();
  1005.                     if ($was_index_name != $index_name{
  1006.                         $change['name'$was_index_name;
  1007.                     }
  1008.                     if (isset($defined_indexes[$was_index_name])) {
  1009.                         return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  1010.                             'the index "'.$was_index_name.'" was specified as base of'.
  1011.                             ' more than one index of table "'.$table_name.'"');
  1012.                     }
  1013.                     $defined_indexes[$was_index_name= true;
  1014.  
  1015.                     $previous_unique = isset($previous_definition[$was_index_name]['unique']);
  1016.                     $unique = isset($index['unique']);
  1017.                     if ($previous_unique != $unique{
  1018.                         $change['changed_unique'= true;
  1019.                         if ($unique{
  1020.                             $change['unique'$unique;
  1021.                         }
  1022.                     }
  1023.                     $defined_fields = array();
  1024.                     $previous_fields $previous_definition[$was_index_name]['fields'];
  1025.                     if (isset($index['fields']&& is_array($index['fields'])) {
  1026.                         foreach ($index['fields'as $field_name => $field{
  1027.                             if (isset($previous_fields[$field_name])) {
  1028.                                 $defined_fields[$field_name= true;
  1029.                                 $sorting (isset($field['sorting']$field['sorting''');
  1030.                                 $previous_sorting (isset($previous_fields[$field_name]['sorting'])
  1031.                                     ? $previous_fields[$field_name]['sorting''');
  1032.                                 if ($sorting != $previous_sorting{
  1033.                                     $change['changed_fields'= true;
  1034.                                 }
  1035.                             else {
  1036.                                 $change['changed_fields'= true;
  1037.                             }
  1038.                         }
  1039.                     }
  1040.                     if (isset($previous_fields&& is_array($previous_fields)) {
  1041.                         foreach ($previous_fields as $field_name => $field{
  1042.                             if (!isset($defined_fields[$field_name])) {
  1043.                                 $change['changed_fields'= true;
  1044.                             }
  1045.                         }
  1046.                     }
  1047.                     if (!empty($change)) {
  1048.                         $changes['changed_indexes'][$index_name$change;
  1049.                     }
  1050.                 else {
  1051.                     if ($index_name != $was_index_name{
  1052.                         return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  1053.                             'it was specified a previous index name ("'.$was_index_name.
  1054.                             ') for index "'.$index_name.'" of table "'.$table_name.'" that does not exist');
  1055.                     }
  1056.                     $changes['added_indexes'][$index_name$current_definition[$index_name];
  1057.                 }
  1058.             }
  1059.         }
  1060.         foreach ($previous_definition as $index_previous_name => $index_previous{
  1061.             if (!isset($defined_indexes[$index_previous_name])) {
  1062.                 $changes['removed_indexes'][$index_previous_name= true;
  1063.             }
  1064.         }
  1065.         return $changes;
  1066.     }
  1067.  
  1068.     // }}}
  1069.     // {{{ compareTableDefinitions()
  1070.  
  1071.     /**
  1072.      * compare a previous definition with the currenlty parsed definition
  1073.      *
  1074.      * @param string $table_name    name of the table
  1075.      * @param array multi dimensional array that contains the previous definition
  1076.      * @param array multi dimensional array that contains the current definition
  1077.      * @return mixed array of changes on success, or a MDB2 error object
  1078.      * @access public
  1079.      */
  1080.     function compareTableDefinitions($table_name$previous_definition,
  1081.         $current_definition&$defined_tables)
  1082.     {
  1083.         $changes = array();
  1084.  
  1085.         if (is_array($current_definition)) {
  1086.             $was_table_name $table_name;
  1087.             if (isset($current_definition['was'])) {
  1088.                 $was_table_name $current_definition['was'];
  1089.             }
  1090.             if (isset($previous_definition[$was_table_name])) {
  1091.                 $changes[$was_table_name= array();
  1092.                 if ($was_table_name != $table_name{
  1093.                     $changes[$was_table_name]+= array('name' => $table_name);
  1094.                 }
  1095.                 if (isset($defined_tables[$was_table_name])) {
  1096.                     return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  1097.                         'the table "'.$was_table_name.
  1098.                         '" was specified as base of more than of table of the database');
  1099.                 }
  1100.                 $defined_tables[$was_table_name= true;
  1101.                 if (isset($current_definition['fields']&& is_array($current_definition['fields'])) {
  1102.                     $previous_fields = array();
  1103.                     if (isset($previous_definition[$was_table_name]['fields'])
  1104.                         && is_array($previous_definition[$was_table_name]['fields'])
  1105.                     {
  1106.                         $previous_fields $previous_definition[$was_table_name]['fields'];
  1107.                     }
  1108.                     $defined_fields = array();
  1109.                     $change $this->compareTableFieldsDefinitions(
  1110.                         $table_name,
  1111.                         $previous_fields,
  1112.                         $current_definition['fields'],
  1113.                         $defined_fields
  1114.                     );
  1115.                     if (PEAR::isError($change)) {
  1116.                         return $change;
  1117.                     }
  1118.                     if (!empty($change)) {
  1119.                         $changes[$was_table_name]+= $change;
  1120.                     }
  1121.                 }
  1122.                 if (isset($current_definition['indexes']&& is_array($current_definition['indexes'])) {
  1123.                     $previous_indexes = array();
  1124.                     if (isset($previous_definition[$was_table_name]['indexes'])
  1125.                         && is_array($previous_definition[$was_table_name]['indexes'])
  1126.                     {
  1127.                         $previous_indexes $previous_definition[$was_table_name]['indexes'];
  1128.                     }
  1129.                     $defined_indexes = array();
  1130.                     $change $this->compareTableIndexesDefinitions(
  1131.                         $table_name,
  1132.                         $previous_indexes,
  1133.                         $current_definition['indexes'],
  1134.                         $defined_indexes
  1135.                     );
  1136.                     if (PEAR::isError($change)) {
  1137.                         return $change;
  1138.                     }
  1139.                     if (!empty($change)) {
  1140.                         if (isset($changes[$was_table_name]['indexes'])) {
  1141.                             $changes[$was_table_name]['indexes']+= $change;
  1142.                         else {
  1143.                             $changes[$was_table_name]['indexes'$change;
  1144.                         }
  1145.                     }
  1146.                 }
  1147.                 if (empty($changes[$was_table_name])) {
  1148.                     unset($changes[$was_table_name]);
  1149.                 }
  1150.             else {
  1151.                 if ($table_name != $was_table_name{
  1152.                     return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  1153.                         'it was specified a previous table name ("'.
  1154.                         $was_table_name.'") for table "'.$table_name.
  1155.                         '" that does not exist');
  1156.                 }
  1157.                 $changes[$table_name]['add'= true;
  1158.             }
  1159.         }
  1160.  
  1161.         return $changes;
  1162.     }
  1163.  
  1164.     // }}}
  1165.     // {{{ compareSequenceDefinitions()
  1166.  
  1167.     /**
  1168.      * compare a previous definition with the currenlty parsed definition
  1169.      *
  1170.      * @param array multi dimensional array that contains the previous definition
  1171.      * @param array multi dimensional array that contains the current definition
  1172.      * @return mixed array of changes on success, or a MDB2 error object
  1173.      * @access public
  1174.      */
  1175.     function compareSequenceDefinitions($sequence_name$previous_definition,
  1176.         $current_definition&$defined_sequences)
  1177.     {
  1178.         $changes = array();
  1179.         if (is_array($current_definition)) {
  1180.             $was_sequence_name $sequence_name;
  1181.             if (isset($previous_definition[$sequence_name])
  1182.                 && isset($previous_definition[$sequence_name]['was'])
  1183.                 && $previous_definition[$sequence_name]['was'== $was_sequence_name
  1184.             {
  1185.                 $was_sequence_name $sequence_name;
  1186.             elseif (isset($current_definition['was'])) {
  1187.                 $was_sequence_name $current_definition['was'];
  1188.             }
  1189.             if (isset($previous_definition[$was_sequence_name])) {
  1190.                 if ($was_sequence_name != $sequence_name{
  1191.                     $changes[$was_sequence_name]['name'$sequence_name;
  1192.                 }
  1193.                 if (isset($defined_sequences[$was_sequence_name])) {
  1194.                     return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  1195.                         'the sequence "'.$was_sequence_name.'" was specified as base'.
  1196.                         ' of more than of sequence of the database');
  1197.                 }
  1198.                 $defined_sequences[$was_sequence_name= true;
  1199.                 $change = array();
  1200.                 if (isset($current_definition['start'])
  1201.                     && isset($previous_definition[$was_sequence_name]['start'])
  1202.                     && $current_definition['start'!= $previous_definition[$was_sequence_name]['start']
  1203.                 {
  1204.                     $change['start'$previous_definition[$sequence_name]['start'];
  1205.                 }
  1206.                 if (isset($current_definition['on']['table'])
  1207.                     && isset($previous_definition[$was_sequence_name]['on']['table'])
  1208.                     && $current_definition['on']['table'!= $previous_definition[$was_sequence_name]['on']['table']
  1209.                     && isset($current_definition['on']['field'])
  1210.                     && isset($previous_definition[$was_sequence_name]['on']['field'])
  1211.                     && $current_definition['on']['field'!= $previous_definition[$was_sequence_name]['on']['field']
  1212.                 {
  1213.                     $change['on'$current_definition['on'];
  1214.                 }
  1215.                 if (!empty($change)) {
  1216.                     $changes[$was_sequence_name]['change'][$sequence_name$change;
  1217.                 }
  1218.             else {
  1219.                 if ($sequence_name != $was_sequence_name{
  1220.                     return $this->raiseError(MDB2_ERROR_INVALIDnullnull,
  1221.                         'it was specified a previous sequence name ("'.$was_sequence_name.
  1222.                         '") for sequence "'.$sequence_name.'" that does not exist');
  1223.                 }
  1224.                 $changes[$sequence_name]['add'= true;
  1225.             }
  1226.         }
  1227.         return $changes;
  1228.     }
  1229.     // }}}
  1230.     // {{{ verifyAlterDatabase()
  1231.  
  1232.     /**
  1233.      * verify that the changes requested are supported
  1234.      *
  1235.      * @param array $changes an associative array that contains the definition of
  1236.      *  the changes that are meant to be applied to the database structure.
  1237.      * @return mixed MDB2_OK on success, or a MDB2 error object
  1238.      * @access public
  1239.      */
  1240.     function verifyAlterDatabase($changes)
  1241.     {
  1242.         if (isset($changes['tables']&& is_array($changes['tables'])) {
  1243.             foreach ($changes['tables'as $table_name => $table{
  1244.                 if (isset($table['add']|| isset($table['remove'])) {
  1245.                     continue;
  1246.                 }
  1247.                 if (isset($table['indexes']&& is_array($table['indexes'])) {
  1248.                     if (!$this->db->supports('indexes')) {
  1249.                         return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1250.                             'indexes are not supported');
  1251.                     }
  1252.                     foreach ($table['indexes'as $index{
  1253.                         $table_changes count($index);
  1254.                         if (isset($index['add'])) {
  1255.                             $table_changes--;
  1256.                         }
  1257.                         if (isset($index['remove'])) {
  1258.                             $table_changes--;
  1259.                         }
  1260.                         if (isset($index['change'])) {
  1261.                             $table_changes--;
  1262.                         }
  1263.                         if ($table_changes{
  1264.                             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1265.                                 'index alteration not yet supported: '.implode(', 'array_keys($index)));
  1266.                         }
  1267.                     }
  1268.                 }
  1269.                 $result $this->db->manager->alterTable($table_name$tabletrue);
  1270.                 if (PEAR::isError($result)) {
  1271.                     return $result;
  1272.                 }
  1273.             }
  1274.         }
  1275.         if (isset($changes['sequences']&& is_array($changes['sequences'])) {
  1276.             if (!$this->db->supports('sequences')) {
  1277.                 return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1278.                     'sequences are not supported');
  1279.             }
  1280.             foreach ($changes['sequences'as $sequence{
  1281.                 if (isset($sequence['add']|| isset($sequence['remove']|| isset($sequence['change'])) {
  1282.                     continue;
  1283.                 }
  1284.                 return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1285.                     'some sequences changes are not yet supported');
  1286.             }
  1287.         }
  1288.         return MDB2_OK;
  1289.     }
  1290.  
  1291.     // }}}
  1292.     // {{{ alterDatabaseIndexes()
  1293.  
  1294.     /**
  1295.      * Execute the necessary actions to implement the requested changes
  1296.      * in the indexes inside a database structure.
  1297.      *
  1298.      * @param string name of the table
  1299.      * @param array $changes an associative array that contains the definition of
  1300.      *  the changes that are meant to be applied to the database structure.
  1301.      * @return mixed MDB2_OK on success, or a MDB2 error object
  1302.      * @access public
  1303.      */
  1304.     function alterDatabaseIndexes($table_name$changes)
  1305.     {
  1306.         $alterations = 0;
  1307.         if (is_array($changes)) {
  1308.             if (isset($changes['changed_indexes'])) {
  1309.                 foreach ($changes['changed_indexes'as $index_name => $index{
  1310.                     $result $this->db->manager->createIndex(
  1311.                         $table_name,
  1312.                         $index_name,
  1313.                         $index
  1314.                     );
  1315.                     if (PEAR::isError($result)) {
  1316.                         return $result;
  1317.                     }
  1318.                     $alterations++;
  1319.                 }
  1320.             }
  1321.             if (isset($changes['added_indexes'])) {
  1322.                 foreach ($changes['added_indexes'as $index_name => $index{
  1323.                     $result $this->db->manager->createIndex(
  1324.                         $table_name,
  1325.                         $index_name,
  1326.                         $index
  1327.                     );
  1328.                     if (PEAR::isError($result)) {
  1329.                         return $result;
  1330.                     }
  1331.                     $alterations++;
  1332.                 }
  1333.             }
  1334.         }
  1335.         return $alterations;
  1336.     }
  1337.  
  1338.     // }}}
  1339.     // {{{ alterDatabaseTables()
  1340.  
  1341.     /**
  1342.      * Execute the necessary actions to implement the requested changes
  1343.      * in the tables inside a database structure.
  1344.      *
  1345.      * @param array $changes an associative array that contains the definition of
  1346.      *  the changes that are meant to be applied to the database structure.
  1347.      * @param array multi dimensional array that contains the current definition
  1348.      * @return mixed MDB2_OK on success, or a MDB2 error object
  1349.      * @access public
  1350.      */
  1351.     function alterDatabaseTables($changes$current_definition)
  1352.     {
  1353.         $alterations = 0;
  1354.         if (is_array($changes)) {
  1355.             foreach ($changes as $table_name => $table{
  1356.                 $indexes = null;
  1357.                 if (isset($table['indexes']&& isset($current_definition[$table_name]['indexes'])) {
  1358.                     $indexes $table['indexes'];
  1359.                     unset($table['indexes']);
  1360.                 }
  1361.                 if (isset($table['remove'])) {
  1362.                     $result $this->dropTable($table_name);
  1363.                     if (PEAR::isError($result)) {
  1364.                         return $result;
  1365.                     }
  1366.                     $alterations++;
  1367.                 elseif (isset($table['add'])) {
  1368.                     $result $this->createTable($table_name$current_definition[$table_name]);
  1369.                     if (PEAR::isError($result)) {
  1370.                         return $result;
  1371.                     }
  1372.                     $alterations++;
  1373.                 elseif(!empty($table)) {
  1374.                     $result $this->db->manager->alterTable($table_name$tablefalse);
  1375.                     if (PEAR::isError($result)) {
  1376.                         return $result;
  1377.                     }
  1378.                     $alterations++;
  1379.                 }
  1380.                 if ($indexes{
  1381.                     $result $this->alterDatabaseIndexes(
  1382.                         $table_name,
  1383.                         $indexes
  1384.                     );
  1385.                     if (PEAR::isError($result)) {
  1386.                         return $result;
  1387.                     }
  1388.                     $alterations += $result;
  1389.                 }
  1390.             }
  1391.         }
  1392.         return $alterations;
  1393.     }
  1394.  
  1395.     // }}}
  1396.     // {{{ alterDatabaseSequences()
  1397.  
  1398.     /**
  1399.      * Execute the necessary actions to implement the requested changes
  1400.      * in the sequences inside a database structure.
  1401.      *
  1402.      * @param array $changes an associative array that contains the definition of
  1403.      *  the changes that are meant to be applied to the database structure.
  1404.      * @param array multi dimensional array that contains the current definition
  1405.      * @return mixed MDB2_OK on success, or a MDB2 error object
  1406.      * @access public
  1407.      */
  1408.     function alterDatabaseSequences($changes$current_definition)
  1409.     {
  1410.         $alterations = 0;
  1411.         if (is_array($changes)) {
  1412.             foreach ($changes as $sequence_name => $sequence{
  1413.                 if (isset($sequence['add'])) {
  1414.                     $result $this->createSequence($sequence_name$sequence);
  1415.                     if (PEAR::isError($result)) {
  1416.                         return $result;
  1417.                     }
  1418.                     $alterations++;
  1419.                 elseif (isset($sequence['remove'])) {
  1420.                     $result $this->dropSequence($sequence_name);
  1421.                     if (PEAR::isError($result)) {
  1422.                         return $result;
  1423.                     }
  1424.                     $alterations++;
  1425.                 elseif (isset($sequence['change'])) {
  1426.                     $result $this->dropSequence($current_definition[$sequence_name]['was']);
  1427.                     if (PEAR::isError($result)) {
  1428.                         return $result;
  1429.                     }
  1430.                     $result $this->createSequence($sequence_name$current_definition[$sequence_name]);
  1431.                     if (PEAR::isError($result)) {
  1432.                         return $result;
  1433.                     }
  1434.                     $alterations++;
  1435.                 }
  1436.             }
  1437.         }
  1438.         return $alterations;
  1439.     }
  1440.  
  1441.     // }}}
  1442.     // {{{ alterDatabase()
  1443.  
  1444.     /**
  1445.      * Execute the necessary actions to implement the requested changes
  1446.      * in a database structure.
  1447.      *
  1448.      * @param array $changes an associative array that contains the definition of
  1449.      *  the changes that are meant to be applied to the database structure.
  1450.      * @param array multi dimensional array that contains the current definition
  1451.      * @return mixed MDB2_OK on success, or a MDB2 error object
  1452.      * @access public
  1453.      */
  1454.     function alterDatabase($changes$current_definition = null)
  1455.     {
  1456.         $current_definition $current_definition
  1457.             ? $current_definition $this->database_definition;
  1458.  
  1459.         $result $this->verifyAlterDatabase($changes);
  1460.  
  1461.         if (isset($current_definition['name'])) {
  1462.             $previous_database_name $this->db->setDatabase($current_definition['name']);
  1463.         else {
  1464.             $previous_database_name $this->db->getDatabase();
  1465.         }
  1466.         if (($support_transactions $this->db->supports('transactions'))
  1467.             && PEAR::isError($result $this->db->beginTransaction())
  1468.         {
  1469.             return $result;
  1470.         }
  1471.  
  1472.         $alterations = 0;
  1473.  
  1474.         if (isset($changes['tables']&& isset($current_definition['tables'])) {
  1475.             $result $this->alterDatabaseTables($changes['tables']$current_definition['tables']);
  1476.             if (is_numeric($result)) {
  1477.                 $alterations += $result;
  1478.             }
  1479.         }
  1480.         if (!PEAR::isError($result&& isset($changes['sequences']&& isset($current_definition['sequences'])) {
  1481.             $result $this->alterDatabaseSequences($changes['sequences']$current_definition['sequences']);
  1482.             if (is_numeric($result)) {
  1483.                 $alterations += $result;
  1484.             }
  1485.         }
  1486.  
  1487.         if (PEAR::isError($result)) {
  1488.             if ($support_transactions{
  1489.                 $res $this->db->rollback();
  1490.                 if (PEAR::isError($res))
  1491.                     $result $this->raiseError(MDB2_ERROR_MANAGERnullnull,
  1492.                         'Could not rollback the partially created database alterations ('.
  1493.                         $result->getMessage().' ('.$result->getUserinfo().'))');
  1494.             else {
  1495.                 $result $this->raiseError(MDB2_ERROR_MANAGERnullnull,
  1496.                     'the requested database alterations were only partially implemented ('.
  1497.                     $result->getMessage().' ('.$result->getUserinfo().'))');
  1498.             }
  1499.         }
  1500.         if ($support_transactions{
  1501.             $result $this->db->commit();
  1502.             if (PEAR::isError($result)) {
  1503.                 $result $this->raiseError(MDB2_ERROR_MANAGERnullnull,
  1504.                     'Could not end transaction after successfully implemented the requested database alterations ('.
  1505.                     $result->getMessage().' ('.$result->getUserinfo().'))');
  1506.             }
  1507.         }
  1508.         $this->db->setDatabase($previous_database_name);
  1509.         return $result;
  1510.     }
  1511.  
  1512.     // }}}
  1513.     // {{{ dumpDatabaseChanges()
  1514.  
  1515.     /**
  1516.      * Dump the changes between two database definitions.
  1517.      *
  1518.      * @param array $changes an associative array that specifies the list
  1519.      *  of database definitions changes as returned by the _compareDefinitions
  1520.      *  manager class function.
  1521.      * @return mixed MDB2_OK on success, or a MDB2 error object
  1522.      * @access public
  1523.      */
  1524.     function dumpDatabaseChanges($changes)
  1525.     {
  1526.         if (isset($changes['tables'])) {
  1527.             foreach ($changes['tables'as $table_name => $table{
  1528.                 $this->db->debug("$table_name:");
  1529.                 if (isset($table['add'])) {
  1530.                     $this->db->debug("\tAdded table '$table_name'");
  1531.                 elseif (isset($table['remove'])) {
  1532.                     $this->db->debug("\tRemoved table '$table_name'");
  1533.                 else {
  1534.                     if (isset($table['name'])) {
  1535.                         $this->db->debug("\tRenamed table '$table_name' to '".
  1536.                             $table['name']."'");
  1537.                     }
  1538.                     if (isset($table['added_fields'])) {
  1539.                         foreach ($table['added_fields'as $field_name => $field{
  1540.                             $this->db->debug("\tAdded field '".$field_name."'");
  1541.                         }
  1542.                     }
  1543.                     if (isset($table['removed_fields'])) {
  1544.                         foreach ($table['removed_fields'as $field_name => $field{
  1545.                             $this->db->debug("\tRemoved field '".$field_name."'");
  1546.                         }
  1547.                     }
  1548.                     if (isset($table['renamed_fields'])) {
  1549.                         foreach ($table['renamed_fields'as $field_name => $field{
  1550.                             $this->db->debug("\tRenamed field '".$field_name."' to '".
  1551.                                 $field['name']."'");
  1552.                         }
  1553.                     }
  1554.                     if (isset($table['changed_fields'])) {
  1555.                         foreach ($table['changed_fields'as $field_name => $field{
  1556.                             if (isset($field['type'])) {
  1557.                                 $this->db->debug(
  1558.                                     "\tChanged field '$field_name' type to '".
  1559.                                         $field['type']."'");
  1560.                             }
  1561.                             if (isset($field['unsigned'])) {
  1562.                                 $this->db->debug(
  1563.                                     "\tChanged field '$field_name' type to '".
  1564.                                     ($field['unsigned''' 'not ')."unsigned'");
  1565.                             }
  1566.                             if (isset($field['length'])) {
  1567.                                 $this->db->debug(
  1568.                                     "\tChanged field '$field_name' length to '".
  1569.                                     ($field['length'== 0 ? 'no length' $field['length'])."'");
  1570.                             }
  1571.                             if (isset($field['changed_default'])) {
  1572.                                 $this->db->debug(
  1573.                                     "\tChanged field '$field_name' default to ".
  1574.                                     (isset($field['default']"'".$field['default']."'" 'NULL'));
  1575.                             }
  1576.                             if (isset($field['changed_not_null'])) {
  1577.                                 $this->db->debug(
  1578.                                    "\tChanged field '$field_name' notnull to ".
  1579.                                     (isset($field['notnull']"'1'" '0')
  1580.                                 );
  1581.                             }
  1582.                         }
  1583.                     }
  1584.                 }
  1585.             }
  1586.         }
  1587.         if (isset($changes['sequences'])) {
  1588.             foreach ($changes['sequences'as $sequence_name => $sequence{
  1589.                 $this->db->debug("$sequence_name:");
  1590.                 if (isset($sequence['add'])) {
  1591.                     $this->db->debug("\tAdded sequence '$sequence_name'");
  1592.                 elseif (isset($sequence['remove'])) {
  1593.                     $this->db->debug("\tRemoved sequence '$sequence_name'");
  1594.                 else {
  1595.                     if (isset($sequence['name'])) {
  1596.                         $this->db->debug(
  1597.                             "\tRenamed sequence '$sequence_name' to '".
  1598.                             $sequence['name']."'");
  1599.                     }
  1600.                     if (isset($sequence['change'])) {
  1601.                         foreach ($sequence['change'as $sequence_name => $sequence{
  1602.                             if (isset($sequence['start'])) {
  1603.                                 $this->db->debug(
  1604.                                     "\tChanged sequence '$sequence_name' start to '".
  1605.                                     $sequence['start']."'");
  1606.                             }
  1607.                         }
  1608.                     }
  1609.                 }
  1610.             }
  1611.         }
  1612.         if (isset($changes['indexes'])) {
  1613.             foreach ($changes['indexes'as $table_name => $table{
  1614.                 $this->db->debug("$table_name:");
  1615.                 if (isset($table['added_indexes'])) {
  1616.                     foreach ($table['added_indexes'as $index_name => $index{
  1617.                         $this->db->debug("\tAdded index '".$index_name.
  1618.                             "' of table '$table_name'");
  1619.                     }
  1620.                 }
  1621.                 if (isset($table['removed_indexes'])) {
  1622.                     foreach ($table['removed_indexes'as $index_name => $index{
  1623.                         $this->db->debug("\tRemoved index '".$index_name.
  1624.                             "' of table '$table_name'");
  1625.                     }
  1626.                 }
  1627.                 if (isset($table['changed_indexes'])) {
  1628.                     foreach ($table['changed_indexes'as $index_name => $index{
  1629.                         if (isset($index['name'])) {
  1630.                             $this->db->debug(
  1631.                                 "\tRenamed index '".$index_name."' to '".$index['name'].
  1632.                                 "' on table '$table_name'");
  1633.                         }
  1634.                         if (isset($index['changed_unique'])) {
  1635.                             $this->db->debug(
  1636.                                 "\tChanged index '".$index_name."' unique to '".
  1637.                                 isset($index['unique'])."' on table '$table_name'");
  1638.                         }
  1639.                         if (isset($index['changed_fields'])) {
  1640.                             $this->db->debug("\tChanged index '".$index_name.
  1641.                                 "' on table '$table_name'");
  1642.                         }
  1643.                     }
  1644.                 }
  1645.             }
  1646.         }
  1647.         return MDB2_OK;
  1648.     }
  1649.  
  1650.     // }}}
  1651.     // {{{ dumpDatabase()
  1652.  
  1653.     /**
  1654.      * Dump a previously parsed database structure in the Metabase schema
  1655.      * XML based format suitable for the Metabase parser. This function
  1656.      * may optionally dump the database definition with initialization
  1657.      * commands that specify the data that is currently present in the tables.
  1658.      *
  1659.      * @param array $arguments an associative array that takes pairs of tag
  1660.      *  names and values that define dump options.
  1661.      *                  array (
  1662.      *                      'definition'    =>    Boolean
  1663.      *                          true   :  dump currently parsed definition
  1664.      *                          default:  dump currently connected database
  1665.      *                      'output_mode'    =>    String
  1666.      *                          'file' :   dump into a file
  1667.      *                          default:   dump using a function
  1668.      *                      'output'        =>    String
  1669.      *                          depending on the 'Output_Mode'
  1670.      *                                   name of the file
  1671.      *                                   name of the function
  1672.      *                      'end_of_line'        =>    String
  1673.      *                          end of line delimiter that should be used
  1674.      *                          default: "\n"
  1675.      *                  );
  1676.      * @param integer $dump constant that determines what data to dump
  1677.      *                       MDB2_MANAGER_DUMP_ALL       : the entire db
  1678.      *                       MDB2_MANAGER_DUMP_STRUCTURE : only the structure of the db
  1679.      *                       MDB2_MANAGER_DUMP_CONTENT   : only the content of the db
  1680.      * @return mixed MDB2_OK on success, or a MDB2 error object
  1681.      * @access public
  1682.      */
  1683.     function dumpDatabase($arguments$dump = MDB2_MANAGER_DUMP_ALL)
  1684.     {
  1685.         if (!isset($arguments['definition']|| !$arguments['definition']{
  1686.             if (!$this->db{
  1687.                 return $this->raiseError(MDB2_ERROR_NODBSELECTED,
  1688.                     nullnull'please connect to a RDBMS first');
  1689.             }
  1690.             $error $this->getDefinitionFromDatabase();
  1691.             if (PEAR::isError($error)) {
  1692.                 return $error;
  1693.             }
  1694.  
  1695.             // get initialization data
  1696.             if (isset($this->database_definition['tables']&& is_array($this->database_definition['tables'])) {
  1697.                 foreach ($this->database_definition['tables'as $table_name => $table{
  1698.                     if ($dump == MDB2_MANAGER_DUMP_ALL || $dump == MDB2_MANAGER_DUMP_CONTENT{
  1699.                         $types = array();
  1700.                         foreach ($table['fields'as $field{
  1701.                             $types[$field['type'];
  1702.                         }
  1703.                         $query 'SELECT '.implode(',',array_keys($table['fields']))." FROM $table_name";
  1704.                         $data $this->db->queryAll($query$typesMDB2_FETCHMODE_ASSOC);
  1705.                         if (PEAR::isError($data)) {
  1706.                             return $data;
  1707.                         }
  1708.                         $rows count($data);
  1709.                         if ($rows > 0{
  1710.                             $table['initialization'= array();
  1711.                             for ($row = 0; $row $rows$row++{
  1712.                                 if (!is_array($data[$row])) {
  1713.                                     break;
  1714.                                 }
  1715.                                 $instruction = array('type' => 'insert''fields' => $data[$row]);
  1716.                                 $this->database_definition['tables'][$table_name]['initialization'][$instruction;
  1717.                             }
  1718.                         }
  1719.                     }
  1720.                 }
  1721.             }
  1722.             $previous_database_name ($this->database_definition['name'!= '')
  1723.                 ? $this->db->setDatabase($this->database_definition['name']'';
  1724.         }
  1725.  
  1726.         require_once 'MDB2/Schema/Writer.php';
  1727.         $writer =new MDB2_Schema_Writer();
  1728.         $return $writer->dumpDatabase($this->database_definition$arguments$dump);
  1729.  
  1730.         if (isset($previous_database_name&& $previous_database_name != ''{
  1731.             $this->db->setDatabase($previous_database_name);
  1732.         }
  1733.  
  1734.         return $return;
  1735.     }
  1736.  
  1737.     // }}}
  1738.     // {{{ updateDatabase()
  1739.  
  1740.     /**
  1741.      * Compare the correspondent files of two versions of a database schema
  1742.      * definition: the previously installed and the one that defines the schema
  1743.      * that is meant to update the database.
  1744.      * If the specified previous definition file does not exist, this function
  1745.      * will create the database from the definition specified in the current
  1746.      * schema file.
  1747.      * If both files exist, the function assumes that the database was previously
  1748.      * installed based on the previous schema file and will update it by just
  1749.      * applying the changes.
  1750.      * If this function succeeds, the contents of the current schema file are
  1751.      * copied to replace the previous schema file contents. Any subsequent schema
  1752.      * changes should only be done on the file specified by the $current_schema_file
  1753.      * to let this function make a consistent evaluation of the exact changes that
  1754.      * need to be applied.
  1755.      *
  1756.      * @param string $current_schema_file name of the updated database schema
  1757.      *  definition file.
  1758.      * @param string $previous_schema_file name the previously installed database
  1759.      *  schema definition file.
  1760.      * @param array $variables an associative array that is passed to the argument
  1761.      *  of the same name to the parseDatabaseDefinitionFile function. (there third
  1762.      *  param)
  1763.      * @return mixed MDB2_OK on success, or a MDB2 error object
  1764.      * @access public
  1765.      */
  1766.     function updateDatabase($current_schema_file$previous_schema_file = false$variables = array())
  1767.     {
  1768.         $database_definition $this->parseDatabaseDefinitionFile(
  1769.             $current_schema_file,
  1770.             $variables,
  1771.             $this->options['fail_on_invalid_names']
  1772.         );
  1773.  
  1774.         if (PEAR::isError($database_definition)) {
  1775.             return $database_definition;
  1776.         }
  1777.  
  1778.         $this->database_definition = $database_definition;
  1779.         if ($previous_schema_file && file_exists($previous_schema_file)) {
  1780.             $errorcodes = array(MDB2_ERROR_UNSUPPORTEDMDB2_ERROR_NOT_CAPABLE);
  1781.             $this->db->expectError($errorcodes);
  1782.             $databases $this->db->manager->listDatabases();
  1783.             $this->db->popExpect();
  1784.             if (!MDB2::isError($databases$errorcodes)) {
  1785.                 return $databases;
  1786.             }
  1787.             if (!PEAR::isError($databases)
  1788.                 && (!is_array($databases|| !in_array($this->database_definition['name']$databases))
  1789.             {
  1790.                 return $this->raiseError(MDB2_ERRORnullnull,
  1791.                     'database to update does not exist: '.$this->database_definition['name']);
  1792.             }
  1793.             $previous_definition $this->parseDatabaseDefinitionFile($previous_schema_file$variables0);
  1794.             if (PEAR::isError($previous_definition)) {
  1795.                 return $previous_definition;
  1796.             }
  1797.             $changes $this->compareDefinitions($previous_definition);
  1798.             if (PEAR::isError($changes)) {
  1799.                 return $changes;
  1800.             }
  1801.             if (is_array($changes)) {
  1802.                 $result $this->alterDatabase($changes$previous_definition);
  1803.                 if (PEAR::isError($result)) {
  1804.                     return $result;
  1805.                 }
  1806.                 $copy = true;
  1807.                 if ($this->db->options['debug']{
  1808.                     $result $this->dumpDatabaseChanges($changes);
  1809.                     if (PEAR::isError($result)) {
  1810.                         return $result;
  1811.                     }
  1812.                 }
  1813.             }
  1814.         else {
  1815.             $result $this->createDatabase();
  1816.             if (PEAR::isError($result)) {
  1817.                 return $result;
  1818.             }
  1819.             if ($previous_schema_file && !copy($current_schema_file$previous_schema_file)) {
  1820.                 return $this->raiseError(MDB2_ERROR_MANAGERnullnull,
  1821.                     'Could not copy the new database definition file to the current file');
  1822.             }
  1823.         }
  1824.  
  1825.         return MDB2_OK;
  1826.     }
  1827.  
  1828.     // }}}
  1829. }
  1830. ?>

Documentation generated on Mon, 11 Mar 2019 14:31:23 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.