47 require_once
'MDB2/Driver/Manager/Common.php';
75 if (!$db->options[
'emulate_database']) {
77 'database creation is only supported if the "emulate_database" option is enabled', __FUNCTION__);
80 $username = $db->options[
'database_name_prefix'].$name;
81 $password = $db->dsn[
'password'] ? $db->dsn[
'password'] :
$name;
82 $tablespace = $db->options[
'default_tablespace']
83 ?
' DEFAULT TABLESPACE '.$db->options[
'default_tablespace'] :
'';
85 $query =
'CREATE USER '.$username.
' IDENTIFIED BY '.$password.$tablespace;
86 $result = $db->standaloneQuery(
$query, null,
true);
90 $query =
'GRANT CREATE SESSION, CREATE TABLE, UNLIMITED TABLESPACE, CREATE SEQUENCE, CREATE TRIGGER TO '.$username;
91 $result = $db->standaloneQuery(
$query, null,
true);
93 $query =
'DROP USER '.$username.
' CASCADE';
94 $result2 = $db->standaloneQuery(
$query, null,
true);
96 return $db->raiseError($result2, null, null,
97 'could not setup the database user', __FUNCTION__);
122 if (!$db->options[
'emulate_database']) {
124 'database dropping is only supported if the "emulate_database" option is enabled', __FUNCTION__);
127 $username = $db->options[
'database_name_prefix'].$name;
128 return $db->standaloneQuery(
'DROP USER '.$username.
' CASCADE', null,
true);
151 $table = strtoupper($table);
152 $index_name = $table .
'_AI_PK';
155 'fields' => array(
$name =>
true),
159 return $db->raiseError($result, null, null,
160 'primary key for autoincrement PK could not be created', __FUNCTION__);
163 if (is_null($start)) {
164 $db->beginTransaction();
165 $query =
'SELECT MAX(' . $db->quoteIdentifier(
$name,
true) .
') FROM ' . $db->quoteIdentifier($table,
true);
166 $start = $this->db->queryOne(
$query,
'integer');
177 return $db->raiseError($result, null, null,
178 'sequence for autoincrement PK could not be created', __FUNCTION__);
180 $sequence_name = $db->getSequenceName($table);
181 $trigger_name = $db->quoteIdentifier($table .
'_AI_PK',
true);
182 $table = $db->quoteIdentifier($table,
true);
185 CREATE TRIGGER '.$trigger_name.
'
190 last_Sequence NUMBER;
191 last_InsertID NUMBER;
193 SELECT '.$sequence_name.
'.NEXTVAL INTO :NEW.'.
$name.
' FROM DUAL;
194 IF (:NEW.'.
$name.
' IS NULL OR :NEW.'.
$name.
' = 0) THEN
195 SELECT '.$sequence_name.
'.NEXTVAL INTO :NEW.'.
$name.
' FROM DUAL;
197 SELECT NVL(Last_Number, 0) INTO last_Sequence
199 WHERE UPPER(Sequence_Name) = UPPER(\''.$sequence_name.
'\');
200 SELECT :NEW.
'.$name.' INTO last_InsertID FROM DUAL;
201 WHILE (last_InsertID > last_Sequence) LOOP
202 SELECT
'.$sequence_name.'.NEXTVAL INTO last_Sequence FROM DUAL;
207 return $db->exec($trigger_sql);
211 // {{{ _dropAutoincrement()
220 function _dropAutoincrement($table)
222 $db =& $this->getDBInstance();
223 if (PEAR::isError($db)) {
227 $table = strtoupper($table);
228 $trigger_name = $table . '_AI_PK
';
229 $trigger_name_quoted = $db->quote($trigger_name, 'text
');
230 $query = 'SELECT trigger_name FROM user_triggers
';
231 $query.= ' WHERE trigger_name=
'.$trigger_name_quoted.' OR trigger_name=
'.strtoupper($trigger_name_quoted);
232 $trigger = $db->queryOne($query);
233 if (PEAR::isError($trigger)) {
238 $trigger_name = $db->quoteIdentifier($table . '_AI_PK
', true);
239 $trigger_sql = 'DROP TRIGGER
' . $trigger_name;
240 $result = $db->exec($trigger_sql);
241 if (PEAR::isError($result)) {
242 return $db->raiseError($result, null, null,
243 'trigger
for autoincrement PK could not be dropped
', __FUNCTION__);
246 $result = $this->dropSequence($table);
247 if (PEAR::isError($result)) {
248 return $db->raiseError($result, null, null,
249 'sequence
for autoincrement PK could not be dropped
', __FUNCTION__);
252 $index_name = $table . '_AI_PK
';
253 $result = $this->dropConstraint($table, $index_name);
254 if (PEAR::isError($result)) {
255 return $db->raiseError($result, null, null,
256 'primary key
for autoincrement PK could not be dropped
', __FUNCTION__);
264 // {{{ _getTemporaryTableQuery()
273 function _getTemporaryTableQuery()
275 return 'GLOBAL TEMPORARY
';
316 function createTable($name, $fields, $options = array())
318 $db =& $this->getDBInstance();
319 if (PEAR::isError($db)) {
322 $db->beginNestedTransaction();
323 $result = parent::createTable($name, $fields, $options);
324 if (!PEAR::isError($result)) {
325 foreach ($fields as $field_name => $field) {
326 if (!empty($field['autoincrement
'])) {
327 $result = $this->_makeAutoincrement($field_name, $name);
331 $db->completeNestedTransaction();
345 function dropTable($name)
347 $db =& $this->getDBInstance();
348 if (PEAR::isError($db)) {
351 $db->beginNestedTransaction();
352 $result = $this->_dropAutoincrement($name);
353 if (!PEAR::isError($result)) {
354 $result = parent::dropTable($name);
356 $db->completeNestedTransaction();
453 function alterTable($name, $changes, $check)
455 $db =& $this->getDBInstance();
456 if (PEAR::isError($db)) {
460 foreach ($changes as $change_name => $change) {
461 switch ($change_name) {
469 return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
470 'change type
"'.$change_name.'" not yet supported
', __FUNCTION__);
478 $name = $db->quoteIdentifier($name, true);
480 if (!empty($changes['add
']) && is_array($changes['add
'])) {
482 foreach ($changes['add
'] as $field_name => $field) {
483 $fields[] = $db->getDeclaration($field['type
'], $field_name, $field);
485 $result = $db->exec("ALTER TABLE $name ADD (". implode(',
', $fields).')
');
486 if (PEAR::isError($result)) {
491 if (!empty($changes['change
']) && is_array($changes['change
'])) {
493 foreach ($changes['change
'] as $field_name => $field) {
494 $fields[] = $field_name. ' ' . $db->getDeclaration($field['definition
']['type
'], '', $field['definition
']);
496 $result = $db->exec("ALTER TABLE $name MODIFY (". implode(',
', $fields).')
');
497 if (PEAR::isError($result)) {
502 if (!empty($changes['rename
']) && is_array($changes['rename
'])) {
503 foreach ($changes['rename
'] as $field_name => $field) {
504 $field_name = $db->quoteIdentifier($field_name, true);
505 //$query = "ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name
']);
506 // Disabled case sensitive renaming smeyer
507 $query = "ALTER TABLE $name RENAME COLUMN $field_name TO ".$field['name
'];
508 $result = $db->exec($query);
509 if (PEAR::isError($result)) {
515 if (!empty($changes['remove']) && is_array($changes['remove'])) {
517 foreach ($changes['remove'] as $field_name => $field) {
518 $fields[] = $db->quoteIdentifier($field_name, true);
520 $result = $db->exec("ALTER TABLE $name DROP COLUMN ". implode(',
', $fields));
521 if (PEAR::isError($result)) {
526 if (!empty($changes['name
'])) {
527 $change_name = $db->quoteIdentifier($changes['name
'], true);
528 $result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name);
529 if (PEAR::isError($result)) {
538 // {{{ listDatabases()
546 function listDatabases()
548 $db =& $this->getDBInstance();
549 if (PEAR::isError($db)) {
553 if (!$db->options['emulate_database
']) {
554 return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
555 'database listing is only supported
if the
"emulate_database" option is enabled
', __FUNCTION__);
558 if ($db->options['database_name_prefix
']) {
559 $query = 'SELECT SUBSTR(username,
';
560 $query.= (strlen($db->options['database_name_prefix
'])+1);
561 $query.= ") FROM sys.dba_users WHERE username LIKE '";
562 $query.= $db->options['database_name_prefix']."%
'";
564 $query = 'SELECT username FROM sys.dba_users
';
566 $result2 = $db->standaloneQuery($query, array('text
'), false);
567 if (PEAR::isError($result2)) {
570 $result = $result2->fetchCol();
571 if (PEAR::isError($result)) {
574 if ($db->options['portability
'] & MDB2_PORTABILITY_FIX_CASE
575 && $db->options['field_case
'] == CASE_LOWER
577 $result = array_map(($db->options['field_case
'] == CASE_LOWER ? 'strtolower
' : 'strtoupper
'), $result);
594 $db =& $this->getDBInstance();
595 if (PEAR::isError($db)) {
599 if ($db->options['emulate_database
'] && $db->options['database_name_prefix
']) {
600 $query = 'SELECT SUBSTR(username,
';
601 $query.= (strlen($db->options['database_name_prefix
'])+1);
602 $query.= ") FROM sys.dba_users WHERE username NOT LIKE '";
603 $query.= $db->options['database_name_prefix']."%
'";
605 $query = 'SELECT username FROM sys.dba_users
';
607 return $db->queryCol($query);
621 $db =& $this->getDBInstance();
622 if (PEAR::isError($db)) {
626 $query = 'SELECT view_name FROM sys.user_views
';
627 $result = $db->queryCol($query);
628 if (PEAR::isError($result)) {
631 if ($db->options['portability
'] & MDB2_PORTABILITY_FIX_CASE
632 && $db->options['field_case
'] == CASE_LOWER
634 $result = array_map(($db->options['field_case
'] == CASE_LOWER ? 'strtolower
' : 'strtoupper
'), $result);
640 // {{{ listFunctions()
648 function listFunctions()
650 $db =& $this->getDBInstance();
651 if (PEAR::isError($db)) {
655 $query = "SELECT name FROM sys.user_source WHERE line = 1 AND type = 'FUNCTION
'";
656 $result = $db->queryCol($query);
657 if (PEAR::isError($result)) {
660 if ($db->options['portability
'] & MDB2_PORTABILITY_FIX_CASE
661 && $db->options['field_case
'] == CASE_LOWER
663 $result = array_map(($db->options['field_case
'] == CASE_LOWER ? 'strtolower
' : 'strtoupper
'), $result);
677 function listTables()
679 $db =& $this->getDBInstance();
680 if (PEAR::isError($db)) {
684 $query = 'SELECT table_name FROM sys.user_tables
';
685 $result = $db->queryCol($query);
686 if (PEAR::isError($result)) {
689 if ($db->options['portability
'] & MDB2_PORTABILITY_FIX_CASE
690 && $db->options['field_case
'] == CASE_LOWER
692 $result = array_map(($db->options['field_case
'] == CASE_LOWER ? 'strtolower
' : 'strtoupper
'), $result);
698 // {{{ listTableFields()
707 function listTableFields($table)
709 $db =& $this->getDBInstance();
710 if (PEAR::isError($db)) {
714 $table = $db->quote($table, 'text
');
715 $query = 'SELECT column_name FROM user_tab_columns
';
716 $query.= ' WHERE table_name=
'.$table.' OR table_name=
'.strtoupper($table).' ORDER BY column_id
';
717 $result = $db->queryCol($query);
718 if (PEAR::isError($result)) {
721 if ($db->options['portability
'] & MDB2_PORTABILITY_FIX_CASE
722 && $db->options['field_case
'] == CASE_LOWER
724 $result = array_map(($db->options['field_case
'] == CASE_LOWER ? 'strtolower
' : 'strtoupper
'), $result);
730 // {{{ listTableIndexes()
739 function listTableIndexes($table)
741 $db =& $this->getDBInstance();
742 if (PEAR::isError($db)) {
746 $table = $db->quote($table, 'text
');
747 $query = 'SELECT index_name name FROM user_indexes
';
748 $query.= ' WHERE (table_name=
'.$table.' OR table_name=
'.strtoupper($table);
749 $query.= ') AND generated=
' .$db->quote('N
', 'text
');
750 $indexes = $db->queryCol($query, 'text
');
751 if (PEAR::isError($indexes)) {
756 foreach ($indexes as $index) {
757 $index = $this->_fixIndexName($index);
758 if (!empty($index)) {
759 $result[$index] = true;
763 if ($db->options['portability
'] & MDB2_PORTABILITY_FIX_CASE
764 && $db->options['field_case
'] == CASE_LOWER
766 $result = array_change_key_case($result, $db->options['field_case
']);
768 return array_keys($result);
772 // {{{ listTableConstraints()
781 function listTableConstraints($table)
783 $db =& $this->getDBInstance();
784 if (PEAR::isError($db)) {
788 $table = $db->quote($table, 'text
');
789 $query = 'SELECT constraint_name name FROM user_constraints
';
790 $query.= ' WHERE table_name=
'.$table.' OR table_name=
'.strtoupper($table);
791 $constraints = $db->queryCol($query);
792 if (PEAR::isError($constraints)) {
797 foreach ($constraints as $constraint) {
798 $constraint = $this->_fixIndexName($constraint);
799 if (!empty($constraint)) {
800 $result[$constraint] = true;
804 if ($db->options['portability
'] & MDB2_PORTABILITY_FIX_CASE
805 && $db->options['field_case
'] == CASE_LOWER
807 $result = array_change_key_case($result, $db->options['field_case
']);
809 return array_keys($result);
813 // {{{ createSequence()
824 function createSequence($seq_name, $start = 1)
826 $db =& $this->getDBInstance();
827 if (PEAR::isError($db)) {
831 $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
832 $query = "CREATE SEQUENCE $sequence_name START WITH $start INCREMENT BY 1 NOCACHE";
833 $query.= ($start < 1 ? " MINVALUE $start" : '');
834 return $db->exec($query);
838 // {{{ dropSequence()
848 function dropSequence($seq_name)
850 $db =& $this->getDBInstance();
851 if (PEAR::isError($db)) {
855 $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
856 return $db->exec("DROP SEQUENCE $sequence_name");
860 // {{{ listSequences()
868 function listSequences()
870 $db =& $this->getDBInstance();
871 if (PEAR::isError($db)) {
875 $query = "SELECT sequence_name FROM sys.user_sequences";
876 $table_names = $db->queryCol($query);
877 if (PEAR::isError($table_names)) {
881 foreach ($table_names as $table_name) {
882 $result[] = $this->_fixSequenceName($table_name);
884 if ($db->options['portability
'] & MDB2_PORTABILITY_FIX_CASE) {
885 $result = array_map(($db->options['field_case
'] == CASE_LOWER ? 'strtolower
' : 'strtoupper
'), $result);