Initial repo created
[timetracker.git] / WEB-INF / lib / pear / MDB2 / Driver / Manager / Common.php
1 <?php
2 // +----------------------------------------------------------------------+
3 // | PHP versions 4 and 5                                                 |
4 // +----------------------------------------------------------------------+
5 // | Copyright (c) 1998-2008 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 // | Authors: Lukas Smith <smith@pooteeweet.org>                          |
43 // |          Lorenzo Alberton <l.alberton@quipo.it>                      |
44 // +----------------------------------------------------------------------+
45 //
46 // $Id: Common.php 327310 2012-08-27 15:16:18Z danielc $
47 //
48
49 /**
50  * @package  MDB2
51  * @category Database
52  * @author   Lukas Smith <smith@pooteeweet.org>
53  * @author   Lorenzo Alberton <l.alberton@quipo.it>
54  */
55
56 /**
57  * Base class for the management modules that is extended by each MDB2 driver
58  *
59  * To load this module in the MDB2 object:
60  * $mdb->loadModule('Manager');
61  *
62  * @package MDB2
63  * @category Database
64  * @author  Lukas Smith <smith@pooteeweet.org>
65  */
66 class MDB2_Driver_Manager_Common extends MDB2_Module_Common
67 {
68     // {{{ splitTableSchema()
69
70     /**
71      * Split the "[owner|schema].table" notation into an array
72      *
73      * @param string $table [schema and] table name
74      *
75      * @return array array(schema, table)
76      * @access private
77      */
78     function splitTableSchema($table)
79     {
80         $ret = array();
81         if (strpos($table, '.') !== false) {
82             return explode('.', $table);
83         }
84         return array(null, $table);
85     }
86
87     // }}}
88     // {{{ getFieldDeclarationList()
89
90     /**
91      * Get declaration of a number of field in bulk
92      *
93      * @param array $fields  a multidimensional associative array.
94      *      The first dimension determines the field name, while the second
95      *      dimension is keyed with the name of the properties
96      *      of the field being declared as array indexes. Currently, the types
97      *      of supported field properties are as follows:
98      *
99      *      default
100      *          Boolean value to be used as default for this field.
101      *
102      *      notnull
103      *          Boolean flag that indicates whether this field is constrained
104      *          to not be set to null.
105      *
106      * @return mixed string on success, a MDB2 error on failure
107      * @access public
108      */
109     function getFieldDeclarationList($fields)
110     {
111         $db = $this->getDBInstance();
112         if (MDB2::isError($db)) {
113             return $db;
114         }
115
116         if (!is_array($fields) || empty($fields)) {
117             return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
118                 'missing any fields', __FUNCTION__);
119         }
120         foreach ($fields as $field_name => $field) {
121             $query = $db->getDeclaration($field['type'], $field_name, $field);
122             if (MDB2::isError($query)) {
123                 return $query;
124             }
125             $query_fields[] = $query;
126         }
127         return implode(', ', $query_fields);
128     }
129
130     // }}}
131     // {{{ _fixSequenceName()
132
133     /**
134      * Removes any formatting in an sequence name using the 'seqname_format' option
135      *
136      * @param string $sqn string that containts name of a potential sequence
137      * @param bool $check if only formatted sequences should be returned
138      * @return string name of the sequence with possible formatting removed
139      * @access protected
140      */
141     function _fixSequenceName($sqn, $check = false)
142     {
143         $db = $this->getDBInstance();
144         if (MDB2::isError($db)) {
145             return $db;
146         }
147
148         $seq_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['seqname_format']).'$/i';
149         $seq_name = preg_replace($seq_pattern, '\\1', $sqn);
150         if ($seq_name && !strcasecmp($sqn, $db->getSequenceName($seq_name))) {
151             return $seq_name;
152         }
153         if ($check) {
154             return false;
155         }
156         return $sqn;
157     }
158
159     // }}}
160     // {{{ _fixIndexName()
161
162     /**
163      * Removes any formatting in an index name using the 'idxname_format' option
164      *
165      * @param string $idx string that containts name of anl index
166      * @return string name of the index with eventual formatting removed
167      * @access protected
168      */
169     function _fixIndexName($idx)
170     {
171         $db = $this->getDBInstance();
172         if (MDB2::isError($db)) {
173             return $db;
174         }
175
176         $idx_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['idxname_format']).'$/i';
177         $idx_name = preg_replace($idx_pattern, '\\1', $idx);
178         if ($idx_name && !strcasecmp($idx, $db->getIndexName($idx_name))) {
179             return $idx_name;
180         }
181         return $idx;
182     }
183
184     // }}}
185     // {{{ createDatabase()
186
187     /**
188      * create a new database
189      *
190      * @param string $name    name of the database that should be created
191      * @param array  $options array with charset, collation info
192      *
193      * @return mixed MDB2_OK on success, a MDB2 error on failure
194      * @access public
195      */
196     function createDatabase($database, $options = array())
197     {
198         $db = $this->getDBInstance();
199         if (MDB2::isError($db)) {
200             return $db;
201         }
202
203         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
204             'method not implemented', __FUNCTION__);
205     }
206
207     // }}}
208     // {{{ alterDatabase()
209
210     /**
211      * alter an existing database
212      *
213      * @param string $name    name of the database that should be created
214      * @param array  $options array with charset, collation info
215      *
216      * @return mixed MDB2_OK on success, a MDB2 error on failure
217      * @access public
218      */
219     function alterDatabase($database, $options = array())
220     {
221         $db = $this->getDBInstance();
222         if (MDB2::isError($db)) {
223             return $db;
224         }
225
226         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
227             'method not implemented', __FUNCTION__);
228     }
229
230     // }}}
231     // {{{ dropDatabase()
232
233     /**
234      * drop an existing database
235      *
236      * @param string $name name of the database that should be dropped
237      * @return mixed MDB2_OK on success, a MDB2 error on failure
238      * @access public
239      */
240     function dropDatabase($database)
241     {
242         $db = $this->getDBInstance();
243         if (MDB2::isError($db)) {
244             return $db;
245         }
246
247         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
248             'method not implemented', __FUNCTION__);
249     }
250
251     // }}}
252     // {{{ _getCreateTableQuery()
253
254     /**
255      * Create a basic SQL query for a new table creation
256      *
257      * @param string $name    Name of the database that should be created
258      * @param array  $fields  Associative array that contains the definition of each field of the new table
259      * @param array  $options An associative array of table options
260      *
261      * @return mixed string (the SQL query) on success, a MDB2 error on failure
262      * @see createTable()
263      */
264     function _getCreateTableQuery($name, $fields, $options = array())
265     {
266         $db = $this->getDBInstance();
267         if (MDB2::isError($db)) {
268             return $db;
269         }
270
271         if (!$name) {
272             return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
273                 'no valid table name specified', __FUNCTION__);
274         }
275         if (empty($fields)) {
276             return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
277                 'no fields specified for table "'.$name.'"', __FUNCTION__);
278         }
279         $query_fields = $this->getFieldDeclarationList($fields);
280         if (MDB2::isError($query_fields)) {
281             return $query_fields;
282         }
283         if (!empty($options['primary'])) {
284             $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')';
285         }
286
287         $name = $db->quoteIdentifier($name, true);
288         $result = 'CREATE ';
289         if (!empty($options['temporary'])) {
290             $result .= $this->_getTemporaryTableQuery();
291         }
292         $result .= " TABLE $name ($query_fields)";
293         return $result;
294     }
295
296     // }}}
297     // {{{ _getTemporaryTableQuery()
298
299     /**
300      * A method to return the required SQL string that fits between CREATE ... TABLE
301      * to create the table as a temporary table.
302      *
303      * Should be overridden in driver classes to return the correct string for the
304      * specific database type.
305      *
306      * The default is to return the string "TEMPORARY" - this will result in a
307      * SQL error for any database that does not support temporary tables, or that
308      * requires a different SQL command from "CREATE TEMPORARY TABLE".
309      *
310      * @return string The string required to be placed between "CREATE" and "TABLE"
311      *                to generate a temporary table, if possible.
312      */
313     function _getTemporaryTableQuery()
314     {
315         return 'TEMPORARY';
316     }
317
318     // }}}
319     // {{{ createTable()
320
321     /**
322      * create a new table
323      *
324      * @param string $name   Name of the database that should be created
325      * @param array $fields  Associative array that contains the definition of each field of the new table
326      *                       The indexes of the array entries are the names of the fields of the table an
327      *                       the array entry values are associative arrays like those that are meant to be
328      *                       passed with the field definitions to get[Type]Declaration() functions.
329      *                          array(
330      *                              'id' => array(
331      *                                  'type' => 'integer',
332      *                                  'unsigned' => 1
333      *                                  'notnull' => 1
334      *                                  'default' => 0
335      *                              ),
336      *                              'name' => array(
337      *                                  'type' => 'text',
338      *                                  'length' => 12
339      *                              ),
340      *                              'password' => array(
341      *                                  'type' => 'text',
342      *                                  'length' => 12
343      *                              )
344      *                          );
345      * @param array $options  An associative array of table options:
346      *                          array(
347      *                              'comment' => 'Foo',
348      *                              'temporary' => true|false,
349      *                          );
350      * @return mixed MDB2_OK on success, a MDB2 error on failure
351      * @access public
352      */
353     function createTable($name, $fields, $options = array())
354     {
355         $query = $this->_getCreateTableQuery($name, $fields, $options);
356         if (MDB2::isError($query)) {
357             return $query;
358         }
359         $db = $this->getDBInstance();
360         if (MDB2::isError($db)) {
361             return $db;
362         }
363         $result = $db->exec($query);
364         if (MDB2::isError($result)) {
365             return $result;
366         }
367         return MDB2_OK;
368     }
369
370     // }}}
371     // {{{ dropTable()
372
373     /**
374      * drop an existing table
375      *
376      * @param string $name name of the table that should be dropped
377      * @return mixed MDB2_OK on success, a MDB2 error on failure
378      * @access public
379      */
380     function dropTable($name)
381     {
382         $db = $this->getDBInstance();
383         if (MDB2::isError($db)) {
384             return $db;
385         }
386
387         $name = $db->quoteIdentifier($name, true);
388         $result = $db->exec("DROP TABLE $name");
389         if (MDB2::isError($result)) {
390             return $result;
391         }
392         return MDB2_OK;
393     }
394
395     // }}}
396     // {{{ truncateTable()
397
398     /**
399      * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
400      * it falls back to a DELETE FROM TABLE query)
401      *
402      * @param string $name name of the table that should be truncated
403      * @return mixed MDB2_OK on success, a MDB2 error on failure
404      * @access public
405      */
406     function truncateTable($name)
407     {
408         $db = $this->getDBInstance();
409         if (MDB2::isError($db)) {
410             return $db;
411         }
412
413         $name = $db->quoteIdentifier($name, true);
414         $result = $db->exec("DELETE FROM $name");
415         if (MDB2::isError($result)) {
416             return $result;
417         }
418         return MDB2_OK;
419     }
420
421     // }}}
422     // {{{ vacuum()
423
424     /**
425      * Optimize (vacuum) all the tables in the db (or only the specified table)
426      * and optionally run ANALYZE.
427      *
428      * @param string $table table name (all the tables if empty)
429      * @param array  $options an array with driver-specific options:
430      *               - timeout [int] (in seconds) [mssql-only]
431      *               - analyze [boolean] [pgsql and mysql]
432      *               - full [boolean] [pgsql-only]
433      *               - freeze [boolean] [pgsql-only]
434      *
435      * @return mixed MDB2_OK success, a MDB2 error on failure
436      * @access public
437      */
438     function vacuum($table = null, $options = array())
439     {
440         $db = $this->getDBInstance();
441         if (MDB2::isError($db)) {
442             return $db;
443         }
444
445         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
446             'method not implemented', __FUNCTION__);
447     }
448
449     // }}}
450     // {{{ alterTable()
451
452     /**
453      * alter an existing table
454      *
455      * @param string $name         name of the table that is intended to be changed.
456      * @param array $changes     associative array that contains the details of each type
457      *                             of change that is intended to be performed. The types of
458      *                             changes that are currently supported are defined as follows:
459      *
460      *                             name
461      *
462      *                                New name for the table.
463      *
464      *                            add
465      *
466      *                                Associative array with the names of fields to be added as
467      *                                 indexes of the array. The value of each entry of the array
468      *                                 should be set to another associative array with the properties
469      *                                 of the fields to be added. The properties of the fields should
470      *                                 be the same as defined by the MDB2 parser.
471      *
472      *
473      *                            remove
474      *
475      *                                Associative array with the names of fields to be removed as indexes
476      *                                 of the array. Currently the values assigned to each entry are ignored.
477      *                                 An empty array should be used for future compatibility.
478      *
479      *                            rename
480      *
481      *                                Associative array with the names of fields to be renamed as indexes
482      *                                 of the array. The value of each entry of the array should be set to
483      *                                 another associative array with the entry named name with the new
484      *                                 field name and the entry named Declaration that is expected to contain
485      *                                 the portion of the field declaration already in DBMS specific SQL code
486      *                                 as it is used in the CREATE TABLE statement.
487      *
488      *                            change
489      *
490      *                                Associative array with the names of the fields to be changed as indexes
491      *                                 of the array. Keep in mind that if it is intended to change either the
492      *                                 name of a field and any other properties, the change array entries
493      *                                 should have the new names of the fields as array indexes.
494      *
495      *                                The value of each entry of the array should be set to another associative
496      *                                 array with the properties of the fields to that are meant to be changed as
497      *                                 array entries. These entries should be assigned to the new values of the
498      *                                 respective properties. The properties of the fields should be the same
499      *                                 as defined by the MDB2 parser.
500      *
501      *                            Example
502      *                                array(
503      *                                    'name' => 'userlist',
504      *                                    'add' => array(
505      *                                        'quota' => array(
506      *                                            'type' => 'integer',
507      *                                            'unsigned' => 1
508      *                                        )
509      *                                    ),
510      *                                    'remove' => array(
511      *                                        'file_limit' => array(),
512      *                                        'time_limit' => array()
513      *                                    ),
514      *                                    'change' => array(
515      *                                        'name' => array(
516      *                                            'length' => '20',
517      *                                            'definition' => array(
518      *                                                'type' => 'text',
519      *                                                'length' => 20,
520      *                                            ),
521      *                                        )
522      *                                    ),
523      *                                    'rename' => array(
524      *                                        'sex' => array(
525      *                                            'name' => 'gender',
526      *                                            'definition' => array(
527      *                                                'type' => 'text',
528      *                                                'length' => 1,
529      *                                                'default' => 'M',
530      *                                            ),
531      *                                        )
532      *                                    )
533      *                                )
534      *
535      * @param boolean $check     indicates whether the function should just check if the DBMS driver
536      *                             can perform the requested table alterations if the value is true or
537      *                             actually perform them otherwise.
538      * @access public
539      *
540       * @return mixed MDB2_OK on success, a MDB2 error on failure
541      */
542     function alterTable($name, $changes, $check)
543     {
544         $db = $this->getDBInstance();
545         if (MDB2::isError($db)) {
546             return $db;
547         }
548
549         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
550             'method not implemented', __FUNCTION__);
551     }
552
553     // }}}
554     // {{{ listDatabases()
555
556     /**
557      * list all databases
558      *
559      * @return mixed array of database names on success, a MDB2 error on failure
560      * @access public
561      */
562     function listDatabases()
563     {
564         $db = $this->getDBInstance();
565         if (MDB2::isError($db)) {
566             return $db;
567         }
568
569         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
570             'method not implementedd', __FUNCTION__);
571     }
572
573     // }}}
574     // {{{ listUsers()
575
576     /**
577      * list all users
578      *
579      * @return mixed array of user names on success, a MDB2 error on failure
580      * @access public
581      */
582     function listUsers()
583     {
584         $db = $this->getDBInstance();
585         if (MDB2::isError($db)) {
586             return $db;
587         }
588
589         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
590             'method not implemented', __FUNCTION__);
591     }
592
593     // }}}
594     // {{{ listViews()
595
596     /**
597      * list all views in the current database
598      *
599      * @param string database, the current is default
600      *               NB: not all the drivers can get the view names from
601      *               a database other than the current one
602      * @return mixed array of view names on success, a MDB2 error on failure
603      * @access public
604      */
605     function listViews($database = null)
606     {
607         $db = $this->getDBInstance();
608         if (MDB2::isError($db)) {
609             return $db;
610         }
611
612         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
613             'method not implemented', __FUNCTION__);
614     }
615
616     // }}}
617     // {{{ listTableViews()
618
619     /**
620      * list the views in the database that reference a given table
621      *
622      * @param string table for which all referenced views should be found
623      * @return mixed array of view names on success, a MDB2 error on failure
624      * @access public
625      */
626     function listTableViews($table)
627     {
628         $db = $this->getDBInstance();
629         if (MDB2::isError($db)) {
630             return $db;
631         }
632
633         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
634             'method not implemented', __FUNCTION__);
635     }
636
637     // }}}
638     // {{{ listTableTriggers()
639
640     /**
641      * list all triggers in the database that reference a given table
642      *
643      * @param string table for which all referenced triggers should be found
644      * @return mixed array of trigger names on success, a MDB2 error on failure
645      * @access public
646      */
647     function listTableTriggers($table = null)
648     {
649         $db = $this->getDBInstance();
650         if (MDB2::isError($db)) {
651             return $db;
652         }
653
654         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
655             'method not implemented', __FUNCTION__);
656     }
657
658     // }}}
659     // {{{ listFunctions()
660
661     /**
662      * list all functions in the current database
663      *
664      * @return mixed array of function names on success, a MDB2 error on failure
665      * @access public
666      */
667     function listFunctions()
668     {
669         $db = $this->getDBInstance();
670         if (MDB2::isError($db)) {
671             return $db;
672         }
673
674         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
675             'method not implemented', __FUNCTION__);
676     }
677
678     // }}}
679     // {{{ listTables()
680
681     /**
682      * list all tables in the current database
683      *
684      * @param string database, the current is default.
685      *               NB: not all the drivers can get the table names from
686      *               a database other than the current one
687      * @return mixed array of table names on success, a MDB2 error on failure
688      * @access public
689      */
690     function listTables($database = null)
691     {
692         $db = $this->getDBInstance();
693         if (MDB2::isError($db)) {
694             return $db;
695         }
696
697         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
698             'method not implemented', __FUNCTION__);
699     }
700
701     // }}}
702     // {{{ listTableFields()
703
704     /**
705      * list all fields in a table in the current database
706      *
707      * @param string $table name of table that should be used in method
708      * @return mixed array of field names on success, a MDB2 error on failure
709      * @access public
710      */
711     function listTableFields($table)
712     {
713         $db = $this->getDBInstance();
714         if (MDB2::isError($db)) {
715             return $db;
716         }
717
718         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
719             'method not implemented', __FUNCTION__);
720     }
721
722     // }}}
723     // {{{ createIndex()
724
725     /**
726      * Get the stucture of a field into an array
727      *
728      * @param string    $table         name of the table on which the index is to be created
729      * @param string    $name         name of the index to be created
730      * @param array     $definition        associative array that defines properties of the index to be created.
731      *                                 Currently, only one property named FIELDS is supported. This property
732      *                                 is also an associative with the names of the index fields as array
733      *                                 indexes. Each entry of this array is set to another type of associative
734      *                                 array that specifies properties of the index that are specific to
735      *                                 each field.
736      *
737      *                                Currently, only the sorting property is supported. It should be used
738      *                                 to define the sorting direction of the index. It may be set to either
739      *                                 ascending or descending.
740      *
741      *                                Not all DBMS support index sorting direction configuration. The DBMS
742      *                                 drivers of those that do not support it ignore this property. Use the
743      *                                 function supports() to determine whether the DBMS driver can manage indexes.
744      *
745      *                                 Example
746      *                                    array(
747      *                                        'fields' => array(
748      *                                            'user_name' => array(
749      *                                                'sorting' => 'ascending'
750      *                                            ),
751      *                                            'last_login' => array()
752      *                                        )
753      *                                    )
754      * @return mixed MDB2_OK on success, a MDB2 error on failure
755      * @access public
756      */
757     function createIndex($table, $name, $definition)
758     {
759         $db = $this->getDBInstance();
760         if (MDB2::isError($db)) {
761             return $db;
762         }
763
764         $table = $db->quoteIdentifier($table, true);
765         $name = $db->quoteIdentifier($db->getIndexName($name), true);
766         $query = "CREATE INDEX $name ON $table";
767         $fields = array();
768         foreach (array_keys($definition['fields']) as $field) {
769             $fields[] = $db->quoteIdentifier($field, true);
770         }
771         $query .= ' ('. implode(', ', $fields) . ')';
772         $result = $db->exec($query);
773         if (MDB2::isError($result)) {
774             return $result;
775         }
776         return MDB2_OK;
777     }
778
779     // }}}
780     // {{{ dropIndex()
781
782     /**
783      * drop existing index
784      *
785      * @param string    $table         name of table that should be used in method
786      * @param string    $name         name of the index to be dropped
787      * @return mixed MDB2_OK on success, a MDB2 error on failure
788      * @access public
789      */
790     function dropIndex($table, $name)
791     {
792         $db = $this->getDBInstance();
793         if (MDB2::isError($db)) {
794             return $db;
795         }
796
797         $name = $db->quoteIdentifier($db->getIndexName($name), true);
798         $result = $db->exec("DROP INDEX $name");
799         if (MDB2::isError($result)) {
800             return $result;
801         }
802         return MDB2_OK;
803     }
804
805     // }}}
806     // {{{ listTableIndexes()
807
808     /**
809      * list all indexes in a table
810      *
811      * @param string $table name of table that should be used in method
812      * @return mixed array of index names on success, a MDB2 error on failure
813      * @access public
814      */
815     function listTableIndexes($table)
816     {
817         $db = $this->getDBInstance();
818         if (MDB2::isError($db)) {
819             return $db;
820         }
821
822         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
823             'method not implemented', __FUNCTION__);
824     }
825
826     // }}}
827     // {{{ _getAdvancedFKOptions()
828
829     /**
830      * Return the FOREIGN KEY query section dealing with non-standard options
831      * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
832      *
833      * @param array $definition
834      * @return string
835      * @access protected
836      */
837     function _getAdvancedFKOptions($definition)
838     {
839         return '';
840     }
841
842     // }}}
843     // {{{ createConstraint()
844
845     /**
846      * create a constraint on a table
847      *
848      * @param string    $table       name of the table on which the constraint is to be created
849      * @param string    $name        name of the constraint to be created
850      * @param array     $definition  associative array that defines properties of the constraint to be created.
851      *                               The full structure of the array looks like this:
852      *          <pre>
853      *          array (
854      *              [primary] => 0
855      *              [unique]  => 0
856      *              [foreign] => 1
857      *              [check]   => 0
858      *              [fields] => array (
859      *                  [field1name] => array() // one entry per each field covered
860      *                  [field2name] => array() // by the index
861      *                  [field3name] => array(
862      *                      [sorting]  => ascending
863      *                      [position] => 3
864      *                  )
865      *              )
866      *              [references] => array(
867      *                  [table] => name
868      *                  [fields] => array(
869      *                      [field1name] => array(  //one entry per each referenced field
870      *                           [position] => 1
871      *                      )
872      *                  )
873      *              )
874      *              [deferrable] => 0
875      *              [initiallydeferred] => 0
876      *              [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
877      *              [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
878      *              [match] => SIMPLE|PARTIAL|FULL
879      *          );
880      *          </pre>
881      * @return mixed MDB2_OK on success, a MDB2 error on failure
882      * @access public
883      */
884     function createConstraint($table, $name, $definition)
885     {
886         $db = $this->getDBInstance();
887         if (MDB2::isError($db)) {
888             return $db;
889         }
890         $table = $db->quoteIdentifier($table, true);
891         $name = $db->quoteIdentifier($db->getIndexName($name), true);
892         $query = "ALTER TABLE $table ADD CONSTRAINT $name";
893         if (!empty($definition['primary'])) {
894             $query.= ' PRIMARY KEY';
895         } elseif (!empty($definition['unique'])) {
896             $query.= ' UNIQUE';
897         } elseif (!empty($definition['foreign'])) {
898             $query.= ' FOREIGN KEY';
899         }
900         $fields = array();
901         foreach (array_keys($definition['fields']) as $field) {
902             $fields[] = $db->quoteIdentifier($field, true);
903         }
904         $query .= ' ('. implode(', ', $fields) . ')';
905         if (!empty($definition['foreign'])) {
906             $query.= ' REFERENCES ' . $db->quoteIdentifier($definition['references']['table'], true);
907             $referenced_fields = array();
908             foreach (array_keys($definition['references']['fields']) as $field) {
909                 $referenced_fields[] = $db->quoteIdentifier($field, true);
910             }
911             $query .= ' ('. implode(', ', $referenced_fields) . ')';
912             $query .= $this->_getAdvancedFKOptions($definition);
913         }
914         $result = $db->exec($query);
915         if (MDB2::isError($result)) {
916             return $result;
917         }
918         return MDB2_OK;
919     }
920
921     // }}}
922     // {{{ dropConstraint()
923
924     /**
925      * drop existing constraint
926      *
927      * @param string    $table        name of table that should be used in method
928      * @param string    $name         name of the constraint to be dropped
929      * @param string    $primary      hint if the constraint is primary
930      * @return mixed MDB2_OK on success, a MDB2 error on failure
931      * @access public
932      */
933     function dropConstraint($table, $name, $primary = false)
934     {
935         $db = $this->getDBInstance();
936         if (MDB2::isError($db)) {
937             return $db;
938         }
939
940         $table = $db->quoteIdentifier($table, true);
941         $name = $db->quoteIdentifier($db->getIndexName($name), true);
942         $result = $db->exec("ALTER TABLE $table DROP CONSTRAINT $name");
943         if (MDB2::isError($result)) {
944             return $result;
945         }
946         return MDB2_OK;
947     }
948
949     // }}}
950     // {{{ listTableConstraints()
951
952     /**
953      * list all constraints in a table
954      *
955      * @param string $table name of table that should be used in method
956      * @return mixed array of constraint names on success, a MDB2 error on failure
957      * @access public
958      */
959     function listTableConstraints($table)
960     {
961         $db = $this->getDBInstance();
962         if (MDB2::isError($db)) {
963             return $db;
964         }
965
966         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
967             'method not implemented', __FUNCTION__);
968     }
969
970     // }}}
971     // {{{ createSequence()
972
973     /**
974      * create sequence
975      *
976      * @param string    $seq_name     name of the sequence to be created
977      * @param string    $start         start value of the sequence; default is 1
978      * @return mixed MDB2_OK on success, a MDB2 error on failure
979      * @access public
980      */
981     function createSequence($seq_name, $start = 1)
982     {
983         $db = $this->getDBInstance();
984         if (MDB2::isError($db)) {
985             return $db;
986         }
987
988         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
989             'method not implemented', __FUNCTION__);
990     }
991
992     // }}}
993     // {{{ dropSequence()
994
995     /**
996      * drop existing sequence
997      *
998      * @param string    $seq_name     name of the sequence to be dropped
999      * @return mixed MDB2_OK on success, a MDB2 error on failure
1000      * @access public
1001      */
1002     function dropSequence($name)
1003     {
1004         $db = $this->getDBInstance();
1005         if (MDB2::isError($db)) {
1006             return $db;
1007         }
1008
1009         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
1010             'method not implemented', __FUNCTION__);
1011     }
1012
1013     // }}}
1014     // {{{ listSequences()
1015
1016     /**
1017      * list all sequences in the current database
1018      *
1019      * @param string database, the current is default
1020      *               NB: not all the drivers can get the sequence names from
1021      *               a database other than the current one
1022      * @return mixed array of sequence names on success, a MDB2 error on failure
1023      * @access public
1024      */
1025     function listSequences($database = null)
1026     {
1027         $db = $this->getDBInstance();
1028         if (MDB2::isError($db)) {
1029             return $db;
1030         }
1031
1032         return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
1033             'method not implemented', __FUNCTION__);
1034     }
1035
1036     // }}}
1037 }
1038 ?>