From 2273d4117fd50ee44dcdaa28fd6444383dc403a0 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Tue, 26 Jan 2010 08:45:16 -0500
Subject: [PATCH] - Add support for MDB2's 'sqlsrv' driver (#1486395)

---
 program/lib/MDB2/Driver/Manager/Common.php |  592 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 495 insertions(+), 97 deletions(-)

diff --git a/program/lib/MDB2/Driver/Manager/Common.php b/program/lib/MDB2/Driver/Manager/Common.php
old mode 100755
new mode 100644
index a9de441..f7f07d9
--- a/program/lib/MDB2/Driver/Manager/Common.php
+++ b/program/lib/MDB2/Driver/Manager/Common.php
@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------+
 // | PHP versions 4 and 5                                                 |
 // +----------------------------------------------------------------------+
-// | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 |
 // | Stig. S. Bakken, Lukas Smith                                         |
 // | All rights reserved.                                                 |
 // +----------------------------------------------------------------------+
@@ -39,20 +39,25 @@
 // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
 // | POSSIBILITY OF SUCH DAMAGE.                                          |
 // +----------------------------------------------------------------------+
-// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// | Authors: Lukas Smith <smith@pooteeweet.org>                          |
+// |          Lorenzo Alberton <l.alberton@quipo.it>                      |
 // +----------------------------------------------------------------------+
 //
-// $Id$
+// $Id: Common.php 273526 2009-01-14 15:01:21Z quipo $
 //
 
 /**
  * @package  MDB2
  * @category Database
  * @author   Lukas Smith <smith@pooteeweet.org>
+ * @author   Lorenzo Alberton <l.alberton@quipo.it>
  */
 
 /**
  * Base class for the management modules that is extended by each MDB2 driver
+ *
+ * To load this module in the MDB2 object:
+ * $mdb->loadModule('Manager');
  *
  * @package MDB2
  * @category Database
@@ -60,13 +65,32 @@
  */
 class MDB2_Driver_Manager_Common extends MDB2_Module_Common
 {
+    // {{{ splitTableSchema()
+
+    /**
+     * Split the "[owner|schema].table" notation into an array
+     *
+     * @param string $table [schema and] table name
+     *
+     * @return array array(schema, table)
+     * @access private
+     */
+    function splitTableSchema($table)
+    {
+        $ret = array();
+        if (strpos($table, '.') !== false) {
+            return explode('.', $table);
+        }
+        return array(null, $table);
+    }
+
     // }}}
     // {{{ getFieldDeclarationList()
 
     /**
-     * get declaration of a number of field in bulk
+     * Get declaration of a number of field in bulk
      *
-     * @param string $fields  a multidimensional associative array.
+     * @param array $fields  a multidimensional associative array.
      *      The first dimension determines the field name, while the second
      *      dimension is keyed with the name of the properties
      *      of the field being declared as array indexes. Currently, the types
@@ -89,31 +113,32 @@
             return $db;
         }
 
-        if (is_array($fields)) {
-            foreach ($fields as $field_name => $field) {
-                $query = $db->getDeclaration($field['type'], $field_name, $field);
-                if (PEAR::isError($query)) {
-                    return $query;
-                }
-                $query_fields[] = $query;
-            }
-            return implode(',', $query_fields);
+        if (!is_array($fields) || empty($fields)) {
+            return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                'missing any fields', __FUNCTION__);
         }
-        return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
-            'getFieldDeclarationList: the definition of the table "'.$table_name.'" does not contain any fields');
+        foreach ($fields as $field_name => $field) {
+            $query = $db->getDeclaration($field['type'], $field_name, $field);
+            if (PEAR::isError($query)) {
+                return $query;
+            }
+            $query_fields[] = $query;
+        }
+        return implode(', ', $query_fields);
     }
 
     // }}}
-    // {{{ _isSequenceName()
+    // {{{ _fixSequenceName()
 
     /**
-     * list all tables in the current database
+     * Removes any formatting in an sequence name using the 'seqname_format' option
      *
      * @param string $sqn string that containts name of a potential sequence
-     * @return mixed name of the sequence if $sqn is a name of a sequence, else false
+     * @param bool $check if only formatted sequences should be returned
+     * @return string name of the sequence with possible formatting removed
      * @access protected
      */
-    function _isSequenceName($sqn)
+    function _fixSequenceName($sqn, $check = false)
     {
         $db =& $this->getDBInstance();
         if (PEAR::isError($db)) {
@@ -122,10 +147,38 @@
 
         $seq_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['seqname_format']).'$/i';
         $seq_name = preg_replace($seq_pattern, '\\1', $sqn);
-        if ($seq_name && $sqn == $db->getSequenceName($seq_name)) {
+        if ($seq_name && !strcasecmp($sqn, $db->getSequenceName($seq_name))) {
             return $seq_name;
         }
-        return false;
+        if ($check) {
+            return false;
+        }
+        return $sqn;
+    }
+
+    // }}}
+    // {{{ _fixIndexName()
+
+    /**
+     * Removes any formatting in an index name using the 'idxname_format' option
+     *
+     * @param string $idx string that containts name of anl index
+     * @return string name of the index with eventual formatting removed
+     * @access protected
+     */
+    function _fixIndexName($idx)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $idx_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['idxname_format']).'$/i';
+        $idx_name = preg_replace($idx_pattern, '\\1', $idx);
+        if ($idx_name && !strcasecmp($idx, $db->getIndexName($idx_name))) {
+            return $idx_name;
+        }
+        return $idx;
     }
 
     // }}}
@@ -134,11 +187,13 @@
     /**
      * create a new database
      *
-     * @param string $name name of the database that should be created
+     * @param string $name    name of the database that should be created
+     * @param array  $options array with charset, collation info
+     *
      * @return mixed MDB2_OK on success, a MDB2 error on failure
      * @access public
      */
-    function createDatabase($database)
+    function createDatabase($database, $options = array())
     {
         $db =& $this->getDBInstance();
         if (PEAR::isError($db)) {
@@ -146,7 +201,30 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'createDatabase: database creation is not supported');
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ alterDatabase()
+
+    /**
+     * alter an existing database
+     *
+     * @param string $name    name of the database that should be created
+     * @param array  $options array with charset, collation info
+     *
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function alterDatabase($database, $options = array())
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
@@ -167,43 +245,23 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'dropDatabase: database dropping is not supported');
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
-    // {{{ createTable()
+    // {{{ _getCreateTableQuery()
 
     /**
-     * create a new table
+     * Create a basic SQL query for a new table creation
      *
-     * @param string $name     Name of the database that should be created
-     * @param array $fields Associative array that contains the definition of each field of the new table
-     *                        The indexes of the array entries are the names of the fields of the table an
-     *                        the array entry values are associative arrays like those that are meant to be
-     *                         passed with the field definitions to get[Type]Declaration() functions.
+     * @param string $name    Name of the database that should be created
+     * @param array  $fields  Associative array that contains the definition of each field of the new table
+     * @param array  $options An associative array of table options
      *
-     *                        Example
-     *                        array(
-     *
-     *                            'id' => array(
-     *                                'type' => 'integer',
-     *                                'unsigned' => 1
-     *                                'notnull' => 1
-     *                                'default' => 0
-     *                            ),
-     *                            'name' => array(
-     *                                'type' => 'text',
-     *                                'length' => 12
-     *                            ),
-     *                            'password' => array(
-     *                                'type' => 'text',
-     *                                'length' => 12
-     *                            )
-     *                        );
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access public
+     * @return mixed string (the SQL query) on success, a MDB2 error on failure
+     * @see createTable()
      */
-    function createTable($name, $fields)
+    function _getCreateTableQuery($name, $fields, $options = array())
     {
         $db =& $this->getDBInstance();
         if (PEAR::isError($db)) {
@@ -212,19 +270,101 @@
 
         if (!$name) {
             return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
-                'createTable: no valid table name specified');
+                'no valid table name specified', __FUNCTION__);
         }
         if (empty($fields)) {
             return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
-                'createTable: no fields specified for table "'.$name.'"');
+                'no fields specified for table "'.$name.'"', __FUNCTION__);
         }
         $query_fields = $this->getFieldDeclarationList($fields);
         if (PEAR::isError($query_fields)) {
-            return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
-                'createTable: unkown error');
+            return $query_fields;
         }
-        $query = "CREATE TABLE $name ($query_fields)";
-        return $db->query($query);
+        if (!empty($options['primary'])) {
+            $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')';
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        $result = 'CREATE ';
+        if (!empty($options['temporary'])) {
+            $result .= $this->_getTemporaryTableQuery();
+        }
+        $result .= " TABLE $name ($query_fields)";
+        return $result;
+    }
+
+    // }}}
+    // {{{ _getTemporaryTableQuery()
+
+    /**
+     * A method to return the required SQL string that fits between CREATE ... TABLE
+     * to create the table as a temporary table.
+     *
+     * Should be overridden in driver classes to return the correct string for the
+     * specific database type.
+     *
+     * The default is to return the string "TEMPORARY" - this will result in a
+     * SQL error for any database that does not support temporary tables, or that
+     * requires a different SQL command from "CREATE TEMPORARY TABLE".
+     *
+     * @return string The string required to be placed between "CREATE" and "TABLE"
+     *                to generate a temporary table, if possible.
+     */
+    function _getTemporaryTableQuery()
+    {
+        return 'TEMPORARY';
+    }
+
+    // }}}
+    // {{{ createTable()
+
+    /**
+     * create a new table
+     *
+     * @param string $name   Name of the database that should be created
+     * @param array $fields  Associative array that contains the definition of each field of the new table
+     *                       The indexes of the array entries are the names of the fields of the table an
+     *                       the array entry values are associative arrays like those that are meant to be
+     *                       passed with the field definitions to get[Type]Declaration() functions.
+     *                          array(
+     *                              'id' => array(
+     *                                  'type' => 'integer',
+     *                                  'unsigned' => 1
+     *                                  'notnull' => 1
+     *                                  'default' => 0
+     *                              ),
+     *                              'name' => array(
+     *                                  'type' => 'text',
+     *                                  'length' => 12
+     *                              ),
+     *                              'password' => array(
+     *                                  'type' => 'text',
+     *                                  'length' => 12
+     *                              )
+     *                          );
+     * @param array $options  An associative array of table options:
+     *                          array(
+     *                              'comment' => 'Foo',
+     *                              'temporary' => true|false,
+     *                          );
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createTable($name, $fields, $options = array())
+    {
+        $query = $this->_getCreateTableQuery($name, $fields, $options);
+        if (PEAR::isError($query)) {
+            return $query;
+        }
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        $result = $db->exec($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        return MDB2_OK;
     }
 
     // }}}
@@ -244,7 +384,58 @@
             return $db;
         }
 
-        return $db->query("DROP TABLE $name");
+        $name = $db->quoteIdentifier($name, true);
+        return $db->exec("DROP TABLE $name");
+    }
+
+    // }}}
+    // {{{ truncateTable()
+
+    /**
+     * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
+     * it falls back to a DELETE FROM TABLE query)
+     *
+     * @param string $name name of the table that should be truncated
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function truncateTable($name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        return $db->exec("DELETE FROM $name");
+    }
+
+    // }}}
+    // {{{ vacuum()
+
+    /**
+     * Optimize (vacuum) all the tables in the db (or only the specified table)
+     * and optionally run ANALYZE.
+     *
+     * @param string $table table name (all the tables if empty)
+     * @param array  $options an array with driver-specific options:
+     *               - timeout [int] (in seconds) [mssql-only]
+     *               - analyze [boolean] [pgsql and mysql]
+     *               - full [boolean] [pgsql-only]
+     *               - freeze [boolean] [pgsql-only]
+     *
+     * @return mixed MDB2_OK success, a MDB2 error on failure
+     * @access public
+     */
+    function vacuum($table = null, $options = array())
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
@@ -268,7 +459,7 @@
      *                                 indexes of the array. The value of each entry of the array
      *                                 should be set to another associative array with the properties
      *                                 of the fields to be added. The properties of the fields should
-     *                                 be the same as defined by the Metabase parser.
+     *                                 be the same as defined by the MDB2 parser.
      *
      *
      *                            remove
@@ -297,7 +488,7 @@
      *                                 array with the properties of the fields to that are meant to be changed as
      *                                 array entries. These entries should be assigned to the new values of the
      *                                 respective properties. The properties of the fields should be the same
-     *                                 as defined by the Metabase parser.
+     *                                 as defined by the MDB2 parser.
      *
      *                            Example
      *                                array(
@@ -311,23 +502,34 @@
      *                                    'remove' => array(
      *                                        'file_limit' => array(),
      *                                        'time_limit' => array()
-     *                                        ),
+     *                                    ),
      *                                    'change' => array(
-     *                                        'gender' => array(
-     *                                            'default' => 'M',
+     *                                        'name' => array(
+     *                                            'length' => '20',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 20,
+     *                                            ),
      *                                        )
      *                                    ),
      *                                    'rename' => array(
      *                                        'sex' => array(
      *                                            'name' => 'gender',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 1,
+     *                                                'default' => 'M',
+     *                                            ),
      *                                        )
      *                                    )
      *                                )
+     *
      * @param boolean $check     indicates whether the function should just check if the DBMS driver
      *                             can perform the requested table alterations if the value is true or
      *                             actually perform them otherwise.
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
      * @access public
+     *
+      * @return mixed MDB2_OK on success, a MDB2 error on failure
      */
     function alterTable($name, $changes, $check)
     {
@@ -337,7 +539,7 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'alterTable: database table alterations are not supported');
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
@@ -346,7 +548,7 @@
     /**
      * list all databases
      *
-     * @return mixed data array on success, a MDB2 error on failure
+     * @return mixed array of database names on success, a MDB2 error on failure
      * @access public
      */
     function listDatabases()
@@ -357,7 +559,7 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'listDatabases: list databases is not supported');
+            'method not implementedd', __FUNCTION__);
     }
 
     // }}}
@@ -366,7 +568,7 @@
     /**
      * list all users
      *
-     * @return mixed data array on success, a MDB2 error on failure
+     * @return mixed array of user names on success, a MDB2 error on failure
      * @access public
      */
     function listUsers()
@@ -377,7 +579,7 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'listUsers: list user is not supported');
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
@@ -386,10 +588,13 @@
     /**
      * list all views in the current database
      *
-     * @return mixed data array on success, a MDB2 error on failure
+     * @param string database, the current is default
+     *               NB: not all the drivers can get the view names from
+     *               a database other than the current one
+     * @return mixed array of view names on success, a MDB2 error on failure
      * @access public
      */
-    function listViews()
+    function listViews($database = null)
     {
         $db =& $this->getDBInstance();
         if (PEAR::isError($db)) {
@@ -397,7 +602,49 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'listViews: list view is not supported');
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listTableViews()
+
+    /**
+     * list the views in the database that reference a given table
+     *
+     * @param string table for which all referenced views should be found
+     * @return mixed array of view names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableViews($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listTableTriggers()
+
+    /**
+     * list all triggers in the database that reference a given table
+     *
+     * @param string table for which all referenced triggers should be found
+     * @return mixed array of trigger names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableTriggers($table = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
@@ -406,7 +653,7 @@
     /**
      * list all functions in the current database
      *
-     * @return mixed data array on success, a MDB2 error on failure
+     * @return mixed array of function names on success, a MDB2 error on failure
      * @access public
      */
     function listFunctions()
@@ -417,7 +664,7 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'listFunctions: list function is not supported');
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
@@ -426,10 +673,13 @@
     /**
      * list all tables in the current database
      *
-     * @return mixed data array on success, a MDB2 error on failure
+     * @param string database, the current is default.
+     *               NB: not all the drivers can get the table names from
+     *               a database other than the current one
+     * @return mixed array of table names on success, a MDB2 error on failure
      * @access public
      */
-    function listTables()
+    function listTables($database = null)
     {
         $db =& $this->getDBInstance();
         if (PEAR::isError($db)) {
@@ -437,17 +687,17 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'listTables: list tables is not supported');
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
     // {{{ listTableFields()
 
     /**
-     * list all fields in a tables in the current database
+     * list all fields in a table in the current database
      *
      * @param string $table name of table that should be used in method
-     * @return mixed data array on success, a MDB2 error on failure
+     * @return mixed array of field names on success, a MDB2 error on failure
      * @access public
      */
     function listTableFields($table)
@@ -458,14 +708,14 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'listTableFields: list table fields is not supported');
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
     // {{{ createIndex()
 
     /**
-     * get the stucture of a field into an array
+     * Get the stucture of a field into an array
      *
      * @param string    $table         name of the table on which the index is to be created
      * @param string    $name         name of the index to be created
@@ -503,8 +753,15 @@
             return $db;
         }
 
-        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'createIndex: Creating Indexes is not supported');
+        $table = $db->quoteIdentifier($table, true);
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        $query = "CREATE INDEX $name ON $table";
+        $fields = array();
+        foreach (array_keys($definition['fields']) as $field) {
+            $fields[] = $db->quoteIdentifier($field, true);
+        }
+        $query .= ' ('. implode(', ', $fields) . ')';
+        return $db->exec($query);
     }
 
     // }}}
@@ -525,7 +782,8 @@
             return $db;
         }
 
-        return $db->query("DROP INDEX $name");
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        return $db->exec("DROP INDEX $name");
     }
 
     // }}}
@@ -534,8 +792,8 @@
     /**
      * list all indexes in a table
      *
-     * @param string    $table      name of table that should be used in method
-     * @return mixed data array on success, a MDB2 error on failure
+     * @param string $table name of table that should be used in method
+     * @return mixed array of index names on success, a MDB2 error on failure
      * @access public
      */
     function listTableIndexes($table)
@@ -546,7 +804,143 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'listTableIndexes: List Indexes is not supported');
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ _getAdvancedFKOptions()
+
+    /**
+     * Return the FOREIGN KEY query section dealing with non-standard options
+     * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
+     *
+     * @param array $definition
+     * @return string
+     * @access protected
+     */
+    function _getAdvancedFKOptions($definition)
+    {
+        return '';
+    }
+
+    // }}}
+    // {{{ createConstraint()
+
+    /**
+     * create a constraint on a table
+     *
+     * @param string    $table       name of the table on which the constraint is to be created
+     * @param string    $name        name of the constraint to be created
+     * @param array     $definition  associative array that defines properties of the constraint to be created.
+     *                               The full structure of the array looks like this:
+     *          <pre>
+     *          array (
+     *              [primary] => 0
+     *              [unique]  => 0
+     *              [foreign] => 1
+     *              [check]   => 0
+     *              [fields] => array (
+     *                  [field1name] => array() // one entry per each field covered
+     *                  [field2name] => array() // by the index
+     *                  [field3name] => array(
+     *                      [sorting]  => ascending
+     *                      [position] => 3
+     *                  )
+     *              )
+     *              [references] => array(
+     *                  [table] => name
+     *                  [fields] => array(
+     *                      [field1name] => array(  //one entry per each referenced field
+     *                           [position] => 1
+     *                      )
+     *                  )
+     *              )
+     *              [deferrable] => 0
+     *              [initiallydeferred] => 0
+     *              [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
+     *              [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
+     *              [match] => SIMPLE|PARTIAL|FULL
+     *          );
+     *          </pre>
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createConstraint($table, $name, $definition)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        $table = $db->quoteIdentifier($table, true);
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        $query = "ALTER TABLE $table ADD CONSTRAINT $name";
+        if (!empty($definition['primary'])) {
+            $query.= ' PRIMARY KEY';
+        } elseif (!empty($definition['unique'])) {
+            $query.= ' UNIQUE';
+        } elseif (!empty($definition['foreign'])) {
+            $query.= ' FOREIGN KEY';
+        }
+        $fields = array();
+        foreach (array_keys($definition['fields']) as $field) {
+            $fields[] = $db->quoteIdentifier($field, true);
+        }
+        $query .= ' ('. implode(', ', $fields) . ')';
+        if (!empty($definition['foreign'])) {
+            $query.= ' REFERENCES ' . $db->quoteIdentifier($definition['references']['table'], true);
+            $referenced_fields = array();
+            foreach (array_keys($definition['references']['fields']) as $field) {
+                $referenced_fields[] = $db->quoteIdentifier($field, true);
+            }
+            $query .= ' ('. implode(', ', $referenced_fields) . ')';
+            $query .= $this->_getAdvancedFKOptions($definition);
+        }
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ dropConstraint()
+
+    /**
+     * drop existing constraint
+     *
+     * @param string    $table        name of table that should be used in method
+     * @param string    $name         name of the constraint to be dropped
+     * @param string    $primary      hint if the constraint is primary
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropConstraint($table, $name, $primary = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        return $db->exec("ALTER TABLE $table DROP CONSTRAINT $name");
+    }
+
+    // }}}
+    // {{{ listTableConstraints()
+
+    /**
+     * list all constraints in a table
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of constraint names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableConstraints($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
@@ -568,7 +962,7 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'createSequence: sequence creation not supported');
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
@@ -589,7 +983,7 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'dropSequence: sequence dropping not supported');
+            'method not implemented', __FUNCTION__);
     }
 
     // }}}
@@ -598,10 +992,13 @@
     /**
      * list all sequences in the current database
      *
-     * @return mixed data array on success, a MDB2 error on failure
+     * @param string database, the current is default
+     *               NB: not all the drivers can get the sequence names from
+     *               a database other than the current one
+     * @return mixed array of sequence names on success, a MDB2 error on failure
      * @access public
      */
-    function listSequences()
+    function listSequences($database = null)
     {
         $db =& $this->getDBInstance();
         if (PEAR::isError($db)) {
@@ -609,8 +1006,9 @@
         }
 
         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
-            'listSequences: List sequences is not supported');
+            'method not implemented', __FUNCTION__);
     }
-}
 
-?>
+    // }}}
+}
+?>
\ No newline at end of file

--
Gitblit v1.9.1