Source for file Pgsql.php

Documentation is available at Pgsql.php

  1. <?php
  2. /*
  3.  *  $Id: Pgsql.php 2291 2007-08-29 22:03:55Z zYne $
  4.  *
  5.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16.  *
  17.  * This software consists of voluntary contributions made by many individuals
  18.  * and is licensed under the LGPL. For more information, see
  19.  * <http://www.phpdoctrine.com>.
  20.  */
  21. Doctrine::autoload('Doctrine_Export');
  22. /**
  23.  * Doctrine_Export_Pgsql
  24.  *
  25.  * @package     Doctrine
  26.  * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
  27.  * @author      Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
  28.  * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
  29.  * @category    Object Relational Mapping
  30.  * @link        www.phpdoctrine.com
  31.  * @since       1.0
  32.  * @version     $Revision: 2291 $
  33.  */
  34. {
  35.    /**
  36.      * create a new database
  37.      *
  38.      * @param string $name name of the database that should be created
  39.      * @throws PDOException
  40.      * @return void 
  41.      */
  42.     public function createDatabaseSql($name)
  43.     {
  44.         $query  'CREATE DATABASE ' $this->conn->quoteIdentifier($name);
  45.         
  46.         return $query;
  47.     }
  48.     /**
  49.      * drop an existing database
  50.      *
  51.      * @param string $name name of the database that should be dropped
  52.      * @throws PDOException
  53.      * @access public
  54.      */
  55.     public function dropDatabaseSql($name)
  56.     {
  57.         $query  'DROP DATABASE ' $this->conn->quoteIdentifier($name);
  58.         
  59.         return $query;
  60.     }
  61.     /**
  62.      * getAdvancedForeignKeyOptions
  63.      * Return the FOREIGN KEY query section dealing with non-standard options
  64.      * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
  65.      *
  66.      * @param array $definition         foreign key definition
  67.      * @return string 
  68.      * @access protected
  69.      */
  70.     public function getAdvancedForeignKeyOptions(array $definition)
  71.     {
  72.         $query '';
  73.         if (isset($definition['match'])) {
  74.             $query .= ' MATCH ' $definition['match'];
  75.         }
  76.         if (isset($definition['onUpdate'])) {
  77.             $query .= ' ON UPDATE ' $definition['onUpdate'];
  78.         }
  79.         if (isset($definition['onDelete'])) {
  80.             $query .= ' ON DELETE ' $definition['onDelete'];
  81.         }
  82.         if (isset($definition['deferrable'])) {
  83.             $query .= ' DEFERRABLE';
  84.         else {
  85.             $query .= ' NOT DEFERRABLE';
  86.         }
  87.         if (isset($definition['feferred'])) {
  88.             $query .= ' INITIALLY DEFERRED';
  89.         else {
  90.             $query .= ' INITIALLY IMMEDIATE';
  91.         }
  92.         return $query;
  93.     }
  94.  
  95.     /**
  96.      * alter an existing table
  97.      *
  98.      * @param string $name         name of the table that is intended to be changed.
  99.      * @param array $changes     associative array that contains the details of each type
  100.      *                              of change that is intended to be performed. The types of
  101.      *                              changes that are currently supported are defined as follows:
  102.      *
  103.      *                              name
  104.      *
  105.      *                                 New name for the table.
  106.      *
  107.      *                             add
  108.      *
  109.      *                                 Associative array with the names of fields to be added as
  110.      *                                  indexes of the array. The value of each entry of the array
  111.      *                                  should be set to another associative array with the properties
  112.      *                                  of the fields to be added. The properties of the fields should
  113.      *                                  be the same as defined by the Metabase parser.
  114.      *
  115.      *
  116.      *                             remove
  117.      *
  118.      *                                 Associative array with the names of fields to be removed as indexes
  119.      *                                  of the array. Currently the values assigned to each entry are ignored.
  120.      *                                  An empty array should be used for future compatibility.
  121.      *
  122.      *                             rename
  123.      *
  124.      *                                 Associative array with the names of fields to be renamed as indexes
  125.      *                                  of the array. The value of each entry of the array should be set to
  126.      *                                  another associative array with the entry named name with the new
  127.      *                                  field name and the entry named Declaration that is expected to contain
  128.      *                                  the portion of the field declaration already in DBMS specific SQL code
  129.      *                                  as it is used in the CREATE TABLE statement.
  130.      *
  131.      *                             change
  132.      *
  133.      *                                 Associative array with the names of the fields to be changed as indexes
  134.      *                                  of the array. Keep in mind that if it is intended to change either the
  135.      *                                  name of a field and any other properties, the change array entries
  136.      *                                  should have the new names of the fields as array indexes.
  137.      *
  138.      *                                 The value of each entry of the array should be set to another associative
  139.      *                                  array with the properties of the fields to that are meant to be changed as
  140.      *                                  array entries. These entries should be assigned to the new values of the
  141.      *                                  respective properties. The properties of the fields should be the same
  142.      *                                  as defined by the Metabase parser.
  143.      *
  144.      *                             Example
  145.      *                                 array(
  146.      *                                     'name' => 'userlist',
  147.      *                                     'add' => array(
  148.      *                                         'quota' => array(
  149.      *                                             'type' => 'integer',
  150.      *                                             'unsigned' => 1
  151.      *                                         )
  152.      *                                     ),
  153.      *                                     'remove' => array(
  154.      *                                         'file_limit' => array(),
  155.      *                                         'time_limit' => array()
  156.      *                                     ),
  157.      *                                     'change' => array(
  158.      *                                         'name' => array(
  159.      *                                             'length' => '20',
  160.      *                                             'definition' => array(
  161.      *                                                 'type' => 'text',
  162.      *                                                 'length' => 20,
  163.      *                                             ),
  164.      *                                         )
  165.      *                                     ),
  166.      *                                     'rename' => array(
  167.      *                                         'sex' => array(
  168.      *                                             'name' => 'gender',
  169.      *                                             'definition' => array(
  170.      *                                                 'type' => 'text',
  171.      *                                                 'length' => 1,
  172.      *                                                 'default' => 'M',
  173.      *                                             ),
  174.      *                                         )
  175.      *                                     )
  176.      *                                 )
  177.      *
  178.      * @param boolean $check     indicates whether the function should just check if the DBMS driver
  179.      *                              can perform the requested table alterations if the value is true or
  180.      *                              actually perform them otherwise.
  181.      * @throws Doctrine_Connection_Exception
  182.      * @return boolean 
  183.      */
  184.     public function alterTable($namearray $changes$check)
  185.     {
  186.         foreach ($changes as $changeName => $change{
  187.             switch ($changeName{
  188.                 case 'add':
  189.                 case 'remove':
  190.                 case 'change':
  191.                 case 'name':
  192.                 case 'rename':
  193.                     break;
  194.                 default:
  195.                     throw new Doctrine_Export_Exception('change type "' $changeName '\" not yet supported');
  196.             }
  197.         }
  198.  
  199.         if ($check{
  200.             return true;
  201.         }
  202.  
  203.         if (isset($changes['add']&& is_array($changes['add'])) {
  204.             foreach ($changes['add'as $fieldName => $field{
  205.                 $query 'ADD ' $this->getDeclaration($fieldName$field);
  206.                 $this->conn->exec('ALTER TABLE ' $name ' ' $query);
  207.             }
  208.         }
  209.  
  210.         if (isset($changes['remove']&& is_array($changes['remove'])) {
  211.             foreach ($changes['remove'as $fieldName => $field{
  212.                 $fieldName $this->conn->quoteIdentifier($fieldNametrue);
  213.                 $query 'DROP ' $fieldName;
  214.                 $this->conn->exec('ALTER TABLE ' $name ' ' $query);
  215.             }
  216.         }
  217.  
  218.         if (isset($changes['change']&& is_array($changes['change'])) {
  219.             foreach ($changes['change'as $fieldName => $field{
  220.                 $fieldName $this->conn->quoteIdentifier($fieldNametrue);
  221.                 if (isset($field['type'])) {
  222.                     $serverInfo $this->conn->getServerVersion();
  223.  
  224.                     if (is_array($serverInfo&& $serverInfo['major'8{
  225.                         throw new Doctrine_Export_Exception('changing column type for "'.$field['type'].'\" requires PostgreSQL 8.0 or above');
  226.                     }
  227.                     $query 'ALTER ' $fieldName ' TYPE ' $this->conn->datatype->getTypeDeclaration($field['definition']);
  228.                     $this->conn->exec('ALTER TABLE ' $name ' ' $query);;
  229.                 }
  230.                 if (array_key_exists('default'$field)) {
  231.                     $query 'ALTER ' $fieldName ' SET DEFAULT ' $this->conn->quote($field['definition']['default']$field['definition']['type']);
  232.                     $this->conn->exec('ALTER TABLE ' $name ' ' $query);
  233.                 }
  234.                 if (!empty($field['notnull'])) {
  235.                     $query 'ALTER ' $fieldName ' ' ($field['definition']['notnull''SET' 'DROP'' NOT NULL';
  236.                     $this->conn->exec('ALTER TABLE ' $name ' ' $query);
  237.                 }
  238.             }
  239.         }
  240.  
  241.         if (isset($changes['rename']&& is_array($changes['rename'])) {
  242.             foreach ($changes['rename'as $fieldName => $field{
  243.                 $fieldName $this->conn->quoteIdentifier($fieldNametrue);
  244.                 $this->conn->exec('ALTER TABLE ' $name ' RENAME COLUMN ' $fieldName ' TO ' $this->conn->quoteIdentifier($field['name']true));
  245.             }
  246.         }
  247.  
  248.         $name $this->conn->quoteIdentifier($nametrue);
  249.         if (isset($changes['name'])) {
  250.             $changeName $this->conn->quoteIdentifier($changes['name']true);
  251.             $this->conn->exec('ALTER TABLE ' $name ' RENAME TO ' $changeName);
  252.         }
  253.     }
  254.     /**
  255.      * return RDBMS specific create sequence statement
  256.      *
  257.      * @throws Doctrine_Connection_Exception     if something fails at database level
  258.      * @param string    $seqName        name of the sequence to be created
  259.      * @param string    $start          start value of the sequence; default is 1
  260.      * @param array     $options  An associative array of table options:
  261.      *                           array(
  262.      *                               'comment' => 'Foo',
  263.      *                               'charset' => 'utf8',
  264.      *                               'collate' => 'utf8_unicode_ci',
  265.      *                           );
  266.      * @return string 
  267.      */
  268.     public function createSequenceSql($sequenceName$start 1array $options array())
  269.     {
  270.         $sequenceName $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($sequenceName)true);
  271.         return $this->conn->exec('CREATE SEQUENCE ' $sequenceName ' INCREMENT 1' .
  272.                     ($start ' MINVALUE ' $start ''' START ' $start);
  273.     }
  274.     /**
  275.      * drop existing sequence
  276.      *
  277.      * @param string $sequenceName name of the sequence to be dropped
  278.      */
  279.     public function dropSequenceSql($sequenceName)
  280.     {
  281.         $sequenceName $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($sequenceName)true);
  282.         return 'DROP SEQUENCE ' $sequenceName;
  283.     }
  284.  
  285.     /**
  286.      * Creates a table.
  287.      *
  288.      * @param unknown_type $name 
  289.      * @param array $fields 
  290.      * @param array $options 
  291.      * @return unknown 
  292.      */
  293.     public function createTableSql($namearray $fieldsarray $options array())
  294.     {
  295.         if $name{
  296.             throw new Doctrine_Export_Exception('no valid table name specified');
  297.         }
  298.         
  299.         if (empty($fields)) {
  300.             throw new Doctrine_Export_Exception('no fields specified for table ' $name);
  301.         }
  302.  
  303.         $queryFields $this->getFieldDeclarationList($fields);
  304.  
  305.  
  306.         if (isset($options['primary']&& empty($options['primary'])) {
  307.             $queryFields .= ', PRIMARY KEY(' implode(', 'array_values($options['primary'])) ')';
  308.         }
  309.  
  310.         $query 'CREATE TABLE ' $this->conn->quoteIdentifier($nametrue' (' $queryFields ')';
  311.  
  312.         $sql[$query;
  313.  
  314.         if (isset($options['indexes']&& empty($options['indexes'])) {
  315.             foreach($options['indexes'as $index => $definition{
  316.                 $sql[$this->createIndexSql($name$index$definition);
  317.             }
  318.         }
  319.         
  320.         if (isset($options['foreignKeys'])) {
  321.  
  322.             foreach ((array) $options['foreignKeys'as $k => $definition{
  323.                 if (is_array($definition)) {
  324.                     $sql[$this->createForeignKeySql($name$definition);
  325.                 }
  326.             }
  327.         }
  328.         
  329.         return $sql;
  330.     }
  331.     
  332.     /**
  333.      * createForeignKeySql
  334.      *
  335.      * @param string    $table         name of the table on which the foreign key is to be created
  336.      * @param array     $definition    associative array that defines properties of the foreign key to be created.
  337.      * @return string 
  338.      */
  339.     public function createForeignKeySql($tablearray $definition)
  340.     {
  341.         $table $this->conn->quoteIdentifier($table);
  342.  
  343.         $query 'ALTER TABLE ' $table ' ADD ' $this->getForeignKeyDeclaration($definition);
  344.  
  345.         return $query;
  346.     
  347. }