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

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