ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
mysql.php
Go to the documentation of this file.
1 <?php
2 // +----------------------------------------------------------------------+
3 // | PHP versions 4 and 5 |
4 // +----------------------------------------------------------------------+
5 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
6 // | Stig. S. Bakken, Lukas Smith |
7 // | All rights reserved. |
8 // +----------------------------------------------------------------------+
9 // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
10 // | API as well as database abstraction for PHP applications. |
11 // | This LICENSE is in the BSD license style. |
12 // | |
13 // | Redistribution and use in source and binary forms, with or without |
14 // | modification, are permitted provided that the following conditions |
15 // | are met: |
16 // | |
17 // | Redistributions of source code must retain the above copyright |
18 // | notice, this list of conditions and the following disclaimer. |
19 // | |
20 // | Redistributions in binary form must reproduce the above copyright |
21 // | notice, this list of conditions and the following disclaimer in the |
22 // | documentation and/or other materials provided with the distribution. |
23 // | |
24 // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
25 // | Lukas Smith nor the names of his contributors may be used to endorse |
26 // | or promote products derived from this software without specific prior|
27 // | written permission. |
28 // | |
29 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
30 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
31 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
32 // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
33 // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
34 // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
35 // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
36 // | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
37 // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
38 // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
39 // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
40 // | POSSIBILITY OF SUCH DAMAGE. |
41 // +----------------------------------------------------------------------+
42 // | Author: Lukas Smith <smith@pooteeweet.org> |
43 // +----------------------------------------------------------------------+
44 //
45 // $Id: mysql.php,v 1.94 2007/03/04 22:50:16 quipo Exp $
46 //
47 
48 require_once 'MDB2/Driver/Manager/Common.php';
49 
58 {
59 
60  // }}}
61  // {{{ createDatabase()
62 
70  function createDatabase($name)
71  {
72  $db =& $this->getDBInstance();
73  if (PEAR::isError($db)) {
74  return $db;
75  }
76 
77  $name = $db->quoteIdentifier($name, true);
78  $query = "CREATE DATABASE $name";
79  $result = $db->exec($query);
80  if (PEAR::isError($result)) {
81  return $result;
82  }
83  return MDB2_OK;
84  }
85 
86  // }}}
87  // {{{ dropDatabase()
88 
96  function dropDatabase($name)
97  {
98  $db =& $this->getDBInstance();
99  if (PEAR::isError($db)) {
100  return $db;
101  }
102 
103  $name = $db->quoteIdentifier($name, true);
104  $query = "DROP DATABASE $name";
105  $result = $db->exec($query);
106  if (PEAR::isError($result)) {
107  return $result;
108  }
109  return MDB2_OK;
110  }
111 
112  // }}}
113  // {{{ createTable()
114 
150  function createTable($name, $fields, $options = array())
151  {
152  $db =& $this->getDBInstance();
153  if (PEAR::isError($db)) {
154  return $db;
155  }
156 
157  $query = $this->_getCreateTableQuery($name, $fields, $options);
158  if (PEAR::isError($query)) {
159  return $query;
160  }
161 
162  $options_strings = array();
163 
164  if (!empty($options['comment'])) {
165  $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text');
166  }
167 
168  if (!empty($options['charset'])) {
169  $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset'];
170  if (!empty($options['collate'])) {
171  $options_strings['charset'].= ' COLLATE '.$options['collate'];
172  }
173  }
174 
175  $type = false;
176  if (!empty($options['type'])) {
177  $type = $options['type'];
178  } elseif ($db->options['default_table_type']) {
179  $type = $db->options['default_table_type'];
180  }
181  if ($type) {
182  $options_strings[] = "ENGINE = $type";
183  }
184 
185  if (!empty($options_strings)) {
186  $query .= ' '.implode(' ', $options_strings);
187  }
188  return $db->exec($query);
189  }
190 
191  // }}}
192  // {{{ alterTable()
193 
284  function alterTable($name, $changes, $check)
285  {
286  $db =& $this->getDBInstance();
287  if (PEAR::isError($db)) {
288  return $db;
289  }
290 
291  foreach ($changes as $change_name => $change) {
292  switch ($change_name) {
293  case 'add':
294  case 'remove':
295  case 'change':
296  case 'rename':
297  case 'name':
298  break;
299  default:
300  return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
301  'change type "'.$change_name.'" not yet supported', __FUNCTION__);
302  }
303  }
304 
305  if ($check) {
306  return MDB2_OK;
307  }
308 
309  $query = '';
310  if (!empty($changes['name'])) {
311  $change_name = $db->quoteIdentifier($changes['name'], true);
312  $query .= 'RENAME TO ' . $change_name;
313  }
314 
315  if (!empty($changes['add']) && is_array($changes['add'])) {
316  foreach ($changes['add'] as $field_name => $field) {
317  if ($query) {
318  $query.= ', ';
319  }
320  $query.= 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
321  }
322  }
323 
324  if (!empty($changes['remove']) && is_array($changes['remove'])) {
325  foreach ($changes['remove'] as $field_name => $field) {
326  if ($query) {
327  $query.= ', ';
328  }
329  $field_name = $db->quoteIdentifier($field_name, true);
330  $query.= 'DROP ' . $field_name;
331  }
332  }
333 
334  $rename = array();
335  if (!empty($changes['rename']) && is_array($changes['rename'])) {
336  foreach ($changes['rename'] as $field_name => $field) {
337  $rename[$field['name']] = $field_name;
338  }
339  }
340 
341  if (!empty($changes['change']) && is_array($changes['change'])) {
342  foreach ($changes['change'] as $field_name => $field) {
343  if ($query) {
344  $query.= ', ';
345  }
346  if (isset($rename[$field_name])) {
347  $old_field_name = $rename[$field_name];
348  unset($rename[$field_name]);
349  } else {
350  $old_field_name = $field_name;
351  }
352  $old_field_name = $db->quoteIdentifier($old_field_name, true);
353  $query.= "CHANGE $old_field_name " . $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']);
354  }
355  }
356 
357  if (!empty($rename) && is_array($rename)) {
358  foreach ($rename as $rename_name => $renamed_field) {
359  if ($query) {
360  $query.= ', ';
361  }
362  $field = $changes['rename'][$renamed_field];
363  $renamed_field = $db->quoteIdentifier($renamed_field, true);
364  $query.= 'CHANGE ' . $renamed_field . ' ' . $db->getDeclaration($field['definition']['type'], $field['name'], $field['definition']);
365  }
366  }
367 
368  if (!$query) {
369  return MDB2_OK;
370  }
371 
372  $name = $db->quoteIdentifier($name, true);
373  return $db->exec("ALTER TABLE $name $query");
374  }
375 
376  // }}}
377  // {{{ listDatabases()
378 
385  function listDatabases()
386  {
387  $db =& $this->getDBInstance();
388  if (PEAR::isError($db)) {
389  return $db;
390  }
391 
392  $result = $db->queryCol('SHOW DATABASES');
393  if (PEAR::isError($result)) {
394  return $result;
395  }
396  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
397  $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
398  }
399  return $result;
400  }
401 
402  // }}}
403  // {{{ listUsers()
404 
411  function listUsers()
412  {
413  $db =& $this->getDBInstance();
414  if (PEAR::isError($db)) {
415  return $db;
416  }
417 
418  return $db->queryCol('SELECT DISTINCT USER FROM mysql.USER');
419  }
420 
421  // }}}
422  // {{{ listFunctions()
423 
430  function listFunctions()
431  {
432  $db =& $this->getDBInstance();
433  if (PEAR::isError($db)) {
434  return $db;
435  }
436 
437  $query = "SELECT name FROM mysql.proc";
438  /*
439  SELECT ROUTINE_NAME
440  FROM INFORMATION_SCHEMA.ROUTINES
441  WHERE ROUTINE_TYPE = 'FUNCTION'
442  */
443  $result = $db->queryCol($query);
444  if (PEAR::isError($result)) {
445  return $result;
446  }
447  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
448  $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
449  }
450  return $result;
451  }
452 
453  // }}}
454  // {{{ listTableTriggers()
455 
463  function listTableTriggers($table = null)
464  {
465  $db =& $this->getDBInstance();
466  if (PEAR::isError($db)) {
467  return $db;
468  }
469 
470  $query = 'SHOW TRIGGERS';
471  if (!is_null($table)) {
472  $table = $db->quote($table, 'text');
473  $query .= " LIKE $table";
474  }
475  $result = $db->queryCol($query);
476  if (PEAR::isError($result)) {
477  return $result;
478  }
479  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
480  $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
481  }
482  return $result;
483  }
484 
485  // }}}
486  // {{{ listTables()
487 
495  function listTables($database = null)
496  {
497  $db =& $this->getDBInstance();
498  if (PEAR::isError($db)) {
499  return $db;
500  }
501 
502  $query = "SHOW /*!50002 FULL*/ TABLES";
503  if (!is_null($database)) {
504  $query .= " FROM $database";
505  }
506  $query.= "/*!50002 WHERE Table_type = 'BASE TABLE'*/";
507 
508  $table_names = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED);
509  if (PEAR::isError($table_names)) {
510  return $table_names;
511  }
512 
513  $result = array();
514  foreach ($table_names as $table) {
515  if (!$this->_fixSequenceName($table[0], true)) {
516  $result[] = $table[0];
517  }
518  }
519  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
520  $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
521  }
522  return $result;
523  }
524 
525  // }}}
526  // {{{ listViews()
527 
535  function listViews($database = null)
536  {
537  $db =& $this->getDBInstance();
538  if (PEAR::isError($db)) {
539  return $db;
540  }
541 
542  $query = 'SHOW FULL TABLES';
543  if (!is_null($database)) {
544  $query.= " FROM $database";
545  }
546  $query.= " WHERE Table_type = 'VIEW'";
547 
548  $result = $db->queryCol($query);
549  if (PEAR::isError($result)) {
550  return $result;
551  }
552 
553  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
554  $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
555  }
556  return $result;
557  }
558 
559  // }}}
560  // {{{ listTableFields()
561 
569  function listTableFields($table)
570  {
571  $db =& $this->getDBInstance();
572  if (PEAR::isError($db)) {
573  return $db;
574  }
575 
576  $table = $db->quoteIdentifier($table, true);
577  $result = $db->queryCol("SHOW COLUMNS FROM $table");
578  if (PEAR::isError($result)) {
579  return $result;
580  }
581  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
582  $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
583  }
584  return $result;
585  }
586 
587  // }}}
588  // {{{ createIndex()
589 
624  function createIndex($table, $name, $definition)
625  {
626  $db =& $this->getDBInstance();
627  if (PEAR::isError($db)) {
628  return $db;
629  }
630 
631  $table = $db->quoteIdentifier($table, true);
632  $name = $db->quoteIdentifier($db->getIndexName($name), true);
633  $query = "CREATE INDEX $name ON $table";
634  $fields = array();
635  foreach ($definition['fields'] as $field => $fieldinfo) {
636  if (!empty($fieldinfo['length'])) {
637  $fields[] = $db->quoteIdentifier($field, true) . '(' . $fieldinfo['length'] . ')';
638  } else {
639  $fields[] = $db->quoteIdentifier($field, true);
640  }
641  }
642  $query .= ' ('. implode(', ', $fields) . ')';
643  return $db->exec($query);
644  }
645 
646  // }}}
647  // {{{ dropIndex()
648 
657  function dropIndex($table, $name)
658  {
659  $db =& $this->getDBInstance();
660  if (PEAR::isError($db)) {
661  return $db;
662  }
663 
664  $table = $db->quoteIdentifier($table, true);
665  $name = $db->quoteIdentifier($db->getIndexName($name), true);
666  return $db->exec("DROP INDEX $name ON $table");
667  }
668 
669  // }}}
670  // {{{ listTableIndexes()
671 
679  function listTableIndexes($table)
680  {
681  $db =& $this->getDBInstance();
682  if (PEAR::isError($db)) {
683  return $db;
684  }
685 
686  $key_name = 'Key_name';
687  $non_unique = 'Non_unique';
688  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
689  if ($db->options['field_case'] == CASE_LOWER) {
690  $key_name = strtolower($key_name);
691  $non_unique = strtolower($non_unique);
692  } else {
693  $key_name = strtoupper($key_name);
694  $non_unique = strtoupper($non_unique);
695  }
696  }
697 
698  $table = $db->quoteIdentifier($table, true);
699  $query = "SHOW INDEX FROM $table";
700  $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
701  if (PEAR::isError($indexes)) {
702  return $indexes;
703  }
704 
705  $result = array();
706  foreach ($indexes as $index_data) {
707  if ($index_data[$non_unique] && ($index = $this->_fixIndexName($index_data[$key_name]))) {
708  $result[$index] = true;
709  }
710  }
711 
712  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
713  $result = array_change_key_case($result, $db->options['field_case']);
714  }
715  return array_keys($result);
716  }
717 
718  // }}}
719  // {{{ createConstraint()
720 
743  function createConstraint($table, $name, $definition)
744  {
745  $db =& $this->getDBInstance();
746  if (PEAR::isError($db)) {
747  return $db;
748  }
749 
750  $type = '';
751  $name = $db->quoteIdentifier($db->getIndexName($name), true);
752  if (!empty($definition['primary'])) {
753  $type = 'PRIMARY';
754  $name = 'KEY';
755  } elseif (!empty($definition['unique'])) {
756  $type = 'UNIQUE';
757  }
758  if (empty($type)) {
759  return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
760  'invalid definition, could not create constraint', __FUNCTION__);
761  }
762 
763  $table = $db->quoteIdentifier($table, true);
764  $query = "ALTER TABLE $table ADD $type $name";
765  $fields = array();
766  foreach (array_keys($definition['fields']) as $field) {
767  $fields[] = $db->quoteIdentifier($field, true);
768  }
769  $query .= ' ('. implode(', ', $fields) . ')';
770  return $db->exec($query);
771  }
772 
773  // }}}
774  // {{{ dropConstraint()
775 
785  function dropConstraint($table, $name, $primary = false)
786  {
787  $db =& $this->getDBInstance();
788  if (PEAR::isError($db)) {
789  return $db;
790  }
791 
792  $table = $db->quoteIdentifier($table, true);
793  if ($primary || strtolower($name) == 'primary') {
794  $query = "ALTER TABLE $table DROP PRIMARY KEY";
795  } else {
796  $name = $db->quoteIdentifier($db->getIndexName($name), true);
797  $query = "ALTER TABLE $table DROP INDEX $name";
798  }
799  return $db->exec($query);
800  }
801 
802  // }}}
803  // {{{ listTableConstraints()
804 
812  function listTableConstraints($table)
813  {
814  $db =& $this->getDBInstance();
815  if (PEAR::isError($db)) {
816  return $db;
817  }
818 
819  $key_name = 'Key_name';
820  $non_unique = 'Non_unique';
821  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
822  if ($db->options['field_case'] == CASE_LOWER) {
823  $key_name = strtolower($key_name);
824  $non_unique = strtolower($non_unique);
825  } else {
826  $key_name = strtoupper($key_name);
827  $non_unique = strtoupper($non_unique);
828  }
829  }
830 
831  $table = $db->quoteIdentifier($table, true);
832  $query = "SHOW INDEX FROM $table";
833  $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
834  if (PEAR::isError($indexes)) {
835  return $indexes;
836  }
837 
838  $result = array();
839  foreach ($indexes as $index_data) {
840  if (!$index_data[$non_unique]) {
841  if ($index_data[$key_name] !== 'PRIMARY') {
842  $index = $this->_fixIndexName($index_data[$key_name]);
843  } else {
844  $index = 'PRIMARY';
845  }
846  if (!empty($index)) {
847  $result[$index] = true;
848  }
849  }
850  }
851 
852  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
853  $result = array_change_key_case($result, $db->options['field_case']);
854  }
855  return array_keys($result);
856  }
857 
858  // }}}
859  // {{{ createSequence()
860 
876  function createSequence($seq_name, $start = 1, $options = array())
877  {
878  $db =& $this->getDBInstance();
879  if (PEAR::isError($db)) {
880  return $db;
881  }
882 
883  $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
884  $seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true);
885 
886  $options_strings = array();
887 
888  if (!empty($options['comment'])) {
889  $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text');
890  }
891 
892  if (!empty($options['charset'])) {
893  $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset'];
894  if (!empty($options['collate'])) {
895  $options_strings['charset'].= ' COLLATE '.$options['collate'];
896  }
897  }
898 
899  $type = false;
900  if (!empty($options['type'])) {
901  $type = $options['type'];
902  } elseif ($db->options['default_table_type']) {
903  $type = $db->options['default_table_type'];
904  }
905  if ($type) {
906  $options_strings[] = "ENGINE = $type";
907  }
908 
909  $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))";
910  if (!empty($options_strings)) {
911  $query .= ' '.implode(' ', $options_strings);
912  }
913  $res = $db->exec($query);
914 
915  if (PEAR::isError($res)) {
916  return $res;
917  }
918 
919  if ($start == 1) {
920  return MDB2_OK;
921  }
922 
923  $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (".($start-1).')';
924  $res = $db->exec($query);
925  if (!PEAR::isError($res)) {
926  return MDB2_OK;
927  }
928 
929  // Handle error
930  $result = $db->exec("DROP TABLE $sequence_name");
931  if (PEAR::isError($result)) {
932  return $db->raiseError($result, null, null,
933  'could not drop inconsistent sequence table', __FUNCTION__);
934  }
935 
936  return $db->raiseError($res, null, null,
937  'could not create sequence table', __FUNCTION__);
938  }
939 
940  // }}}
941  // {{{ dropSequence()
942 
950  function dropSequence($seq_name)
951  {
952  $db =& $this->getDBInstance();
953  if (PEAR::isError($db)) {
954  return $db;
955  }
956 
957  $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
958  return $db->exec("DROP TABLE $sequence_name");
959  }
960 
961  // }}}
962  // {{{ listSequences()
963 
971  function listSequences($database = null)
972  {
973  $db =& $this->getDBInstance();
974  if (PEAR::isError($db)) {
975  return $db;
976  }
977 
978  $query = "SHOW TABLES";
979  if (!is_null($database)) {
980  $query .= " FROM $database";
981  }
982  $table_names = $db->queryCol($query);
983  if (PEAR::isError($table_names)) {
984  return $table_names;
985  }
986 
987  $result = array();
988  foreach ($table_names as $table_name) {
989  if ($sqn = $this->_fixSequenceName($table_name, true)) {
990  $result[] = $sqn;
991  }
992  }
993  if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
994  $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
995  }
996  return $result;
997  }
998 
999  // }}}
1000 }
1001 ?>