8 include_once (
"MDB2.php");
55 "text" => array(
"length",
"notnull",
"default",
"fixed"),
56 "integer" => array(
"length",
"notnull",
"default",
"unsigned"),
57 "float" => array(
"notnull",
"default"),
58 "date" => array(
"notnull",
"default"),
59 "time" => array(
"notnull",
"default"),
60 "timestamp" => array(
"notnull",
"default"),
61 "clob" => array(
"notnull",
"default"),
62 "blob" => array(
"notnull",
"default")
83 $this->db_user = $a_user;
103 $this->db_port = $a_port;
113 return $this->db_port;
123 $this->db_host = $a_host;
143 $this->db_password = $a_password;
153 return $this->db_password;
163 $this->db_name = $a_name;
179 abstract function getDSN();
208 global $ilClientIniFile;
211 if (is_object($tmpClientIniFile))
212 $clientIniFile = $tmpClientIniFile;
214 $clientIniFile = $ilClientIniFile;
216 if (is_object($clientIniFile ))
218 $this->
setDBUser($clientIniFile ->readVariable(
"db",
"user"));
219 $this->
setDBHost($clientIniFile ->readVariable(
"db",
"host"));
220 $this->
setDBPort($clientIniFile ->readVariable(
"db",
"port"));
221 $this->
setDBPassword($clientIniFile ->readVariable(
"db",
"pass"));
222 $this->
setDBName($clientIniFile ->readVariable(
"db",
"name"));
229 function connect($a_return_false_for_error =
false)
236 if ($this->
getDSN() ==
"")
271 array(
"use_transactions" =>
true));
279 $this->db->disconnect();
322 array(
"use_transactions" =>
true));
334 $this->db->setOption(
"portability", $this->db->getOption(
"portability") - $cur);
337 $this->db->setOption(
"portability", $this->db->getOption(
"portability") - $cur);
375 $a_level = $this->error_class->FATAL;
385 $stack = $e->getTraceAsString();
388 if(is_object($ilLog))
391 $a_res->getMessage().
"<br />".$a_res->getUserInfo().
"<br />".$stack, $a_level);
405 $a_level = $this->error_class->FATAL;
420 $this->db->loadModule(
'Extended');
445 if ($a_collation !=
"")
447 $sql =
"CREATE DATABASE ".$a_name.
448 " CHARACTER SET ".$a_charset.
449 " COLLATE ".$a_collation;
453 $sql =
"CREATE DATABASE ".$a_name.
454 " CHARACTER SET ".$a_charset;
457 return $this->
query($sql,
false);
468 function createTable($a_name, $a_definition_array, $a_drop_table =
false,
469 $a_ignore_erros =
false)
472 if ($a_options ==
"")
474 $a_options = array();
480 $this->
raisePearError(
"ilDB Error: createTable(".$a_name.
")<br />".
487 $this->
raisePearError(
"ilDB Error: createTable(".$a_name.
")<br />".
496 $manager = $this->db->loadModule(
'Manager');
497 $r = $manager->createTable($a_name, $a_definition_array, $a_options);
499 return $this->
handleError($r,
"createTable(".$a_name.
")");
508 function dropTable($a_name, $a_error_if_not_existing =
true)
510 if (!$a_error_if_not_existing)
513 if (!in_array($a_name, $tables))
519 $manager = $this->db->loadModule(
'Manager');
520 $r = $manager->dropTable($a_name);
522 return $this->
handleError($r,
"dropTable(".$a_name.
")");
532 if ($a_options ==
"")
534 $a_options = array();
537 $manager = $this->db->loadModule(
'Manager');
538 $r = $manager->alterTable($a_name, $a_changes,
false);
540 return $this->
handleError($r,
"alterTable(".$a_name.
")");
554 $manager = $this->db->loadModule(
'Manager');
558 $this->
raisePearError(
"ilDB Error: addTableColumn(".$a_table.
", ".$a_column.
")<br />".
563 $this->
raisePearError(
"ilDB Error: addTableColumn(".$a_table.
", ".$a_column.
")<br />".
569 $a_column => $a_attributes
573 $r = $manager->alterTable($a_table, $changes,
false);
575 return $this->
handleError($r,
"addTableColumn(".$a_table.
", ".$a_column.
")");
588 $manager = $this->db->loadModule(
'Manager');
596 $r = $manager->alterTable($a_table, $changes,
false);
598 return $this->
handleError($r,
"dropTableColumn(".$a_table.
", ".$a_column.
")");
611 $manager = $this->db->loadModule(
'Manager');
612 $reverse = $this->db->loadModule(
'Reverse');
613 $def = $reverse->getTableFieldDefinition($a_table, $a_column);
615 $this->
handleError($def,
"modifyTableColumn(".$a_table.
")");
617 if (is_file(
"./Services/Database/classes/class.ilDBAnalyzer.php"))
619 include_once(
"./Services/Database/classes/class.ilDBAnalyzer.php");
623 include_once(
"../Services/Database/classes/class.ilDBAnalyzer.php");
626 $best_alt = $analyzer->getBestDefinitionAlternative($def);
627 $def = $def[$best_alt];
628 unset($def[
"nativetype"]);
629 unset($def[
"mdb2type"]);
632 $type = ($a_attributes[
"type"] !=
"")
633 ? $a_attributes[
"type"]
635 foreach ($def as $k => $v)
637 if ($k !=
"type" && !in_array($k, $this->allowed_attributes[
$type]))
643 foreach ($a_attributes as $k => $v)
645 $check_array[$k] = $v;
649 $this->
raisePearError(
"ilDB Error: modifyTableColumn(".$a_table.
", ".$a_column.
")<br />".
654 if ($this->getDbType() ==
"oracle")
656 if ($def[
"notnull"] ==
true && $a_attributes[
"notnull"] ==
true)
658 unset($def[
"notnull"]);
659 unset($a_attributes[
"notnull"]);
663 foreach ($a_attributes as $a => $v)
668 $a_attributes[
"definition"] = $def;
672 $a_column => $a_attributes
676 $r = $manager->alterTable($a_table, $changes,
false);
678 return $this->
handleError($r,
"modifyTableColumn(".$a_table.
")");
694 $this->
raisePearError(
"ilDB Error: renameTableColumn(".$a_table.
",".$a_column.
",".$a_new_column.
")<br />".
698 $manager = $this->db->loadModule(
'Manager');
699 $reverse = $this->db->loadModule(
'Reverse');
700 $def = $reverse->getTableFieldDefinition($a_table, $a_column);
702 $this->
handleError($def,
"renameTableColumn(".$a_table.
",".$a_column.
",".$a_new_column.
")");
704 if (is_file(
"./Services/Database/classes/class.ilDBAnalyzer.php"))
706 include_once(
"./Services/Database/classes/class.ilDBAnalyzer.php");
710 include_once(
"../Services/Database/classes/class.ilDBAnalyzer.php");
714 $best_alt = $analyzer->getBestDefinitionAlternative($def);
715 $def = $def[$best_alt];
716 unset($def[
"nativetype"]);
717 unset($def[
"mdb2type"]);
719 $f[
"definition"] = $def;
720 $f[
"name"] = $a_new_column;
728 $r = $manager->alterTable($a_table, $changes,
false);
730 return $this->
handleError($r,
"renameTableColumn(".$a_table.
",".$a_column.
",".$a_new_column.
")");
744 $this->
raisePearError(
"ilDB Error: renameTable(".$a_name.
",".$a_new_name.
")<br />".
748 $manager = $this->db->loadModule(
'Manager');
749 $r = $manager->alterTable($a_name, array(
"name" => $a_new_name),
false);
751 $query =
"UPDATE abstraction_progress ".
752 "SET table_name = ".$this->db->quote($a_new_name,
'text').
" ".
753 "WHERE table_name = ".$this->db->quote($a_name,
'text');
756 return $this->
handleError($r,
"renameTable(".$a_name.
",".$a_new_name.
")");
768 $manager = $this->db->loadModule(
'Manager');
771 foreach ($a_fields as
$f)
773 $fields[
$f] = array();
775 $definition = array (
779 $r = $manager->createConstraint($a_table,
782 return $this->
handleError($r,
"addPrimaryKey(".$a_table.
")");
801 $manager = $this->db->loadModule(
'Manager');
803 $r = $manager->dropConstraint($a_table,
806 return $this->
handleError($r,
"dropPrimaryKey(".$a_table.
")");
816 function addIndex($a_table, $a_fields, $a_name =
"in", $a_fulltext =
false)
818 $manager = $this->db->loadModule(
'Manager');
823 $this->
raisePearError(
"ilDB Error: addIndex(".$a_table.
",".$a_name.
")<br />".
828 foreach ($a_fields as
$f)
830 $fields[
$f] = array();
832 $definition = array (
838 $r = $manager->createIndex($a_table, $this->
constraintName($a_table, $a_name), $definition);
848 return $this->
handleError($r,
"addIndex(".$a_table.
")");
876 $manager = $this->db->loadModule(
'Manager');
880 $r = $manager->dropIndex($a_table, $this->
constraintName($a_table, $a_name));
884 $this->dropFulltextIndex($a_table, $a_name);
887 return $this->
handleError($r,
"dropIndex(".$a_table.
")");
899 $manager = $this->db->loadModule(
'Manager');
904 $this->
raisePearError(
"ilDB Error: addUniqueConstraint(".$a_table.
",".$a_name.
")<br />".
909 foreach ($a_fields as
$f)
911 $fields[
$f] = array();
913 $definition = array (
918 $r = $manager->createConstraint($a_table, $this->
constraintName($a_table, $a_name), $definition);
920 return $this->
handleError($r,
"addUniqueConstraint(".$a_table.
")");
928 $manager = $this->db->loadModule(
'Manager');
930 $r = $manager->createSequence($a_table_name, $a_start);
932 return $this->
handleError($r,
"createSequence(".$a_table_name.
")");
941 $manager = $this->db->loadModule(
'Manager');
943 $r = $manager->dropSequence($a_table_name);
945 return $this->
handleError($r,
"dropSequence(".$a_table_name.
")");
955 if (!preg_match (
"/^[a-z]+[_a-z0-9]*$/", $a_name))
957 $this->error_str =
"Table name must only contain _a-z0-9 and must start with a-z.";
963 $this->error_str =
"Invalid table name '".$a_name.
"' (Reserved Word).";
967 if (strtolower(substr($a_name, 0, 4)) ==
"sys_")
969 $this->error_str =
"Invalid table name '".$a_name.
"'. Name must not start with 'sys_'.";
973 if (strlen($a_name) > 22)
975 $this->error_str =
"Invalid table name '".$a_name.
"'. Maximum table identifer lenght is 22 bytes.";
989 foreach ($a_cols as $col => $def)
1026 if (!in_array($a_def[
"type"], array(
"text",
"integer",
"float",
"date",
"time",
"timestamp",
"clob",
"blob")))
1028 switch ($a_def[
"type"])
1031 $this->error_str =
"Invalid column type '".$a_def[
"type"].
"'. Use integer(1) instead.";
1035 $this->error_str =
"Invalid column type '".$a_def[
"type"].
"'. Use float or integer instead.";
1039 $this->error_str =
"Invalid column type '".$a_def[
"type"].
"'. Allowed types are: ".
1040 "text, integer, float, date, time, timestamp, clob and blob.";
1047 foreach ($a_def as $k => $v)
1051 $this->error_str =
"Attribute '".$k.
"' is not allowed for column type '".$a_def[
"type"].
"'.";
1057 switch ($a_def[
"type"])
1060 if ($a_def[
"length"] < 1 || $a_def[
"length"] > 4000)
1062 if (!$a_modify_mode || isset($a_def[
"length"]))
1064 $this->error_str =
"Invalid length '".$a_def[
"length"].
"' for type text.".
1065 " Length must be >=1 and <= 4000.";
1072 if (!in_array($a_def[
"length"], array(1, 2, 3, 4, 8)))
1074 if (!$a_modify_mode || isset($a_def[
"length"]))
1076 $this->error_str =
"Invalid length '".$a_def[
"length"].
"' for type integer.".
1077 " Length must be 1, 2, 3, 4 or 8 (bytes).";
1081 if ($a_def[
"unsigned"])
1083 $this->error_str =
"Unsigned attribut must not be true for type integer.";
1099 if (!preg_match (
"/^[a-z]+[_a-z0-9]*$/", $a_name))
1101 $this->error_str =
"Invalid column name '".$a_name.
"'. Column name must only contain _a-z0-9 and must start with a-z.";
1107 $this->error_str =
"Invalid column name '".$a_name.
"' (Reserved Word).";
1111 if (strtolower(substr($a_name, 0, 4)) ==
"sys_")
1113 $this->error_str =
"Invalid column name '".$a_name.
"'. Name must not start with 'sys_'.";
1117 if (strlen($a_name) > 30)
1119 $this->error_str =
"Invalid column name '".$a_name.
"'. Maximum column identifer lenght is 30 bytes.";
1133 if (!preg_match (
"/^[a-z]+[_a-z0-9]*$/", $a_name))
1135 $this->error_str =
"Invalid column name '".$a_name.
"'. Column name must only contain _a-z0-9 and must start with a-z.";
1141 $this->error_str =
"Invalid column name '".$a_name.
"' (Reserved Word).";
1145 if (strlen($a_name) > 3)
1147 $this->error_str =
"Invalid index name '".$a_name.
"'. Maximum index identifer lenght is 3 bytes.";
1166 return $a_constraint;
1175 include_once(
"./Services/Database/classes/class.ilDBMySQL.php");
1177 if (in_array(strtoupper($a_word), $mysql_reserved_words))
1181 include_once(
"./Services/Database/classes/class.ilDBOracle.php");
1183 if (in_array(strtoupper($a_word), $oracle_reserved_words))
1187 include_once(
"./Services/Database/classes/class.ilDBPostgreSQL.php");
1189 if (in_array(strtoupper($a_word), $postgres_reserved_words))
1210 function query($sql, $a_handle_error =
true)
1212 $r = $this->db->query($sql);
1214 if ($a_handle_error)
1229 function queryF($a_query, $a_types, $a_values)
1231 if (!is_array($a_types) || !is_array($a_values) ||
1232 count($a_types) != count($a_values))
1234 $this->
raisePearError(
"ilDB::queryF: types and values must be arrays of same size.");
1236 $quoted_values = array();
1237 foreach($a_types as $k =>
$t)
1239 $quoted_values[] = $this->
quote($a_values[$k],
$t);
1241 $query = vsprintf($a_query, $quoted_values);
1255 if (!is_array($a_types) || !is_array($a_values) ||
1256 count($a_types) != count($a_values))
1258 $this->
raisePearError(
"ilDB::manipulateF: types and values must be arrays of same size.");
1260 $quoted_values = array();
1261 foreach($a_types as $k =>
$t)
1263 $quoted_values[] = $this->
quote($a_values[$k],
$t);
1265 $query = vsprintf($a_query, $quoted_values);
1275 $pos1 = strpos(strtolower($sql),
"from ");
1279 $tablef = substr($sql, $pos1+5);
1280 $pos2 = strpos(strtolower($tablef),
" ");
1283 $table =substr($tablef, 0, $pos2);
1290 if (trim($table) !=
"")
1292 if (!is_array($this->ttt) || !in_array($table, $this->ttt))
1295 $this->ttt[] = $table;
1300 echo
"<br><b>".$sql.
"</b>";
1309 $this->db->setLimit($a_limit, $a_offset);
1320 $r = $this->db->nextId($a_table_name,
false);
1322 return $this->
handleError($r,
"nextId(".$a_table_name.
")");
1337 $r = $this->db->exec($sql);
1339 return $this->
handleError($r,
"manipulate(".$sql.
")");
1350 function prepare($a_query, $a_types = null, $a_result_types = null)
1352 $res = $this->db->prepare($a_query, $a_types, $a_result_types);
1382 $res = $a_stmt->execute($a_data);
1398 $res = $this->db->extended->executeMultiple($a_stmt,$a_data);
1400 return $this->
handleError(
$res,
"executeMultiple(".$a_stmt->query.
")");
1412 $field_values = array();
1413 $placeholders = array();
1418 foreach ($a_columns as $k => $col)
1421 $placeholders[] =
"%s";
1422 $placeholders2[] =
":$k";
1424 $values[] = $col[1];
1425 $field_values[$k] = $col[1];
1426 if ($col[0] ==
"blob" || $col[0] ==
"clob")
1434 $st = $this->db->prepare(
"INSERT INTO ".$a_table.
" (".implode($fields,
",").
") VALUES (".
1436 $r = $st->execute($field_values);
1440 $this->
handleError($r,
"insert / prepare/execute(".$a_table.
")");
1445 $q =
"INSERT INTO ".$a_table.
" (".implode($fields,
",").
") VALUES (".
1446 implode($placeholders,
",").
")";
1460 function update($a_table, $a_columns, $a_where)
1463 $field_values = array();
1464 $placeholders = array();
1469 foreach ($a_columns as $k => $col)
1472 $placeholders[] =
"%s";
1473 $placeholders2[] =
":$k";
1475 $values[] = $col[1];
1476 $field_values[$k] = $col[1];
1477 if ($col[0] ==
"blob" || $col[0] ==
"clob")
1486 $q =
"UPDATE ".$a_table.
" SET ";
1488 foreach ($fields as $k => $field)
1490 $q.= $lim.$field.
" = ".$placeholders2[$k];
1495 foreach ($a_where as $k => $col)
1497 $q.= $lim.$k.
" = ".$this->
quote($col[1], $col[0]);
1501 $r = $st->execute($field_values);
1504 $this->
handleError($r,
"update / prepare/execute(".$a_table.
")");
1509 foreach ($a_where as $k => $col)
1512 $values[] = $col[1];
1513 $field_values[$k] = $col;
1515 $q =
"UPDATE ".$a_table.
" SET ";
1517 foreach ($fields as $k => $field)
1519 $q.= $lim.$field.
" = ".$placeholders[$k];
1524 foreach ($a_where as $k => $col)
1526 $q.= $lim.$k.
" = %s";
1542 function replace($a_table, $a_pk_columns, $a_other_columns)
1545 $a_columns = array_merge($a_pk_columns, $a_other_columns);
1547 $field_values = array();
1548 $placeholders = array();
1553 foreach ($a_columns as $k => $col)
1556 $placeholders[] =
"%s";
1557 $placeholders2[] =
":$k";
1559 $values[] = $col[1];
1560 $field_values[$k] = $col[1];
1561 if ($col[0] ==
"blob" || $col[0] ==
"clob")
1569 $st = $this->db->prepare(
"REPLACE INTO ".$a_table.
" (".implode($fields,
",").
") VALUES (".
1571 $r = $st->execute($field_values);
1573 $this->
handleError($r,
"insert / prepare/execute(".$a_table.
")");
1578 $q =
"REPLACE INTO ".$a_table.
" (".implode($fields,
",").
") VALUES (".
1579 implode($placeholders,
",").
")";
1600 return $a_st->free();
1620 return $a_set->numRows();
1638 function in($a_field, $a_values, $negate =
false, $a_type =
"")
1640 if (count($a_values) == 0)
1646 $str = $a_field.(($negate) ?
" NOT" :
"").
" IN (?".str_repeat(
",?", count($a_values) - 1).
")";
1650 $str = $a_field.(($negate) ?
" NOT" :
"").
" IN (";
1652 foreach ($a_values as $v)
1654 $str.= $sep.$this->quote($v, $a_type);
1668 if (!is_array($a_arr))
1674 $type_arr = array_fill(0, $a_cnt, $a_type);
1678 $type_arr = array();
1680 return array_merge($a_arr, $type_arr);
1702 public function concat($a_values,$a_allow_null =
true)
1704 if(!count($a_values))
1709 $concat =
' CONCAT(';
1711 foreach($a_values as $field_info)
1713 $val = $field_info[0];
1722 $concat .=
'COALESCE(';
1746 public function locate($a_needle,$a_string,$a_start_pos = 1)
1748 $locate =
' LOCATE( ';
1749 $locate .= $a_needle;
1751 $locate .= $a_string;
1753 $locate .= $a_start_pos;
1764 function like($a_col, $a_type, $a_value =
"?", $case_insensitive =
true)
1766 if (!in_array($a_type, array(
"text",
"clob",
"blob")))
1768 $this->
raisePearError(
"Like: Invalid column type '".$a_type.
"'.", $this->error_class->FATAL);
1770 if ($a_value ==
"?")
1772 if ($case_insensitive)
1774 return "UPPER(".$a_col.
") LIKE(UPPER(?))";
1778 return $a_col .
" LIKE(?)";
1783 if ($case_insensitive)
1786 return " UPPER(".$a_col.
") LIKE(UPPER(".$this->
quote($a_value,
'text').
"))";
1791 return " ".$a_col.
" LIKE(".$this->
quote($a_value,
'text').
")";
1800 function equals($a_col, $a_value, $a_type, $a_empty_or_null =
false)
1802 if (!$a_empty_or_null || $a_value !=
"")
1804 return $a_col.
" = ".$this->
quote($a_value, $a_type);
1808 return "(".$a_col.
" = '' OR $a_col IS NULL)";
1815 function equalsNot($a_col, $a_value, $a_type, $a_empty_or_null =
false)
1817 if (!$a_empty_or_null)
1819 return $a_col.
" <> ".$this->
quote($a_value, $a_type);
1823 return "(".$a_col.
" <> ".$this->
quote($a_value, $a_type).
" OR ".
1828 return "(".$a_col.
" <> '' AND $a_col IS NOT NULL)";
1840 return "FROM_UNIXTIME(".$a_expr.
")";
1848 return "UNIX_TIMESTAMP()";
1874 if (is_array($tables))
1876 if (in_array($a_table, $tables))
1894 $column_visibility =
false;
1895 $manager = $this->db->loadModule(
'Manager');
1896 $r = $manager->listTableFields($a_table);
1900 foreach($r as $field)
1902 if ($field == $a_column_name)
1904 $column_visibility =
true;
1909 return $column_visibility;
1919 $manager = $this->db->loadModule(
'Manager');
1920 $r = $manager->listTables();
1938 function quote($a_query, $a_type = null)
1940 if ($a_query ==
"" && is_null($a_type))
1945 if ($a_type ==
"blob" || $a_type ==
"clob")
1947 $this->
raisePearError(
"ilDB::quote: Quoting not allowed on type '".$a_type.
"'. Please use ilDB->insert and ilDB->update to write clobs.", $this->error_class->FATAL);
1950 return $this->db->quote($a_query, $a_type);
1962 return $this->db->quoteIdentifier($a_identifier);
1976 if (!$this->db->supports(
'transactions'))
1978 $this->
raisePearError(
"ilDB::beginTransaction: Transactions are not supported.", $this->error_class->FATAL);
1980 $res = $this->db->beginTransaction();
1990 $res = $this->db->commit();
2000 $res = $this->db->rollback();
2010 abstract public function lockTables($a_tables);
2035 $res = $this->db->autoExecute($a_tablename,$a_fields,$a_mode,$a_where);
2051 $res = $this->db->lastInsertId();
2071 $set = $this->db->query($sql);
2094 $set = $this->
query($sql);
2095 $r = $set->fetchRow($mode);