ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
class.ilDBPdo.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once("./Services/Database/classes/PDO/class.ilPDOStatement.php");
5 require_once("./Services/Database/classes/QueryUtils/class.ilMySQLQueryUtils.php");
6 require_once('./Services/Database/classes/PDO/Manager/class.ilDBPdoManager.php');
7 require_once('./Services/Database/classes/PDO/Reverse/class.ilDBPdoReverse.php');
8 require_once('./Services/Database/interfaces/interface.ilDBInterface.php');
9 require_once('./Services/Database/classes/class.ilDBConstants.php');
10 require_once('./Services/Database/interfaces/interface.ilDBLegacyInterface.php');
11 
18 abstract class ilDBPdo implements ilDBInterface, ilDBPdoInterface {
19 
20  const FEATURE_TRANSACTIONS = 'transactions';
21  const FEATURE_FULLTEXT = 'fulltext';
22  const FEATURE_SLAVE = 'slave';
26  protected $host = '';
30  protected $dbname = '';
34  protected $charset = 'utf8';
38  protected $username = '';
42  protected $password = '';
46  protected $port = 3306;
50  protected $pdo;
54  protected $manager;
58  protected $reverse;
62  protected $limit = null;
66  protected $offset = null;
70  protected $storage_engine = 'MyISAM';
74  protected $dsn = '';
78  protected $attributes = array(
79  // PDO::ATTR_EMULATE_PREPARES => true,
80  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
81  );
85  protected $db_type = '';
89  protected $error_code = 0;
93  protected $field_definition;
94 
95 
101  public function connect($return_false_for_error = false) {
102  $this->generateDSN();
103  try {
104  $options = $this->getAttributes();
105  $this->pdo = new PDO($this->getDSN(), $this->getUsername(), $this->getPassword(), $options);
106  $this->initHelpers();
107  $this->initSQLMode();
108  } catch (Exception $e) {
109  $this->error_code = $e->getCode();
110  if ($return_false_for_error) {
111  return false;
112  }
113  throw $e;
114  }
115 
116  return ($this->pdo->errorCode() == PDO::ERR_NONE);
117  }
118 
119 
120  abstract public function initHelpers();
121 
122 
123  protected function initSQLMode() {
124  }
125 
126 
130  protected function getAttributes() {
132  foreach ($this->getAdditionalAttributes() as $k => $v) {
133  $options[$k] = $v;
134  }
135 
136  return $options;
137  }
138 
139 
143  protected function getAdditionalAttributes() {
144  return array();
145  }
146 
147 
151  public function getFieldDefinition() {
153  }
154 
155 
160  $this->field_definition = $field_definition;
161  }
162 
163 
171  public function createDatabase($a_name, $a_charset = "utf8", $a_collation = "") {
172  $this->setDbname(null);
173  $this->generateDSN();
174  $this->connect(true);
175  try {
176  return $this->query($this->manager->getQueryUtils()->createDatabase($a_name, $a_charset, $a_collation));
177  } catch (PDOException $e) {
178  return false;
179  }
180  }
181 
182 
186  public function getLastErrorCode() {
187  if ($this->pdo instanceof PDO) {
188  return $this->pdo->errorCode();
189  }
190 
191  return $this->error_code;
192  }
193 
194 
198  public function initFromIniFile($tmpClientIniFile = null) {
199  global $ilClientIniFile;
200  if ($tmpClientIniFile instanceof ilIniFile) {
201  $clientIniFile = $tmpClientIniFile;
202  } else {
203  $clientIniFile = $ilClientIniFile;
204  }
205 
206  $this->setUsername($clientIniFile->readVariable("db", "user"));
207  $this->setHost($clientIniFile->readVariable("db", "host"));
208  $this->setPort((int)$clientIniFile->readVariable("db", "port"));
209  $this->setPassword($clientIniFile->readVariable("db", "pass"));
210  $this->setDbname($clientIniFile->readVariable("db", "name"));
211  $this->setDBType($clientIniFile->readVariable("db", "type"));
212 
213  $this->generateDSN();
214  }
215 
216 
217  public function generateDSN() {
218  $port = $this->getPort() ? ";port=" . $this->getPort() : "";
219  $dbname = $this->getDbname() ? ';dbname=' . $this->getDbname() : '';
220  $host = $this->getHost();
221  $charset = ';charset=' . $this->getCharset();
222  $this->dsn = 'mysql:host=' . $host . $port . $dbname . $charset;
223  }
224 
225 
230  public function quoteIdentifier($identifier, $check_option = false) {
231  return '`' . $identifier . '`';
232  }
233 
234 
240  public function nextId($table_name) {
241  $sequence_table_name = $table_name . '_seq';
242 
243  $last_insert_id = $this->pdo->lastInsertId($table_name);
244  if ($last_insert_id) {
245  // return $last_insert_id;
246  }
247 
248  if ($this->tableExists($sequence_table_name)) {
249  $stmt = $this->pdo->prepare("SELECT sequence FROM $sequence_table_name");
250  $stmt->execute();
251  $rows = $stmt->fetch(PDO::FETCH_ASSOC);
252  $stmt->closeCursor();
253  $next_id = $rows['sequence'] + 1;
254  $stmt = $this->pdo->prepare("DELETE FROM $sequence_table_name");
255  $stmt->execute(array("next_id" => $next_id));
256  $stmt = $this->pdo->prepare("INSERT INTO $sequence_table_name (sequence) VALUES (:next_id)");
257  $stmt->execute(array("next_id" => $next_id));
258 
259  return $next_id;
260  }
261 
262  return 1;
263  }
264 
265 
274  public function createTable($table_name, $fields, $drop_table = false, $ignore_erros = false) {
275  // check table name
276  if (!$this->checkTableName($table_name) && !$ignore_erros) {
277  throw new ilDatabaseException("ilDB Error: createTable(" . $table_name . ")");
278  }
279 
280  // check definition array
281  if (!$this->checkTableColumns($fields) && !$ignore_erros) {
282  throw new ilDatabaseException("ilDB Error: createTable(" . $table_name . ")");
283  }
284 
285  if ($drop_table) {
286  $this->dropTable($table_name, false);
287  }
288 
289  return $this->manager->createTable($table_name, $fields, array());
290  }
291 
292 
297  protected function checkTableColumns($a_cols) {
298  foreach ($a_cols as $col => $def) {
299  if (!$this->checkColumn($col, $def)) {
300  return false;
301  }
302  }
303 
304  return true;
305  }
306 
307 
313  protected function checkColumn($a_col, $a_def) {
314  if (!$this->checkColumnName($a_col)) {
315  return false;
316  }
317 
318  if (!$this->checkColumnDefinition($a_def)) {
319  return false;
320  }
321 
322  return true;
323  }
324 
325 
331  protected function checkColumnDefinition($a_def, $a_modify_mode = false) {
332  return $this->field_definition->checkColumnDefinition($a_def);
333  }
334 
335 
340  public function checkColumnName($a_name) {
341  return $this->field_definition->checkColumnName($a_name);
342  }
343 
344 
351  public function addPrimaryKey($table_name, $primary_keys) {
352  assert(is_array($primary_keys));
353 
354  $fields = array();
355  foreach ($primary_keys as $f) {
356  $fields[$f] = array();
357  }
358  $definition = array(
359  'primary' => true,
360  'fields' => $fields,
361  );
362  $this->manager->createConstraint($table_name, $this->constraintName($table_name, $this->getPrimaryKeyIdentifier()), $definition);
363 
364  return true;
365  }
366 
367 
374  public function dropIndexByFields($table_name, $fields) {
375  foreach ($this->manager->listTableIndexes($table_name) as $idx_name) {
376  $def = $this->reverse->getTableIndexDefinition($table_name, $idx_name);
377  $idx_fields = array_keys((array)$def['fields']);
378 
379  if ($idx_fields === $fields) {
380  return $this->dropIndex($table_name, $idx_name);
381  }
382  }
383 
384  return false;
385  }
386 
387 
391  public function getPrimaryKeyIdentifier() {
392  return "PRIMARY";
393  }
394 
395 
400  public function createSequence($table_name, $start = 1) {
401  $this->manager->createSequence($table_name, $start);
402  }
403 
404 
410  public function tableExists($table_name) {
411  $result = $this->pdo->prepare("SHOW TABLES LIKE :table_name");
412  $result->execute(array('table_name' => $table_name));
413  $return = $result->rowCount();
414  $result->closeCursor();
415 
416  return $return > 0;
417  }
418 
419 
426  public function tableColumnExists($table_name, $column_name) {
427  $fields = $this->loadModule(ilDBConstants::MODULE_MANAGER)->listTableFields($table_name);
428 
429  $in_array = in_array($column_name, $fields);
430 
431  return $in_array;
432  }
433 
434 
442  public function addTableColumn($table_name, $column_name, $attributes) {
443  if (!$this->checkColumnName($column_name)) {
444  throw new ilDatabaseException("ilDB Error: addTableColumn(" . $table_name . ", " . $column_name . ")");
445  }
446  if (!$this->checkColumnDefinition($attributes)) {
447  throw new ilDatabaseException("ilDB Error: addTableColumn(" . $table_name . ", " . $column_name . ")");
448  }
449 
450  $changes = array(
451  "add" => array(
452  $column_name => $attributes,
453  ),
454  );
455 
456  return $this->manager->alterTable($table_name, $changes, false);
457  }
458 
459 
466  public function dropTable($table_name, $error_if_not_existing = true) {
467  $ilDBPdoManager = $this->loadModule(ilDBConstants::MODULE_MANAGER);
468  $tables = $ilDBPdoManager->listTables();
469  $table_exists = in_array($table_name, $tables);
470  if (!$table_exists && $error_if_not_existing) {
471  throw new ilDatabaseException("Table {$table_name} does not exist");
472  }
473 
474  // drop sequence
475  $sequences = $ilDBPdoManager->listSequences();
476  if (in_array($table_name, $sequences)) {
477  $ilDBPdoManager->dropSequence($table_name);
478  }
479 
480  // drop table
481  if ($table_exists) {
482  $ilDBPdoManager->dropTable($table_name);
483  }
484 
485  return true;
486  }
487 
488 
495  public function query($query) {
496  global $ilBench;
497 
498  $query = $this->appendLimit($query);
499 
500  try {
501  if ($ilBench instanceof ilBenchmark) {
502  $ilBench->startDbBench($query);
503  }
504  $res = $this->pdo->query($query);
505  if ($ilBench instanceof ilBenchmark) {
506  $ilBench->stopDbBench();
507  }
508  } catch (PDOException $e) {
509  throw new ilDatabaseException($e->getMessage() . ' QUERY: ' . $query);
510  }
511 
512  $err = $this->pdo->errorCode();
513  if ($err != PDO::ERR_NONE) {
514  $info = $this->pdo->errorInfo();
515  $info_message = $info[2];
516  throw new ilDatabaseException($info_message . ' QUERY: ' . $query);
517  }
518 
519  return new ilPDOStatement($res);
520  }
521 
522 
528  public function fetchAll($query_result, $fetch_mode = ilDBConstants::FETCHMODE_ASSOC) {
532  $return = array();
533  while ($data = $query_result->fetch($fetch_mode)) {
534  $return[] = $data;
535  }
536 
537  return $return;
538  }
539 
540 
544  public function dropSequence($table_name) {
545  $this->manager->dropSequence($table_name);
546  }
547 
548 
555  public function dropTableColumn($table_name, $column_name) {
556  $changes = array(
557  "remove" => array(
558  $column_name => array(),
559  ),
560  );
561 
562  return $this->manager->alterTable($table_name, $changes, false);
563  }
564 
565 
573  public function renameTableColumn($table_name, $column_old_name, $column_new_name) {
574  // check table name
575  if (!$this->checkColumnName($column_new_name)) {
576  throw new ilDatabaseException("ilDB Error: renameTableColumn(" . $table_name . "," . $column_old_name . "," . $column_new_name . ")");
577  }
578 
579  $def = $this->reverse->getTableFieldDefinition($table_name, $column_old_name);
580 
581  $analyzer = new ilDBAnalyzer($this);
582  $best_alt = $analyzer->getBestDefinitionAlternative($def);
583  $def = $def[$best_alt];
584  unset($def["nativetype"]);
585  unset($def["mdb2type"]);
586 
587  $f["definition"] = $def;
588  $f["name"] = $column_new_name;
589 
590  $changes = array(
591  "rename" => array(
592  $column_old_name => $f,
593  ),
594  );
595 
596  return $this->manager->alterTable($table_name, $changes, false);
597  }
598 
599 
605  public function insert($table_name, $values) {
606  $real = array();
607  $fields = array();
608  foreach ($values as $key => $val) {
609  $real[] = $this->quote($val[1], $val[0]);
610  $fields[] = $this->quoteIdentifier($key);
611  }
612  $values = implode(",", $real);
613  $fields = implode(",", $fields);
614  $query = "INSERT INTO " . $table_name . " (" . $fields . ") VALUES (" . $values . ")";
615 
617 
618  return $this->pdo->exec($query);
619  }
620 
621 
627  public function fetchObject($query_result) {
628  $res = $query_result->fetchObject();
629  if ($res == null) {
630  $query_result->closeCursor();
631 
632  return null;
633  }
634 
635  return $res;
636  }
637 
638 
645  public function update($table_name, $columns, $where) {
646  $fields = array();
647  $field_values = array();
648  $placeholders = array();
649  $placeholders_full = array();
650  $types = array();
651  $values = array();
652  $lobs = false;
653  $lob = array();
654  foreach ($columns as $k => $col) {
655  $field_value = $col[1];
656  $fields[] = $k;
657  $placeholders[] = "%s";
658  $placeholders_full[] = ":$k";
659  $types[] = $col[0];
660 
661  if ($col[0] == "blob" || $col[0] == "clob" || $col[0] == 'text') {
662  $field_value = $this->sanitizeMB4StringIfNotSupported($field_value);
663  }
664 
665  // integer auto-typecast (this casts bool values to integer)
666  if ($col[0] == 'integer' && !is_null($field_value)) {
667  $field_value = (int)$field_value;
668  }
669 
670  $values[] = $field_value;
671  $field_values[$k] = $field_value;
672  if ($col[0] == "blob" || $col[0] == "clob") {
673  $lobs = true;
674  $lob[$k] = $k;
675  }
676  }
677 
678  if ($lobs) {
679  $q = "UPDATE " . $table_name . " SET ";
680  $lim = "";
681  foreach ($fields as $k => $field) {
682  $q .= $lim . $field . " = " . $placeholders_full[$k];
683  $lim = ", ";
684  }
685  $q .= " WHERE ";
686  $lim = "";
687  foreach ($where as $k => $col) {
688  $q .= $lim . $k . " = " . $this->quote($col[1], $col[0]);
689  $lim = " AND ";
690  }
691 
692  $r = $this->prepareManip($q, $types);
693  $this->execute($r, $field_values);
694  $this->free($r);
695  } else {
696  foreach ($where as $k => $col) {
697  $types[] = $col[0];
698  $values[] = $col[1];
699  $field_values[$k] = $col;
700  }
701  $q = "UPDATE " . $table_name . " SET ";
702  $lim = "";
703  foreach ($fields as $k => $field) {
704  $q .= $lim . $this->quoteIdentifier($field) . " = " . $placeholders[$k];
705  $lim = ", ";
706  }
707  $q .= " WHERE ";
708  $lim = "";
709  foreach ($where as $k => $col) {
710  $q .= $lim . $k . " = %s";
711  $lim = " AND ";
712  }
713 
714  $r = $this->manipulateF($q, $types, $values);
715  }
716 
717  return $r;
718  }
719 
720 
721 
727  public function manipulate($query) {
728  global $DIC;
729  $ilBench = $DIC['ilBench'];
730  try {
732  if ($ilBench instanceof ilBenchmark) {
733  $ilBench->startDbBench($query);
734  }
735  $r = $this->pdo->exec($query);
736  if ($ilBench instanceof ilBenchmark) {
737  $ilBench->stopDbBench();
738  }
739  } catch (PDOException $e) {
740  throw new ilDatabaseException($e->getMessage() . ' QUERY: ' . $query);
741  }
742 
743  return $r;
744  }
745 
746 
752  public function fetchAssoc($query_result) {
753  $res = $query_result->fetch(PDO::FETCH_ASSOC);
754  if ($res == null) {
755  $query_result->closeCursor();
756 
757  return null;
758  }
759 
760  return $res;
761  }
762 
763 
769  public function numRows($query_result) {
770  return $query_result->rowCount();
771  }
772 
773 
780  public function quote($value, $type = null) {
781  if ($value === null) {
782  return 'NULL';
783  }
784 
785  $pdo_type = PDO::PARAM_STR;
786  switch ($type) {
790  if ($value === '') {
791  return 'NULL';
792  }
793  break;
795  $value = (int)$value;
796 
797  return $value;
798  break;
800  $pdo_type = PDO::PARAM_INT;
801  break;
803  default:
804  $pdo_type = PDO::PARAM_STR;
805  break;
806  }
807 
808  return $this->pdo->quote($value, $pdo_type);
809  }
810 
811 
818  public function indexExistsByFields($table_name, $fields) {
819  foreach ($this->manager->listTableIndexes($table_name) as $idx_name) {
820  $def = $this->reverse->getTableIndexDefinition($table_name, $idx_name);
821  $idx_fields = array_keys((array)$def['fields']);
822 
823  if ($idx_fields === $fields) {
824  return true;
825  }
826  }
827 
828  return false;
829  }
830 
831 
838  public function addIndex($table_name, $fields, $index_name = '', $fulltext = false) {
839  assert(is_array($fields));
840  $this->field_definition->checkIndexName($index_name);
841 
842  $definition_fields = array();
843  foreach ($fields as $f) {
844  $definition_fields[$f] = array();
845  }
846  $definition = array(
847  'fields' => $definition_fields,
848  );
849 
850  if (!$fulltext) {
851  $this->manager->createIndex($table_name, $this->constraintName($table_name, $index_name), $definition);
852  } else {
853  if ($this->supportsFulltext()) {
854  $this->addFulltextIndex($table_name, $fields, $index_name); // TODO
855  }
856  }
857 
858  return true;
859  }
860 
861 
869  public function addFulltextIndex($a_table, $a_fields, $a_name = "in") {
870  $i_name = $this->constraintName($a_table, $a_name) . "_idx";
871  $f_str = implode($a_fields, ",");
872  $q = "ALTER TABLE $a_table ADD FULLTEXT $i_name ($f_str)";
873  $this->query($q);
874  }
875 
876 
880  public function dropFulltextIndex($a_table, $a_name) {
881  $i_name = $this->constraintName($a_table, $a_name) . "_idx";
882  $this->query("ALTER TABLE $a_table DROP FULLTEXT $i_name");
883  }
884 
885 
889  public function isFulltextIndex($a_table, $a_name) {
890  $set = $this->query("SHOW INDEX FROM " . $a_table);
891  while ($rec = $this->fetchAssoc($set)) {
892  if ($rec["Key_name"] == $a_name && $rec["Index_type"] == "FULLTEXT") {
893  return true;
894  }
895  }
896 
897  return false;
898  }
899 
900 
905  public function getIndexName($index_name_base) {
906  return sprintf(ilDBPdoFieldDefinition::INDEX_FORMAT, preg_replace('/[^a-z0-9_\$]/i', '_', $index_name_base));
907  }
908 
909 
914  public function getSequenceName($table_name) {
915  return sprintf(ilDBPdoFieldDefinition::SEQUENCE_FORMAT, preg_replace('/[^a-z0-9_\$.]/i', '_', $table_name));
916  }
917 
918 
924  public function constraintName($a_table, $a_constraint) {
925  return $a_constraint;
926  }
927 
928 
932  public function getDSN() {
933  return $this->dsn;
934  }
935 
936 
940  public function getDBType() {
941  return $this->db_type;
942  }
943 
944 
949  public function setDBType($type) {
950  $this->db_type = $type;
951  }
952 
953 
958  public static function getReservedWords() {
959  global $ilDB;
960 
964  return $ilDB->getFieldDefinition()->getReservedMysql();
965  }
966 
967 
972  public function lockTables($tables) {
973  assert(is_array($tables));
974 
975  $lock = $this->manager->getQueryUtils()->lock($tables);
976  global $ilLog;
977  if ($ilLog instanceof ilLog) {
978  $ilLog->write('ilDB::lockTables(): ' . $lock);
979  }
980 
981  $this->pdo->exec($lock);
982  }
983 
984 
989  public function unlockTables() {
990  $this->pdo->exec($this->manager->getQueryUtils()->unlock());
991  }
992 
993 
1001  public function in($field, $values, $negate = false, $type = "") {
1002  return $this->manager->getQueryUtils()->in($field, $values, $negate, $type);
1003  }
1004 
1005 
1013  public function queryF($query, $types, $values) {
1014  if (!is_array($types) || !is_array($values) || count($types) != count($values)) {
1015  throw new ilDatabaseException("ilDB::queryF: Types and values must be arrays of same size. ($query)");
1016  }
1017  $quoted_values = array();
1018  foreach ($types as $k => $t) {
1019  $quoted_values[] = $this->quote($values[$k], $t);
1020  }
1021  $query = vsprintf($query, $quoted_values);
1022 
1023  return $this->query($query);
1024  }
1025 
1026 
1034  public function manipulateF($query, $types, $values) {
1035  if (!is_array($types) || !is_array($values) || count($types) != count($values)) {
1036  throw new ilDatabaseException("ilDB::manipulateF: types and values must be arrays of same size. ($query)");
1037  }
1038  $quoted_values = array();
1039  foreach ($types as $k => $t) {
1040  $quoted_values[] = $this->quote($values[$k], $t);
1041  }
1042  $query = vsprintf($query, $quoted_values);
1043 
1044  return $this->manipulate($query);
1045  }
1046 
1047 
1054  public function useSlave($bool) {
1055  return false;
1056  }
1057 
1058 
1065  public function setLimit($limit, $offset = 0) {
1066  $this->limit = $limit;
1067  $this->offset = $offset;
1068  }
1069 
1070 
1079  public function like($column, $type, $value = "?", $case_insensitive = true) {
1080  return $this->manager->getQueryUtils()->like($column, $type, $value, $case_insensitive);
1081  }
1082 
1083 
1087  public function now() {
1088  return $this->manager->getQueryUtils()->now();
1089  }
1090 
1091 
1100  public function replace($table, $primaryKeys, $otherColumns) {
1101  $a_columns = array_merge($primaryKeys, $otherColumns);
1102  $fields = array();
1103  $field_values = array();
1104  $placeholders = array();
1105  $types = array();
1106  $values = array();
1107 
1108  foreach ($a_columns as $k => $col) {
1109  $fields[] = $k;
1110  $placeholders[] = "%s";
1111  $placeholders2[] = ":$k";
1112  $types[] = $col[0];
1113 
1114  // integer auto-typecast (this casts bool values to integer)
1115  if ($col[0] == 'integer' && !is_null($col[1])) {
1116  $col[1] = (int)$col[1];
1117  }
1118 
1119  $values[] = $col[1];
1120  $field_values[$k] = $col[1];
1121  }
1122 
1123  $q = "REPLACE INTO " . $table . " (" . implode($fields, ",") . ") VALUES (" . implode($placeholders, ",") . ")";
1124 
1125  $r = $this->manipulateF($q, $types, $values);
1126 
1127  return $r;
1128  }
1129 
1130 
1138  public function equals($columns, $value, $type, $emptyOrNull = false) {
1139  if (!$emptyOrNull || $value != "") {
1140  return $columns . " = " . $this->quote($value, $type);
1141  } else {
1142  return "(" . $columns . " = '' OR $columns IS NULL)";
1143  }
1144  }
1145 
1146 
1150  public function getHost() {
1151  return $this->host;
1152  }
1153 
1154 
1158  public function setHost($host) {
1159  $this->host = $host;
1160  }
1161 
1162 
1166  public function getDbname() {
1167  return $this->dbname;
1168  }
1169 
1170 
1174  public function setDbname($dbname) {
1175  $this->dbname = $dbname;
1176  }
1177 
1178 
1182  public function getCharset() {
1183  return $this->charset;
1184  }
1185 
1186 
1190  public function setCharset($charset) {
1191  $this->charset = $charset;
1192  }
1193 
1194 
1198  public function getUsername() {
1199  return $this->username;
1200  }
1201 
1202 
1206  public function setUsername($username) {
1207  $this->username = $username;
1208  }
1209 
1210 
1214  public function getPassword() {
1215  return $this->password;
1216  }
1217 
1218 
1222  public function setPassword($password) {
1223  $this->password = $password;
1224  }
1225 
1226 
1230  public function getPort() {
1231  return $this->port;
1232  }
1233 
1234 
1238  public function setPort($port) {
1239  $this->port = $port;
1240  }
1241 
1242 
1246  public function setDBUser($user) {
1247  $this->setUsername($user);
1248  }
1249 
1250 
1254  public function setDBPort($port) {
1255  $this->setPort($port);
1256  }
1257 
1258 
1262  public function setDBPassword($password) {
1263  $this->setPassword($password);
1264  }
1265 
1266 
1270  public function setDBHost($host) {
1271  $this->setHost($host);
1272  }
1273 
1274 
1279  public function upper($a_exp) {
1280  return " UPPER(" . $a_exp . ") ";
1281  }
1282 
1283 
1288  public function lower($a_exp) {
1289  return " LOWER(" . $a_exp . ") ";
1290  }
1291 
1292 
1299  public function substr($a_exp, $a_pos = 1, $a_len = -1) {
1300  $lenstr = "";
1301  if ($a_len > -1) {
1302  $lenstr = ", " . $a_len;
1303  }
1304 
1305  return " SUBSTR(" . $a_exp . ", " . $a_pos . $lenstr . ") ";
1306  }
1307 
1308 
1314  public function prepareManip($query, $types = null) {
1315  return new ilPDOStatement($this->pdo->prepare($query));
1316  }
1317 
1318 
1325  public function prepare($query, $types = null, $result_types = null) {
1326  return new ilPDOStatement($this->pdo->prepare($query));
1327  }
1328 
1329 
1333  public function enableResultBuffering($a_status) {
1334  $this->pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, $a_status);
1335  }
1336 
1337 
1344  public function execute($stmt, $data = array()) {
1348  $result = $stmt->execute($data);
1349  if ($result === false) {
1350  throw new ilDatabaseException(implode(', ', $stmt->errorInfo()), $stmt->errorCode());
1351  }
1352  return $stmt;
1353  }
1354 
1355 
1359  public function supportsSlave() {
1360  return false;
1361  }
1362 
1363 
1367  public function supportsFulltext() {
1368  return false;
1369  }
1370 
1371 
1375  public function supportsTransactions() {
1376  return false;
1377  }
1378 
1379 
1384  public function supports($feature) {
1385  switch ($feature) {
1386  case self::FEATURE_TRANSACTIONS:
1387  return $this->supportsTransactions();
1388  case self::FEATURE_FULLTEXT:
1389  return $this->supportsFulltext();
1390  case self::FEATURE_SLAVE:
1391  return $this->supportsSlave();
1392  default:
1393  return false;
1394  }
1395  }
1396 
1397 
1401  public function listTables() {
1402  return $this->manager->listTables();
1403  }
1404 
1405 
1410  public function loadModule($module) {
1411  switch ($module) {
1413  return $this->manager;
1415  return $this->reverse;
1416  }
1417  }
1418 
1419 
1423  public function getAllowedAttributes() {
1424  return $this->field_definition->getAllowedAttributes();
1425  }
1426 
1427 
1432  public function sequenceExists($sequence) {
1433  return in_array($sequence, $this->listSequences());
1434  }
1435 
1436 
1440  public function listSequences() {
1441  return $this->manager->listSequences();
1442  }
1443 
1444 
1450  public function concat(array $values, $allow_null = true) {
1451  return $this->manager->getQueryUtils()->concat($values, $allow_null);
1452  }
1453 
1454 
1459  protected function appendLimit($query) {
1460  if ($this->limit !== null && $this->offset !== null) {
1461  $query .= ' LIMIT ' . (int)$this->offset . ', ' . (int)$this->limit;
1462  $this->limit = null;
1463  $this->offset = null;
1464 
1465  return $query;
1466  }
1467 
1468  return $query;
1469  }
1470 
1471 
1478  public function locate($a_needle, $a_string, $a_start_pos = 1) {
1479  return $this->manager->getQueryUtils()->locate($a_needle, $a_string, $a_start_pos);
1480  }
1481 
1482 
1490  public function modifyTableColumn($table, $a_column, $a_attributes) {
1491  $def = $this->reverse->getTableFieldDefinition($table, $a_column);
1492 
1493  $analyzer = new ilDBAnalyzer($this);
1494  $best_alt = $analyzer->getBestDefinitionAlternative($def);
1495  $def = $def[$best_alt];
1496  unset($def["nativetype"]);
1497  unset($def["mdb2type"]);
1498 
1499  // check attributes
1500  $ilDBPdoFieldDefinition = $this->field_definition;
1501 
1502  $type = ($a_attributes["type"] != "") ? $a_attributes["type"] : $def["type"];
1503  foreach ($def as $k => $v) {
1504  if ($k != "type" && !$ilDBPdoFieldDefinition->isAllowedAttribute($k, $type)) {
1505  unset($def[$k]);
1506  }
1507  }
1508  $check_array = $def;
1509  foreach ($a_attributes as $k => $v) {
1510  $check_array[$k] = $v;
1511  }
1512  if (!$this->checkColumnDefinition($check_array, true)) {
1513  throw new ilDatabaseException("ilDB Error: modifyTableColumn(" . $table . ", " . $a_column . ")");
1514  }
1515 
1516  foreach ($a_attributes as $a => $v) {
1517  $def[$a] = $v;
1518  }
1519 
1520  $a_attributes["definition"] = $def;
1521 
1522  $changes = array(
1523  "change" => array(
1524  $a_column => $a_attributes,
1525  ),
1526  );
1527 
1528  return $this->manager->alterTable($table, $changes, false);
1529  }
1530 
1531 
1536  public function free($a_st) {
1540  return $a_st->closeCursor();
1541  }
1542 
1543 
1550  public function renameTable($a_name, $a_new_name) {
1551  // check table name
1552  try {
1553  $this->checkTableName($a_new_name);
1554  } catch (ilDatabaseException $e) {
1555  throw new ilDatabaseException("ilDB Error: renameTable(" . $a_name . "," . $a_new_name . ")<br />" . $e->getMessage());
1556  }
1557 
1558  $this->manager->alterTable($a_name, array("name" => $a_new_name), false);
1559 
1560  // The abstraction_progress is no longer used in ILIAS, see http://www.ilias.de/mantis/view.php?id=19513
1561  // $query = "UPDATE abstraction_progress " . "SET table_name = " . $this->quote($a_new_name, 'text') . " " . "WHERE table_name = "
1562  // . $this->quote($a_name, 'text');
1563  // $this->pdo->query($query);
1564 
1565  return true;
1566  }
1567 
1568 
1574  public function checkTableName($a_name) {
1575  return $this->field_definition->checkTableName($a_name);
1576  }
1577 
1578 
1583  public static function isReservedWord($a_word) {
1584  require_once('./Services/Database/classes/PDO/FieldDefinition/class.ilDBPdoMySQLFieldDefinition.php');
1585  global $DIC;
1586  $ilDBPdoMySQLFieldDefinition = new ilDBPdoMySQLFieldDefinition($DIC['ilDB']);
1587 
1588  return $ilDBPdoMySQLFieldDefinition->isReserved($a_word);
1589  }
1590 
1591 
1596  public function beginTransaction() {
1597  if (!$this->supports(self::FEATURE_TRANSACTIONS)) {
1598  throw new ilDatabaseException("ilDB::beginTransaction: Transactions are not supported.");
1599  }
1600 
1601  return $this->pdo->beginTransaction();
1602  }
1603 
1604 
1609  public function commit() {
1610  if (!$this->supports(self::FEATURE_TRANSACTIONS)) {
1611  throw new ilDatabaseException("ilDB::beginTransaction: Transactions are not supported.");
1612  }
1613 
1614  return $this->pdo->commit();
1615  }
1616 
1617 
1622  public function rollback() {
1623  if (!$this->supports(self::FEATURE_TRANSACTIONS)) {
1624  throw new ilDatabaseException("ilDB::beginTransaction: Transactions are not supported.");
1625  }
1626 
1627  return $this->pdo->rollBack();
1628  }
1629 
1630 
1636  public function dropIndex($a_table, $a_name = "i1") {
1637  return $this->manager->dropIndex($a_table, $a_name);
1638  }
1639 
1640 
1645  $this->storage_engine = $storage_engine;
1646  }
1647 
1648 
1652  public function getStorageEngine() {
1653  return $this->storage_engine;
1654  }
1655 
1656 
1663  public function queryCol($query, $type = PDO::FETCH_ASSOC, $colnum = 0) {
1664  switch ($type) {
1666  $type = PDO::FETCH_ASSOC;
1667  break;
1669  $type = PDO::FETCH_OBJ;
1670  break;
1671  default:
1672  $type = PDO::FETCH_ASSOC;
1673  break;
1674  }
1675 
1676  return $this->pdo->query($query, PDO::FETCH_ASSOC)->fetchAll(PDO::FETCH_COLUMN, $colnum);
1677  }
1678 
1679 
1686  public function queryRow($query, $types = null, $fetchmode = ilDBConstants::FETCHMODE_DEFAULT) {
1687  switch ($fetchmode) {
1689  $type = PDO::FETCH_ASSOC;
1690  break;
1692  $type = PDO::FETCH_OBJ;
1693  break;
1694  default:
1695  $type = PDO::FETCH_ASSOC;
1696  break;
1697  }
1698 
1699  return $this->pdo->query($query, $type)->fetch();
1700  }
1701 
1702 
1707  public function getServerVersion($native = false) {
1708  return $this->pdo->query('SELECT VERSION()')->fetchColumn();
1709  }
1710 
1711 
1717  public function escape($value, $escape_wildcards = false) {
1718  return $value;
1719  }
1720 
1721 
1726  public function escapePattern($text) {
1727  return $text;
1728  }
1729 
1730 
1736  return array();
1737  }
1738 
1739 
1744  return array();
1745  }
1746 
1747 
1751  public function supportsCollationMigration() {
1752  return false;
1753  }
1754 
1755 
1759  public function supportsEngineMigration() {
1760  return false;
1761  }
1762 
1763 
1769  public function checkIndexName($name) {
1770  return $this->getFieldDefinition()->checkIndexName($name);
1771  }
1772 
1773 
1781  public function addUniqueConstraint($table, $fields, $name = "con") {
1782  assert(is_array($fields));
1784 
1785  // check index name
1786  if (!$this->checkIndexName($name)) {
1787  throw new ilDatabaseException("ilDB Error: addUniqueConstraint(" . $table . "," . $name . ")");
1788  }
1789 
1790  $fields_corrected = array();
1791  foreach ($fields as $f) {
1792  $fields_corrected[$f] = array();
1793  }
1794  $definition = array(
1795  'unique' => true,
1796  'fields' => $fields_corrected,
1797  );
1798 
1799  return $manager->createConstraint($table, $this->constraintName($table, $name), $definition);
1800  }
1801 
1802 
1808  public function dropUniqueConstraint($a_table, $a_name = "con") {
1809  return $this->manager->dropConstraint($a_table, $this->constraintName($a_table, $a_name), false);
1810  }
1811 
1812 
1818  public function dropUniqueConstraintByFields($a_table, $a_fields) {
1819  $analyzer = new ilDBAnalyzer();
1820  $cons = $analyzer->getConstraintsInformation($a_table);
1821  foreach ($cons as $c) {
1822  if ($c["type"] == "unique" && count($a_fields) == count($c["fields"])) {
1823  $all_in = true;
1824  foreach ($a_fields as $f) {
1825  if (!isset($c["fields"][$f])) {
1826  $all_in = false;
1827  }
1828  }
1829  if ($all_in) {
1830  return $this->dropUniqueConstraint($a_table, $c['name']);
1831  }
1832  }
1833  }
1834 
1835  return false;
1836  }
1837 
1838 
1842  public function getLastInsertId() {
1843  return $this->pdo->lastInsertId();
1844  }
1845 
1846 
1850  public function buildAtomQuery() {
1851  require_once('./Services/Database/classes/Atom/class.ilAtomQueryLock.php');
1852 
1853  return new ilAtomQueryLock($this);
1854  }
1855 
1856 
1862  public function uniqueConstraintExists($table, array $fields) {
1863  require_once('./Services/Database/classes/class.ilDBAnalyzer.php');
1864  $analyzer = new ilDBAnalyzer();
1865  $cons = $analyzer->getConstraintsInformation($table);
1866  foreach ($cons as $c) {
1867  if ($c["type"] == "unique" && count($fields) == count($c["fields"])) {
1868  $all_in = true;
1869  foreach ($fields as $f) {
1870  if (!isset($c["fields"][$f])) {
1871  $all_in = false;
1872  }
1873  }
1874  if ($all_in) {
1875  return true;
1876  }
1877  }
1878  }
1879 
1880  return false;
1881  }
1882 
1883 
1888  public function dropPrimaryKey($table_name) {
1889  return $this->manager->dropConstraint($table_name, "PRIMARY", true);
1890  }
1891 
1892 
1897  public function executeMultiple($stmt, $a_data) {
1898  for ($i = 0, $j = count($a_data); $i < $j; $i++) {
1899  $stmt->execute($a_data[$i]);
1900  }
1901  }
1902 
1903 
1909  public function fromUnixtime($a_expr, $a_to_text = true) {
1910  return "FROM_UNIXTIME(" . $a_expr . ")";
1911  }
1912 
1913 
1917  public function unixTimestamp() {
1918  return "UNIX_TIMESTAMP()";
1919  }
1920 
1921 
1937  public function autoExecute($tablename, $fields, $mode = ilDBConstants::MDB2_AUTOQUERY_INSERT, $where = false) {
1938  $fields_values = (array)$fields;
1939  if ($mode == ilDBConstants::MDB2_AUTOQUERY_INSERT) {
1940  if (!empty($fields_values)) {
1941  $keys = $fields_values;
1942  } else {
1943  $keys = array();
1944  }
1945  } else {
1946  $keys = array_keys($fields_values);
1947  }
1948  $params = array_values($fields_values);
1949  if (empty($params)) {
1950  $query = $this->buildManipSQL($tablename, $keys, $mode, $where);
1951  $result = $this->pdo->query($query);
1952  } else {
1953  $stmt = $this->autoPrepare($tablename, $keys, $mode, $where, $types, $result_types);
1954  $this->execute($stmt);
1955  $this->free($stmt);
1956  $result = $stmt;
1957  }
1958 
1959  return $result;
1960  }
1961 
1962 
1972  protected function autoPrepare($table, $table_fields, $mode = ilDBConstants::MDB2_AUTOQUERY_INSERT, $where = false, $types = null, $result_types = ilDBConstants::MDB2_PREPARE_MANIP) {
1973  $query = $this->buildManipSQL($table, $table_fields, $mode, $where);
1974 
1975  return $this->prepare($query, $types, $result_types);
1976  }
1977 
1978 
1987  protected function buildManipSQL($table, $table_fields, $mode, $where = false) {
1988  if ($this->options['quote_identifier']) {
1989  $table = $this->quoteIdentifier($table);
1990  }
1991 
1992  if (!empty($table_fields) && $this->options['quote_identifier']) {
1993  foreach ($table_fields as $key => $field) {
1994  $table_fields[$key] = $this->quoteIdentifier($field);
1995  }
1996  }
1997 
1998  if ($where !== false && !is_null($where)) {
1999  if (is_array($where)) {
2000  $where = implode(' AND ', $where);
2001  }
2002  $where = ' WHERE ' . $where;
2003  }
2004 
2005  switch ($mode) {
2007  if (empty($table_fields)) {
2008  throw new ilDatabaseException('Insert requires table fields');
2009  }
2010  $cols = implode(', ', $table_fields);
2011  $values = '?' . str_repeat(', ?', (count($table_fields) - 1));
2012 
2013  return 'INSERT INTO ' . $table . ' (' . $cols . ') VALUES (' . $values . ')';
2014  break;
2016  if (empty($table_fields)) {
2017  throw new ilDatabaseException('Update requires table fields');
2018  }
2019  $set = implode(' = ?, ', $table_fields) . ' = ?';
2020  $sql = 'UPDATE ' . $table . ' SET ' . $set . $where;
2021 
2022  return $sql;
2023  break;
2025  $sql = 'DELETE FROM ' . $table . $where;
2026 
2027  return $sql;
2028  break;
2030  $cols = !empty($table_fields) ? implode(', ', $table_fields) : '*';
2031  $sql = 'SELECT ' . $cols . ' FROM ' . $table . $where;
2032 
2033  return $sql;
2034  break;
2035  }
2036 
2037  throw new ilDatabaseException('Syntax error');
2038  }
2039 
2040 
2045  public function getDBVersion() {
2046  $d = $this->fetchObject($this->query("SELECT VERSION() AS version"));
2047 
2048  return ($d->version ? $d->version : 'Unknown');
2049  }
2050 
2051 
2056  {
2057  if (!$this->doesCollationSupportMB4Strings()) {
2058  $query_replaced = preg_replace(
2059  '/[\x{10000}-\x{10FFFF}]/u', ilDBConstants::MB4_REPLACEMENT, $query
2060  );
2061  if (!empty($query_replaced)) {
2062  return $query_replaced;
2063  }
2064  }
2065 
2066  return $query;
2067  }
2068 
2073  {
2074  return false;
2075  }
2076 
2077 
2081  public function groupConcat($a_field_name, $a_seperator = ",", $a_order = NULL) {
2082  return $this->manager->getQueryUtils()->groupConcat($a_field_name, $a_seperator, $a_order);
2083  }
2084 
2088  public function cast($a_field_name, $a_dest_type) {
2089  return $this->manager->getQueryUtils()->cast($a_field_name, $a_dest_type);
2090  }
2091 }
sanitizeMB4StringIfNotSupported($query)
string to sanitize, all MB4-Characters like emojis will re replaced with ???string sanitized query ...
upper($a_exp)
supportsTransactions()
setPassword($password)
useSlave($bool)
addPrimaryKey($table_name, $primary_keys)
checkTableName($a_name)
setFieldDefinition($field_definition)
escapePattern($text)
addIndex($table_name, $fields, $index_name='', $fulltext=false)
static getReservedWords()
Get reserved words.
getSequenceName($table_name)
doesCollationSupportMB4Strings()
$result
equals($columns, $value, $type, $emptyOrNull=false)
execute($stmt, $data=array())
Class ilPDOStatement is a Wrapper Class for PDOStatement.
like($column, $type, $value="?", $case_insensitive=true)
queryF($query, $types, $values)
getServerVersion($native=false)
escape($value, $escape_wildcards=false)
$engine
Definition: workflow.php:90
setDBPort($port)
Interface ilDBPdoInterface.
numRows($query_result)
dropUniqueConstraint($a_table, $a_name="con")
Class ilAtomQueryLock.
setUsername($username)
supportsCollationMigration()
dropSequence($table_name)
setDBType($type)
sequenceExists($sequence)
update($table_name, $columns, $where)
renameTableColumn($table_name, $column_old_name, $column_new_name)
queryCol($query, $type=PDO::FETCH_ASSOC, $colnum=0)
concat(array $values, $allow_null=true)
quote($value, $type=null)
logging
Definition: class.ilLog.php:18
modifyTableColumn($table, $a_column, $a_attributes)
const FEATURE_FULLTEXT
autoPrepare($table, $table_fields, $mode=ilDBConstants::MDB2_AUTOQUERY_INSERT, $where=false, $types=null, $result_types=ilDBConstants::MDB2_PREPARE_MANIP)
Class ilDatabaseException.
initHelpers()
executeMultiple($stmt, $a_data)
dropFulltextIndex($a_table, $a_name)
Drop fulltext index.
checkColumnName($a_name)
for($col=0; $col< 50; $col++) $d
indexExistsByFields($table_name, $fields)
migrateAllTablesToCollation($collation=ilDBConstants::MYSQL_COLLATION_UTF8MB4)
manipulateF($query, $types, $values)
addFulltextIndex($a_table, $a_fields, $a_name="in")
getAdditionalAttributes()
setHost($host)
Class pdoDB.
supports($feature)
setDBUser($user)
lockTables($tables)
Interface ilDBInterface.
$info
Definition: example_052.php:80
$r
Definition: example_031.php:79
dropTable($table_name, $error_if_not_existing=true)
checkTableColumns($a_cols)
queryRow($query, $types=null, $fetchmode=ilDBConstants::FETCHMODE_DEFAULT)
$column
Definition: 39dropdown.php:62
const FEATURE_SLAVE
quoteIdentifier($identifier, $check_option=false)
if(!is_array($argv)) $options
dropUniqueConstraintByFields($a_table, $a_fields)
isFulltextIndex($a_table, $a_name)
Is index a fulltext index?
query($query)
replace($table, $primaryKeys, $otherColumns)
Replace into method.
static isReservedWord($a_word)
createTable($table_name, $fields, $drop_table=false, $ignore_erros=false)
getFieldDefinition()
fetchAssoc($query_result)
nextId($table_name)
setCharset($charset)
createDatabase($a_name, $a_charset="utf8", $a_collation="")
tableExists($table_name)
autoExecute($tablename, $fields, $mode=ilDBConstants::MDB2_AUTOQUERY_INSERT, $where=false)
Generate an insert, update or delete query and call prepare() and execute() on it.
tableColumnExists($table_name, $column_name)
dropPrimaryKey($table_name)
getLastErrorCode()
supportsEngineMigration()
setLimit($limit, $offset=0)
Set the Limit for the next Query.
setDbname($dbname)
groupConcat($a_field_name, $a_seperator=",", $a_order=NULL)
string
lower($a_exp)
dropTableColumn($table_name, $column_name)
dropIndexByFields($table_name, $fields)
checkColumn($a_col, $a_def)
Create styles array
The data for the language used.
constraintName($a_table, $a_constraint)
Determine contraint name by table name and constraint name.
prepareManip($query, $types=null)
checkIndexName($name)
getPrimaryKeyIdentifier()
loadModule($module)
setDBHost($host)
appendLimit($query)
Class ilDBPdoMySQLFieldDefinition.
createSequence($table_name, $start=1)
in($field, $values, $negate=false, $type="")
getAllowedAttributes()
array
buildManipSQL($table, $table_fields, $mode, $where=false)
setPort($port)
setStorageEngine($storage_engine)
addUniqueConstraint($table, $fields, $name="con")
const FEATURE_TRANSACTIONS
addTableColumn($table_name, $column_name, $attributes)
locate($a_needle, $a_string, $a_start_pos=1)
fromUnixtime($a_expr, $a_to_text=true)
global $ilBench
Definition: ilias.php:18
global $ilDB
enableResultBuffering($a_status)
$text
performance measurement class
insert($table_name, $values)
setDBPassword($password)
cast($a_field_name, $a_dest_type)
string;
global $DIC
This class gives all kind of DB information using the MDB2 manager and reverse module.
connect($return_false_for_error=false)
uniqueConstraintExists($table, array $fields)
manipulate($query)
if(! $in) $columns
Definition: Utf8Test.php:45
renameTable($a_name, $a_new_name)
dropIndex($a_table, $a_name="i1")
migrateAllTablesToEngine($engine=ilDBConstants::MYSQL_ENGINE_INNODB)
INIFile Parser.
$params
Definition: example_049.php:96
prepare($query, $types=null, $result_types=null)
fetchObject($query_result)
substr($a_exp, $a_pos=1, $a_len=-1)
initFromIniFile($tmpClientIniFile=null)
fetchAll($query_result, $fetch_mode=ilDBConstants::FETCHMODE_ASSOC)
getIndexName($index_name_base)
checkColumnDefinition($a_def, $a_modify_mode=false)