ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
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 
10 abstract class ilDBPdo implements ilDBInterface, ilDBPdoInterface
11 {
12  const FEATURE_TRANSACTIONS = 'transactions';
13  const FEATURE_FULLTEXT = 'fulltext';
14  const FEATURE_SLAVE = 'slave';
18  protected $host = '';
22  protected $dbname = '';
26  protected $charset = 'utf8';
30  protected $username = '';
34  protected $password = '';
38  protected $port = 3306;
42  protected $pdo;
46  protected $manager;
50  protected $reverse;
54  protected $limit = null;
58  protected $offset = null;
62  protected $storage_engine = 'MyISAM';
66  protected $dsn = '';
70  protected $attributes = array(
71  // PDO::ATTR_EMULATE_PREPARES => true,
72  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
73  );
77  protected $db_type = '';
81  protected $error_code = 0;
85  protected $field_definition;
86 
87 
93  public function connect($return_false_for_error = false)
94  {
95  $this->generateDSN();
96  try {
97  $options = $this->getAttributes();
98  $this->pdo = new PDO($this->getDSN(), $this->getUsername(), $this->getPassword(), $options);
99  $this->initHelpers();
100  $this->initSQLMode();
101  } catch (Exception $e) {
102  $this->error_code = $e->getCode();
103  if ($return_false_for_error) {
104  return false;
105  }
106  throw $e;
107  }
108 
109  return ($this->pdo->errorCode() == PDO::ERR_NONE);
110  }
111 
112 
113  abstract public function initHelpers();
114 
115 
116  protected function initSQLMode()
117  {
118  }
119 
120 
124  protected function getAttributes()
125  {
126  $options = $this->attributes;
127  foreach ($this->getAdditionalAttributes() as $k => $v) {
128  $options[$k] = $v;
129  }
130 
131  return $options;
132  }
133 
134 
138  protected function getAdditionalAttributes()
139  {
140  return array();
141  }
142 
143 
147  public function getFieldDefinition()
148  {
150  }
151 
152 
157  {
158  $this->field_definition = $field_definition;
159  }
160 
161 
169  public function createDatabase($a_name, $a_charset = "utf8", $a_collation = "")
170  {
171  $this->setDbname(null);
172  $this->generateDSN();
173  $this->connect(true);
174  try {
175  return $this->query($this->manager->getQueryUtils()->createDatabase($a_name, $a_charset, $a_collation));
176  } catch (PDOException $e) {
177  return false;
178  }
179  }
180 
181 
185  public function getLastErrorCode()
186  {
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  {
200  global $DIC;
201 
202  if ($tmpClientIniFile instanceof ilIniFile) {
203  $clientIniFile = $tmpClientIniFile;
204  } else {
205  $ilClientIniFile = null;
206  if ($DIC->offsetExists('ilClientIniFile')) {
207  $clientIniFile = $DIC['ilClientIniFile'];
208  } else {
209  throw new InvalidArgumentException('$tmpClientIniFile is not an instance of ilIniFile');
210  }
211  }
212 
213  $this->setUsername($clientIniFile->readVariable("db", "user"));
214  $this->setHost($clientIniFile->readVariable("db", "host"));
215  $this->setPort((int) $clientIniFile->readVariable("db", "port"));
216  $this->setPassword($clientIniFile->readVariable("db", "pass"));
217  $this->setDbname($clientIniFile->readVariable("db", "name"));
218  $this->setDBType($clientIniFile->readVariable("db", "type"));
219 
220  $this->generateDSN();
221  }
222 
223 
224  public function generateDSN()
225  {
226  $port = $this->getPort() ? ";port=" . $this->getPort() : "";
227  $dbname = $this->getDbname() ? ';dbname=' . $this->getDbname() : '';
228  $host = $this->getHost();
229  $charset = ';charset=' . $this->getCharset();
230  $this->dsn = 'mysql:host=' . $host . $port . $dbname . $charset;
231  }
232 
233 
238  public function quoteIdentifier($identifier, $check_option = false)
239  {
240  return '`' . $identifier . '`';
241  }
242 
243 
249  abstract public function nextId($table_name);
250 
251 
260  public function createTable($table_name, $fields, $drop_table = false, $ignore_erros = false)
261  {
262  // check table name
263  if (!$this->checkTableName($table_name) && !$ignore_erros) {
264  throw new ilDatabaseException("ilDB Error: createTable(" . $table_name . ")");
265  }
266 
267  // check definition array
268  if (!$this->checkTableColumns($fields) && !$ignore_erros) {
269  throw new ilDatabaseException("ilDB Error: createTable(" . $table_name . ")");
270  }
271 
272  if ($drop_table) {
273  $this->dropTable($table_name, false);
274  }
275 
276  return $this->manager->createTable($table_name, $fields, array());
277  }
278 
279 
284  protected function checkTableColumns($a_cols)
285  {
286  foreach ($a_cols as $col => $def) {
287  if (!$this->checkColumn($col, $def)) {
288  return false;
289  }
290  }
291 
292  return true;
293  }
294 
295 
301  protected function checkColumn($a_col, $a_def)
302  {
303  if (!$this->checkColumnName($a_col)) {
304  return false;
305  }
306 
307  if (!$this->checkColumnDefinition($a_def)) {
308  return false;
309  }
310 
311  return true;
312  }
313 
314 
320  protected function checkColumnDefinition($a_def, $a_modify_mode = false)
321  {
322  return $this->field_definition->checkColumnDefinition($a_def);
323  }
324 
325 
330  public function checkColumnName($a_name)
331  {
332  return $this->field_definition->checkColumnName($a_name);
333  }
334 
335 
342  public function addPrimaryKey($table_name, $primary_keys)
343  {
344  assert(is_array($primary_keys));
345 
346  $fields = array();
347  foreach ($primary_keys as $f) {
348  $fields[$f] = array();
349  }
350  $definition = array(
351  'primary' => true,
352  'fields' => $fields,
353  );
354  $this->manager->createConstraint($table_name, $this->constraintName($table_name, $this->getPrimaryKeyIdentifier()), $definition);
355 
356  return true;
357  }
358 
359 
366  public function dropIndexByFields($table_name, $fields)
367  {
368  foreach ($this->manager->listTableIndexes($table_name) as $idx_name) {
369  $def = $this->reverse->getTableIndexDefinition($table_name, $idx_name);
370  $idx_fields = array_keys((array) $def['fields']);
371 
372  if ($idx_fields === $fields) {
373  return $this->dropIndex($table_name, $idx_name);
374  }
375  }
376 
377  return false;
378  }
379 
380 
384  public function getPrimaryKeyIdentifier()
385  {
386  return "PRIMARY";
387  }
388 
389 
394  public function createSequence($table_name, $start = 1)
395  {
396  $this->manager->createSequence($table_name, $start);
397  }
398 
399 
405  public function tableExists($table_name)
406  {
407  $result = $this->pdo->prepare("SHOW TABLES LIKE :table_name");
408  $result->execute(array('table_name' => $table_name));
409  $return = $result->rowCount();
410  $result->closeCursor();
411 
412  return $return > 0;
413  }
414 
415 
422  public function tableColumnExists($table_name, $column_name)
423  {
424  $fields = $this->loadModule(ilDBConstants::MODULE_MANAGER)->listTableFields($table_name);
425 
426  $in_array = in_array($column_name, $fields);
427 
428  return $in_array;
429  }
430 
431 
439  public function addTableColumn($table_name, $column_name, $attributes)
440  {
441  if (!$this->checkColumnName($column_name)) {
442  throw new ilDatabaseException("ilDB Error: addTableColumn(" . $table_name . ", " . $column_name . ")");
443  }
444  if (!$this->checkColumnDefinition($attributes)) {
445  throw new ilDatabaseException("ilDB Error: addTableColumn(" . $table_name . ", " . $column_name . ")");
446  }
447 
448  $changes = array(
449  "add" => array(
450  $column_name => $attributes,
451  ),
452  );
453 
454  return $this->manager->alterTable($table_name, $changes, false);
455  }
456 
457 
464  public function dropTable($table_name, $error_if_not_existing = true)
465  {
466  $ilDBPdoManager = $this->loadModule(ilDBConstants::MODULE_MANAGER);
467  $tables = $ilDBPdoManager->listTables();
468  $table_exists = in_array($table_name, $tables);
469  if (!$table_exists && $error_if_not_existing) {
470  throw new ilDatabaseException("Table {$table_name} does not exist");
471  }
472 
473  // drop sequence
474  $sequences = $ilDBPdoManager->listSequences();
475  if (in_array($table_name, $sequences)) {
476  $ilDBPdoManager->dropSequence($table_name);
477  }
478 
479  // drop table
480  if ($table_exists) {
481  $ilDBPdoManager->dropTable($table_name);
482  }
483 
484  return true;
485  }
486 
487 
494  public function query($query)
495  {
496  global $DIC;
497  $ilBench = $DIC['ilBench'];
498 
499  $query = $this->appendLimit($query);
500 
501  try {
502  if ($ilBench instanceof ilBenchmark) {
503  $ilBench->startDbBench($query);
504  }
505  $res = $this->pdo->query($query);
506  if ($ilBench instanceof ilBenchmark) {
507  $ilBench->stopDbBench();
508  }
509  } catch (PDOException $e) {
510  throw new ilDatabaseException($e->getMessage() . ' QUERY: ' . $query);
511  }
512 
513  $err = $this->pdo->errorCode();
514  if ($err != PDO::ERR_NONE) {
515  $info = $this->pdo->errorInfo();
516  $info_message = $info[2];
517  throw new ilDatabaseException($info_message . ' QUERY: ' . $query);
518  }
519 
520  return new ilPDOStatement($res);
521  }
522 
523 
529  public function fetchAll($query_result, $fetch_mode = ilDBConstants::FETCHMODE_ASSOC)
530  {
534  $return = array();
535  while ($data = $query_result->fetch($fetch_mode)) {
536  $return[] = $data;
537  }
538 
539  return $return;
540  }
541 
542 
546  public function dropSequence($table_name)
547  {
548  $this->manager->dropSequence($table_name);
549  }
550 
551 
558  public function dropTableColumn($table_name, $column_name)
559  {
560  $changes = array(
561  "remove" => array(
562  $column_name => array(),
563  ),
564  );
565 
566  return $this->manager->alterTable($table_name, $changes, false);
567  }
568 
569 
577  public function renameTableColumn($table_name, $column_old_name, $column_new_name)
578  {
579  // check table name
580  if (!$this->checkColumnName($column_new_name)) {
581  throw new ilDatabaseException("ilDB Error: renameTableColumn(" . $table_name . "," . $column_old_name . "," . $column_new_name . ")");
582  }
583 
584  $def = $this->reverse->getTableFieldDefinition($table_name, $column_old_name);
585 
586  $analyzer = new ilDBAnalyzer($this);
587  $best_alt = $analyzer->getBestDefinitionAlternative($def);
588  $def = $def[$best_alt];
589  unset($def["nativetype"]);
590  unset($def["mdb2type"]);
591 
592  $f["definition"] = $def;
593  $f["name"] = $column_new_name;
594 
595  $changes = array(
596  "rename" => array(
597  $column_old_name => $f,
598  ),
599  );
600 
601  return $this->manager->alterTable($table_name, $changes, false);
602  }
603 
604 
610  public function insert($table_name, $values)
611  {
612  $real = array();
613  $fields = array();
614  foreach ($values as $key => $val) {
615  $real[] = $this->quote($val[1], $val[0]);
616  $fields[] = $this->quoteIdentifier($key);
617  }
618  $values = implode(",", $real);
619  $fields = implode(",", $fields);
620  $query = "INSERT INTO " . $this->quoteIdentifier($table_name) . " (" . $fields . ") VALUES (" . $values . ")";
621 
623 
624  return $this->pdo->exec($query);
625  }
626 
627 
633  public function fetchObject($query_result)
634  {
635  $res = $query_result->fetchObject();
636  if ($res == null) {
637  $query_result->closeCursor();
638 
639  return null;
640  }
641 
642  return $res;
643  }
644 
645 
652  public function update($table_name, $columns, $where)
653  {
654  $fields = array();
655  $field_values = array();
656  $placeholders = array();
657  $placeholders_full = array();
658  $types = array();
659  $values = array();
660  $lobs = false;
661  $lob = array();
662  foreach ($columns as $k => $col) {
663  $field_value = $col[1];
664  $fields[] = $k;
665  $placeholders[] = "%s";
666  $placeholders_full[] = ":$k";
667  $types[] = $col[0];
668 
669  if ($col[0] == "blob" || $col[0] == "clob" || $col[0] == 'text') {
670  $field_value = $this->sanitizeMB4StringIfNotSupported($field_value);
671  }
672 
673  // integer auto-typecast (this casts bool values to integer)
674  if ($col[0] == 'integer' && !is_null($field_value)) {
675  $field_value = (int) $field_value;
676  }
677 
678  $values[] = $field_value;
679  $field_values[$k] = $field_value;
680  if ($col[0] == "blob" || $col[0] == "clob") {
681  $lobs = true;
682  $lob[$k] = $k;
683  }
684  }
685 
686  if ($lobs) {
687  $q = "UPDATE " . $this->quoteIdentifier($table_name) . " SET ";
688  $lim = "";
689  foreach ($fields as $k => $field) {
690  $q .= $lim . $field . " = " . $placeholders_full[$k];
691  $lim = ", ";
692  }
693  $q .= " WHERE ";
694  $lim = "";
695  foreach ($where as $k => $col) {
696  $q .= $lim . $k . " = " . $this->quote($col[1], $col[0]);
697  $lim = " AND ";
698  }
699 
700  $r = $this->prepareManip($q, $types);
701  $this->execute($r, $field_values);
702  $this->free($r);
703  } else {
704  foreach ($where as $k => $col) {
705  $types[] = $col[0];
706  $values[] = $col[1];
707  $field_values[$k] = $col;
708  }
709  $q = "UPDATE " . $this->quoteIdentifier($table_name) . " SET ";
710  $lim = "";
711  foreach ($fields as $k => $field) {
712  $q .= $lim . $this->quoteIdentifier($field) . " = " . $placeholders[$k];
713  $lim = ", ";
714  }
715  $q .= " WHERE ";
716  $lim = "";
717  foreach ($where as $k => $col) {
718  $q .= $lim . $k . " = %s";
719  $lim = " AND ";
720  }
721 
722  $r = $this->manipulateF($q, $types, $values);
723  }
724 
725  return $r;
726  }
727 
728 
729 
735  public function manipulate($query)
736  {
737  global $DIC;
738  $ilBench = $DIC['ilBench'];
739  try {
741  if ($ilBench instanceof ilBenchmark) {
742  $ilBench->startDbBench($query);
743  }
744  $r = $this->pdo->exec($query);
745  if ($ilBench instanceof ilBenchmark) {
746  $ilBench->stopDbBench();
747  }
748  } catch (PDOException $e) {
749  throw new ilDatabaseException($e->getMessage() . ' QUERY: ' . $query);
750  }
751 
752  return $r;
753  }
754 
755 
761  public function fetchAssoc($query_result)
762  {
763  $res = $query_result->fetch(PDO::FETCH_ASSOC);
764  if ($res == null) {
765  $query_result->closeCursor();
766 
767  return null;
768  }
769 
770  return $res;
771  }
772 
773 
779  public function numRows($query_result)
780  {
781  return $query_result->rowCount();
782  }
783 
784 
791  public function quote($value, $type = null)
792  {
793  if ($value === null) {
794  return 'NULL';
795  }
796 
797  $pdo_type = PDO::PARAM_STR;
798  switch ($type) {
802  if ($value === '') {
803  return 'NULL';
804  }
805  break;
807  $value = (int) $value;
808 
809  return $value;
810  break;
812  $pdo_type = PDO::PARAM_INT;
813  break;
815  default:
816  $pdo_type = PDO::PARAM_STR;
817  break;
818  }
819 
820  return $this->pdo->quote($value, $pdo_type);
821  }
822 
823 
830  public function indexExistsByFields($table_name, $fields)
831  {
832  foreach ($this->manager->listTableIndexes($table_name) as $idx_name) {
833  $def = $this->reverse->getTableIndexDefinition($table_name, $idx_name);
834  $idx_fields = array_keys((array) $def['fields']);
835 
836  if ($idx_fields === $fields) {
837  return true;
838  }
839  }
840 
841  return false;
842  }
843 
844 
851  public function addIndex($table_name, $fields, $index_name = '', $fulltext = false)
852  {
853  assert(is_array($fields));
854  $this->field_definition->checkIndexName($index_name);
855 
856  $definition_fields = array();
857  foreach ($fields as $f) {
858  $definition_fields[$f] = array();
859  }
860  $definition = array(
861  'fields' => $definition_fields,
862  );
863 
864  if (!$fulltext) {
865  $this->manager->createIndex($table_name, $this->constraintName($table_name, $index_name), $definition);
866  } else {
867  if ($this->supportsFulltext()) {
868  $this->addFulltextIndex($table_name, $fields, $index_name); // TODO
869  }
870  }
871 
872  return true;
873  }
874 
875 
883  public function addFulltextIndex($a_table, $a_fields, $a_name = "in")
884  {
885  $i_name = $this->constraintName($a_table, $a_name) . "_idx";
886  $f_str = implode(",", $a_fields);
887  $q = "ALTER TABLE $a_table ADD FULLTEXT $i_name ($f_str)";
888  $this->query($q);
889  }
890 
891 
895  public function dropFulltextIndex($a_table, $a_name)
896  {
897  $i_name = $this->constraintName($a_table, $a_name) . "_idx";
898  $this->query("ALTER TABLE $a_table DROP FULLTEXT $i_name");
899  }
900 
901 
905  public function isFulltextIndex($a_table, $a_name)
906  {
907  $set = $this->query("SHOW INDEX FROM " . $a_table);
908  while ($rec = $this->fetchAssoc($set)) {
909  if ($rec["Key_name"] == $a_name && $rec["Index_type"] == "FULLTEXT") {
910  return true;
911  }
912  }
913 
914  return false;
915  }
916 
917 
922  public function getIndexName($index_name_base)
923  {
924  return sprintf(ilDBPdoFieldDefinition::INDEX_FORMAT, preg_replace('/[^a-z0-9_\$]/i', '_', $index_name_base));
925  }
926 
927 
932  public function getSequenceName($table_name)
933  {
934  return sprintf(ilDBPdoFieldDefinition::SEQUENCE_FORMAT, preg_replace('/[^a-z0-9_\$.]/i', '_', $table_name));
935  }
936 
937 
942  public function constraintName($a_table, $a_constraint)
943  {
944  return $a_constraint;
945  }
946 
947 
951  public function getDSN()
952  {
953  return $this->dsn;
954  }
955 
956 
960  public function getDBType()
961  {
962  return $this->db_type;
963  }
964 
965 
970  public function setDBType($type)
971  {
972  $this->db_type = $type;
973  }
974 
975 
980  public static function getReservedWords()
981  {
982  global $DIC;
983  $ilDB = $DIC->database();
984 
988  return $ilDB->getFieldDefinition()->getReservedMysql();
989  }
990 
991 
996  public function lockTables($tables)
997  {
998  assert(is_array($tables));
999 
1000  $lock = $this->manager->getQueryUtils()->lock($tables);
1001  global $DIC;
1002  $ilLogger = $DIC->logger()->root();
1003  if ($ilLogger instanceof ilLogger) {
1004  $ilLogger->log('ilDB::lockTables(): ' . $lock);
1005  }
1006 
1007  $this->pdo->exec($lock);
1008  }
1009 
1010 
1015  public function unlockTables()
1016  {
1017  $this->pdo->exec($this->manager->getQueryUtils()->unlock());
1018  }
1019 
1020 
1028  public function in($field, $values, $negate = false, $type = "")
1029  {
1030  return $this->manager->getQueryUtils()->in($field, $values, $negate, $type);
1031  }
1032 
1033 
1041  public function queryF($query, $types, $values)
1042  {
1043  if (!is_array($types) || !is_array($values) || count($types) != count($values)) {
1044  throw new ilDatabaseException("ilDB::queryF: Types and values must be arrays of same size. ($query)");
1045  }
1046  $quoted_values = array();
1047  foreach ($types as $k => $t) {
1048  $quoted_values[] = $this->quote($values[$k], $t);
1049  }
1050  $query = vsprintf($query, $quoted_values);
1051 
1052  return $this->query($query);
1053  }
1054 
1055 
1063  public function manipulateF($query, $types, $values)
1064  {
1065  if (!is_array($types) || !is_array($values) || count($types) != count($values)) {
1066  throw new ilDatabaseException("ilDB::manipulateF: types and values must be arrays of same size. ($query)");
1067  }
1068  $quoted_values = array();
1069  foreach ($types as $k => $t) {
1070  $quoted_values[] = $this->quote($values[$k], $t);
1071  }
1072  $query = vsprintf($query, $quoted_values);
1073 
1074  return $this->manipulate($query);
1075  }
1076 
1077 
1084  public function useSlave($bool)
1085  {
1086  return false;
1087  }
1088 
1089 
1096  public function setLimit($limit, $offset = 0)
1097  {
1098  $this->limit = $limit;
1099  $this->offset = $offset;
1100  }
1101 
1102 
1111  public function like($column, $type, $value = "?", $case_insensitive = true)
1112  {
1113  return $this->manager->getQueryUtils()->like($column, $type, $value, $case_insensitive);
1114  }
1115 
1116 
1120  public function now()
1121  {
1122  return $this->manager->getQueryUtils()->now();
1123  }
1124 
1125 
1134  public function replace($table, $primaryKeys, $otherColumns)
1135  {
1136  $a_columns = array_merge($primaryKeys, $otherColumns);
1137  $fields = array();
1138  $field_values = array();
1139  $placeholders = array();
1140  $types = array();
1141  $values = array();
1142 
1143  foreach ($a_columns as $k => $col) {
1144  $fields[] = $k;
1145  $placeholders[] = "%s";
1146  $placeholders2[] = ":$k";
1147  $types[] = $col[0];
1148 
1149  // integer auto-typecast (this casts bool values to integer)
1150  if ($col[0] == 'integer' && !is_null($col[1])) {
1151  $col[1] = (int) $col[1];
1152  }
1153 
1154  $values[] = $col[1];
1155  $field_values[$k] = $col[1];
1156  }
1157 
1158  $q = "REPLACE INTO " . $table . " (" . implode(",", $fields) . ") VALUES (" . implode(",", $placeholders) . ")";
1159 
1160  $r = $this->manipulateF($q, $types, $values);
1161 
1162  return $r;
1163  }
1164 
1165 
1173  public function equals($columns, $value, $type, $emptyOrNull = false)
1174  {
1175  if (!$emptyOrNull || $value != "") {
1176  return $columns . " = " . $this->quote($value, $type);
1177  } else {
1178  return "(" . $columns . " = '' OR $columns IS NULL)";
1179  }
1180  }
1181 
1182 
1186  public function getHost()
1187  {
1188  return $this->host;
1189  }
1190 
1191 
1195  public function setHost($host)
1196  {
1197  $this->host = $host;
1198  }
1199 
1200 
1204  public function getDbname()
1205  {
1206  return $this->dbname;
1207  }
1208 
1209 
1213  public function setDbname($dbname)
1214  {
1215  $this->dbname = $dbname;
1216  }
1217 
1218 
1222  public function getCharset()
1223  {
1224  return $this->charset;
1225  }
1226 
1227 
1231  public function setCharset($charset)
1232  {
1233  $this->charset = $charset;
1234  }
1235 
1236 
1240  public function getUsername()
1241  {
1242  return $this->username;
1243  }
1244 
1245 
1249  public function setUsername($username)
1250  {
1251  $this->username = $username;
1252  }
1253 
1254 
1258  public function getPassword()
1259  {
1260  return $this->password;
1261  }
1262 
1263 
1267  public function setPassword($password)
1268  {
1269  $this->password = $password;
1270  }
1271 
1272 
1276  public function getPort()
1277  {
1278  return $this->port;
1279  }
1280 
1281 
1285  public function setPort($port)
1286  {
1287  $this->port = $port;
1288  }
1289 
1290 
1294  public function setDBUser($user)
1295  {
1296  $this->setUsername($user);
1297  }
1298 
1299 
1303  public function setDBPort($port)
1304  {
1305  $this->setPort($port);
1306  }
1307 
1308 
1312  public function setDBPassword($password)
1313  {
1314  $this->setPassword($password);
1315  }
1316 
1317 
1321  public function setDBHost($host)
1322  {
1323  $this->setHost($host);
1324  }
1325 
1326 
1331  public function upper($a_exp)
1332  {
1333  return " UPPER(" . $a_exp . ") ";
1334  }
1335 
1336 
1341  public function lower($a_exp)
1342  {
1343  return " LOWER(" . $a_exp . ") ";
1344  }
1345 
1346 
1353  public function substr($a_exp, $a_pos = 1, $a_len = -1)
1354  {
1355  $lenstr = "";
1356  if ($a_len > -1) {
1357  $lenstr = ", " . $a_len;
1358  }
1359 
1360  return " SUBSTR(" . $a_exp . ", " . $a_pos . $lenstr . ") ";
1361  }
1362 
1363 
1369  public function prepareManip($query, $types = null)
1370  {
1371  return new ilPDOStatement($this->pdo->prepare($query));
1372  }
1373 
1374 
1381  public function prepare($query, $types = null, $result_types = null)
1382  {
1383  return new ilPDOStatement($this->pdo->prepare($query));
1384  }
1385 
1386 
1390  public function enableResultBuffering($a_status)
1391  {
1392  $this->pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, $a_status);
1393  }
1394 
1395 
1402  public function execute($stmt, $data = array())
1403  {
1407  $result = $stmt->execute($data);
1408  if ($result === false) {
1409  throw new ilDatabaseException(implode(', ', $stmt->errorInfo()), $stmt->errorCode());
1410  }
1411  return $stmt;
1412  }
1413 
1414 
1418  public function supportsSlave()
1419  {
1420  return false;
1421  }
1422 
1423 
1427  public function supportsFulltext()
1428  {
1429  return false;
1430  }
1431 
1432 
1436  public function supportsTransactions()
1437  {
1438  return false;
1439  }
1440 
1441 
1446  public function supports($feature)
1447  {
1448  switch ($feature) {
1449  case self::FEATURE_TRANSACTIONS:
1450  return $this->supportsTransactions();
1451  case self::FEATURE_FULLTEXT:
1452  return $this->supportsFulltext();
1453  case self::FEATURE_SLAVE:
1454  return $this->supportsSlave();
1455  default:
1456  return false;
1457  }
1458  }
1459 
1460 
1464  public function listTables()
1465  {
1466  return $this->manager->listTables();
1467  }
1468 
1469 
1474  public function loadModule($module)
1475  {
1476  switch ($module) {
1478  return $this->manager;
1480  return $this->reverse;
1481  }
1482  }
1483 
1484 
1488  public function getAllowedAttributes()
1489  {
1490  return $this->field_definition->getAllowedAttributes();
1491  }
1492 
1493 
1498  public function sequenceExists($sequence)
1499  {
1500  return in_array($sequence, $this->listSequences());
1501  }
1502 
1503 
1507  public function listSequences()
1508  {
1509  return $this->manager->listSequences();
1510  }
1511 
1512 
1518  public function concat(array $values, $allow_null = true)
1519  {
1520  return $this->manager->getQueryUtils()->concat($values, $allow_null);
1521  }
1522 
1523 
1528  protected function appendLimit($query)
1529  {
1530  if ($this->limit !== null && $this->offset !== null) {
1531  $query .= ' LIMIT ' . (int) $this->offset . ', ' . (int) $this->limit;
1532  $this->limit = null;
1533  $this->offset = null;
1534 
1535  return $query;
1536  }
1537 
1538  return $query;
1539  }
1540 
1541 
1548  public function locate($a_needle, $a_string, $a_start_pos = 1)
1549  {
1550  return $this->manager->getQueryUtils()->locate($a_needle, $a_string, $a_start_pos);
1551  }
1552 
1553 
1561  public function modifyTableColumn($table, $a_column, $a_attributes)
1562  {
1563  $def = $this->reverse->getTableFieldDefinition($table, $a_column);
1564 
1565  $analyzer = new ilDBAnalyzer($this);
1566  $best_alt = $analyzer->getBestDefinitionAlternative($def);
1567  $def = $def[$best_alt];
1568  unset($def["nativetype"]);
1569  unset($def["mdb2type"]);
1570 
1571  // check attributes
1572  $ilDBPdoFieldDefinition = $this->field_definition;
1573 
1574  $type = ($a_attributes["type"] ?? "" != "") ? $a_attributes["type"] : $def["type"];
1575  foreach ($def as $k => $v) {
1576  if ($k != "type" && !$ilDBPdoFieldDefinition->isAllowedAttribute($k, $type)) {
1577  unset($def[$k]);
1578  }
1579  }
1580  $check_array = $def;
1581  foreach ($a_attributes as $k => $v) {
1582  $check_array[$k] = $v;
1583  }
1584  if (!$this->checkColumnDefinition($check_array, true)) {
1585  throw new ilDatabaseException("ilDB Error: modifyTableColumn(" . $table . ", " . $a_column . ")");
1586  }
1587 
1588  foreach ($a_attributes as $a => $v) {
1589  $def[$a] = $v;
1590  }
1591 
1592  $a_attributes["definition"] = $def;
1593 
1594  $changes = array(
1595  "change" => array(
1596  $a_column => $a_attributes,
1597  ),
1598  );
1599 
1600  return $this->manager->alterTable($table, $changes, false);
1601  }
1602 
1603 
1608  public function free($a_st)
1609  {
1613  return $a_st->closeCursor();
1614  }
1615 
1616 
1623  public function renameTable($a_name, $a_new_name)
1624  {
1625  // check table name
1626  try {
1627  $this->checkTableName($a_new_name);
1628  } catch (ilDatabaseException $e) {
1629  throw new ilDatabaseException("ilDB Error: renameTable(" . $a_name . "," . $a_new_name . ")<br />" . $e->getMessage());
1630  }
1631 
1632  $this->manager->alterTable($a_name, ["name" => $a_new_name], false);
1633  if ($this->sequenceExists($a_name)) {
1634  $this->manager->alterTable($this->getSequenceName($a_name), ["name" => $this->getSequenceName($a_new_name)], false);
1635  }
1636  // The abstraction_progress is no longer used in ILIAS, see http://www.ilias.de/mantis/view.php?id=19513
1637  // $query = "UPDATE abstraction_progress " . "SET table_name = " . $this->quote($a_new_name, 'text') . " " . "WHERE table_name = "
1638  // . $this->quote($a_name, 'text');
1639  // $this->pdo->query($query);
1640 
1641  return true;
1642  }
1643 
1644 
1650  public function checkTableName($a_name)
1651  {
1652  return $this->field_definition->checkTableName($a_name);
1653  }
1654 
1655 
1660  public static function isReservedWord($a_word)
1661  {
1662  global $DIC;
1663  $ilDBPdoMySQLFieldDefinition = new ilDBPdoMySQLFieldDefinition($DIC->database());
1664 
1665  return $ilDBPdoMySQLFieldDefinition->isReserved($a_word);
1666  }
1667 
1668 
1673  public function beginTransaction()
1674  {
1675  if (!$this->supports(self::FEATURE_TRANSACTIONS)) {
1676  throw new ilDatabaseException("ilDB::beginTransaction: Transactions are not supported.");
1677  }
1678 
1679  return $this->pdo->beginTransaction();
1680  }
1681 
1682 
1687  public function commit()
1688  {
1689  if (!$this->supports(self::FEATURE_TRANSACTIONS)) {
1690  throw new ilDatabaseException("ilDB::beginTransaction: Transactions are not supported.");
1691  }
1692 
1693  return $this->pdo->commit();
1694  }
1695 
1696 
1701  public function rollback()
1702  {
1703  if (!$this->supports(self::FEATURE_TRANSACTIONS)) {
1704  throw new ilDatabaseException("ilDB::beginTransaction: Transactions are not supported.");
1705  }
1706 
1707  return $this->pdo->rollBack();
1708  }
1709 
1710 
1716  public function dropIndex($a_table, $a_name = "i1")
1717  {
1718  return $this->manager->dropIndex($a_table, $a_name);
1719  }
1720 
1721 
1726  {
1727  $this->storage_engine = $storage_engine;
1728  }
1729 
1730 
1734  public function getStorageEngine()
1735  {
1736  return $this->storage_engine;
1737  }
1738 
1739 
1746  public function queryCol($query, $type = PDO::FETCH_ASSOC, $colnum = 0)
1747  {
1748  switch ($type) {
1750  $type = PDO::FETCH_ASSOC;
1751  break;
1753  $type = PDO::FETCH_OBJ;
1754  break;
1755  default:
1756  $type = PDO::FETCH_ASSOC;
1757  break;
1758  }
1759 
1760  return $this->pdo->query($query, PDO::FETCH_ASSOC)->fetchAll(PDO::FETCH_COLUMN, $colnum);
1761  }
1762 
1763 
1770  public function queryRow($query, $types = null, $fetchmode = ilDBConstants::FETCHMODE_DEFAULT)
1771  {
1772  switch ($fetchmode) {
1774  $type = PDO::FETCH_ASSOC;
1775  break;
1777  $type = PDO::FETCH_OBJ;
1778  break;
1779  default:
1780  $type = PDO::FETCH_ASSOC;
1781  break;
1782  }
1783 
1784  return $this->pdo->query($query, $type)->fetch();
1785  }
1786 
1787 
1792  public function getServerVersion($native = false)
1793  {
1794  return $this->pdo->query('SELECT VERSION()')->fetchColumn();
1795  }
1796 
1797 
1803  public function escape($value, $escape_wildcards = false)
1804  {
1805  return $value;
1806  }
1807 
1808 
1813  public function escapePattern($text)
1814  {
1815  return $text;
1816  }
1817 
1818 
1824  {
1825  return array();
1826  }
1827 
1828 
1833  {
1834  return array();
1835  }
1836 
1837 
1841  public function supportsCollationMigration()
1842  {
1843  return false;
1844  }
1845 
1846 
1850  public function supportsEngineMigration()
1851  {
1852  return false;
1853  }
1854 
1855 
1861  public function checkIndexName($name)
1862  {
1863  return $this->getFieldDefinition()->checkIndexName($name);
1864  }
1865 
1866 
1874  public function addUniqueConstraint($table, $fields, $name = "con")
1875  {
1876  assert(is_array($fields));
1878 
1879  // check index name
1880  if (!$this->checkIndexName($name)) {
1881  throw new ilDatabaseException("ilDB Error: addUniqueConstraint(" . $table . "," . $name . ")");
1882  }
1883 
1884  $fields_corrected = array();
1885  foreach ($fields as $f) {
1886  $fields_corrected[$f] = array();
1887  }
1888  $definition = array(
1889  'unique' => true,
1890  'fields' => $fields_corrected,
1891  );
1892 
1893  return $manager->createConstraint($table, $this->constraintName($table, $name), $definition);
1894  }
1895 
1896 
1902  public function dropUniqueConstraint($a_table, $a_name = "con")
1903  {
1904  return $this->manager->dropConstraint($a_table, $this->constraintName($a_table, $a_name), false);
1905  }
1906 
1907 
1913  public function dropUniqueConstraintByFields($a_table, $a_fields)
1914  {
1915  $analyzer = new ilDBAnalyzer();
1916  $cons = $analyzer->getConstraintsInformation($a_table);
1917  foreach ($cons as $c) {
1918  if ($c["type"] == "unique" && count($a_fields) == count($c["fields"])) {
1919  $all_in = true;
1920  foreach ($a_fields as $f) {
1921  if (!isset($c["fields"][$f])) {
1922  $all_in = false;
1923  }
1924  }
1925  if ($all_in) {
1926  return $this->dropUniqueConstraint($a_table, $c['name']);
1927  }
1928  }
1929  }
1930 
1931  return false;
1932  }
1933 
1934 
1938  public function getLastInsertId()
1939  {
1940  return $this->pdo->lastInsertId();
1941  }
1942 
1943 
1947  public function buildAtomQuery()
1948  {
1949  return new ilAtomQueryLock($this);
1950  }
1951 
1952 
1958  public function uniqueConstraintExists($table, array $fields)
1959  {
1960  $analyzer = new ilDBAnalyzer();
1961  $cons = $analyzer->getConstraintsInformation($table);
1962  foreach ($cons as $c) {
1963  if ($c["type"] == "unique" && count($fields) == count($c["fields"])) {
1964  $all_in = true;
1965  foreach ($fields as $f) {
1966  if (!isset($c["fields"][$f])) {
1967  $all_in = false;
1968  }
1969  }
1970  if ($all_in) {
1971  return true;
1972  }
1973  }
1974  }
1975 
1976  return false;
1977  }
1978 
1979 
1984  public function dropPrimaryKey($table_name)
1985  {
1986  return $this->manager->dropConstraint($table_name, "PRIMARY", true);
1987  }
1988 
1989 
1994  public function executeMultiple($stmt, $a_data)
1995  {
1996  for ($i = 0, $j = count($a_data); $i < $j; $i++) {
1997  $stmt->execute($a_data[$i]);
1998  }
1999  }
2000 
2001 
2007  public function fromUnixtime($a_expr, $a_to_text = true)
2008  {
2009  return "FROM_UNIXTIME(" . $a_expr . ")";
2010  }
2011 
2012 
2016  public function unixTimestamp()
2017  {
2018  return "UNIX_TIMESTAMP()";
2019  }
2020 
2021 
2037  public function autoExecute($tablename, $fields, $mode = ilDBConstants::AUTOQUERY_INSERT, $where = false)
2038  {
2039  $fields_values = (array) $fields;
2040  if ($mode == ilDBConstants::AUTOQUERY_INSERT) {
2041  if (!empty($fields_values)) {
2042  $keys = $fields_values;
2043  } else {
2044  $keys = array();
2045  }
2046  } else {
2047  $keys = array_keys($fields_values);
2048  }
2049  $params = array_values($fields_values);
2050  if (empty($params)) {
2051  $query = $this->buildManipSQL($tablename, $keys, $mode, $where);
2052  $result = $this->pdo->query($query);
2053  } else {
2054  $stmt = $this->autoPrepare($tablename, $keys, $mode, $where, $types, $result_types);
2055  $this->execute($stmt);
2056  $this->free($stmt);
2057  $result = $stmt;
2058  }
2059 
2060  return $result;
2061  }
2062 
2063 
2073  protected function autoPrepare($table, $table_fields, $mode = ilDBConstants::AUTOQUERY_INSERT, $where = false, $types = null, $result_types = ilDBConstants::PREPARE_MANIP)
2074  {
2075  $query = $this->buildManipSQL($table, $table_fields, $mode, $where);
2076 
2077  return $this->prepare($query, $types, $result_types);
2078  }
2079 
2080 
2089  protected function buildManipSQL($table, $table_fields, $mode, $where = false)
2090  {
2091  if ($this->options['quote_identifier']) {
2092  $table = $this->quoteIdentifier($table);
2093  }
2094 
2095  if (!empty($table_fields) && $this->options['quote_identifier']) {
2096  foreach ($table_fields as $key => $field) {
2097  $table_fields[$key] = $this->quoteIdentifier($field);
2098  }
2099  }
2100 
2101  if ($where !== false && !is_null($where)) {
2102  if (is_array($where)) {
2103  $where = implode(' AND ', $where);
2104  }
2105  $where = ' WHERE ' . $where;
2106  }
2107 
2108  switch ($mode) {
2110  if (empty($table_fields)) {
2111  throw new ilDatabaseException('Insert requires table fields');
2112  }
2113  $cols = implode(', ', $table_fields);
2114  $values = '?' . str_repeat(', ?', (count($table_fields) - 1));
2115 
2116  return 'INSERT INTO ' . $table . ' (' . $cols . ') VALUES (' . $values . ')';
2117  break;
2119  if (empty($table_fields)) {
2120  throw new ilDatabaseException('Update requires table fields');
2121  }
2122  $set = implode(' = ?, ', $table_fields) . ' = ?';
2123  $sql = 'UPDATE ' . $table . ' SET ' . $set . $where;
2124 
2125  return $sql;
2126  break;
2128  $sql = 'DELETE FROM ' . $table . $where;
2129 
2130  return $sql;
2131  break;
2133  $cols = !empty($table_fields) ? implode(', ', $table_fields) : '*';
2134  $sql = 'SELECT ' . $cols . ' FROM ' . $table . $where;
2135 
2136  return $sql;
2137  break;
2138  }
2139 
2140  throw new ilDatabaseException('Syntax error');
2141  }
2142 
2143 
2148  public function getDBVersion()
2149  {
2150  $d = $this->fetchObject($this->query("SELECT VERSION() AS version"));
2151 
2152  return ($d->version ? $d->version : 'Unknown');
2153  }
2154 
2155 
2160  {
2161  if (!$this->doesCollationSupportMB4Strings()) {
2162  $query_replaced = preg_replace(
2163  '/[\x{10000}-\x{10FFFF}]/u',
2165  $query
2166  );
2167  if (!empty($query_replaced)) {
2168  return $query_replaced;
2169  }
2170  }
2171 
2172  return $query;
2173  }
2174 
2179  {
2180  return false;
2181  }
2182 
2183 
2187  public function groupConcat($a_field_name, $a_seperator = ",", $a_order = null)
2188  {
2189  return $this->manager->getQueryUtils()->groupConcat($a_field_name, $a_seperator, $a_order);
2190  }
2191 
2195  public function cast($a_field_name, $a_dest_type)
2196  {
2197  return $this->manager->getQueryUtils()->cast($a_field_name, $a_dest_type);
2198  }
2199 }
sanitizeMB4StringIfNotSupported($query)
string to sanitize, all MB4-Characters like emojis will re replaced with ???string sanitized query ...
autoPrepare($table, $table_fields, $mode=ilDBConstants::AUTOQUERY_INSERT, $where=false, $types=null, $result_types=ilDBConstants::PREPARE_MANIP)
upper($a_exp)
supportsTransactions()
setPassword($password)
useSlave($bool)
addPrimaryKey($table_name, $primary_keys)
checkTableName($a_name)
setFieldDefinition($field_definition)
escapePattern($text)
$data
Definition: storeScorm.php:23
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())
$type
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:89
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)
modifyTableColumn($table, $a_column, $a_attributes)
const FEATURE_FULLTEXT
Class ilDatabaseException.
initHelpers()
executeMultiple($stmt, $a_data)
dropFulltextIndex($a_table, $a_name)
Drop fulltext index.
checkColumnName($a_name)
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.
if($format !==null) $name
Definition: metadata.php:230
autoExecute($tablename, $fields, $mode=ilDBConstants::AUTOQUERY_INSERT, $where=false)
Generate an insert, update or delete query and call prepare() and execute() on it.
dropTable($table_name, $error_if_not_existing=true)
checkTableColumns($a_cols)
queryRow($query, $types=null, $fetchmode=ilDBConstants::FETCHMODE_DEFAULT)
const FEATURE_SLAVE
foreach($_POST as $key=> $value) $res
quoteIdentifier($identifier, $check_option=false)
$keys
Definition: metadata.php:187
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)
tableColumnExists($table_name, $column_name)
dropPrimaryKey($table_name)
getLastErrorCode()
supportsEngineMigration()
setLimit($limit, $offset=0)
Set the Limit for the next Query.
setDbname($dbname)
$query
lower($a_exp)
dropTableColumn($table_name, $column_name)
dropIndexByFields($table_name, $fields)
checkColumn($a_col, $a_def)
groupConcat($a_field_name, $a_seperator=",", $a_order=null)
string
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
$DIC
Definition: xapitoken.php:46
enableResultBuffering($a_status)
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
performance measurement class
insert($table_name, $values)
setDBPassword($password)
cast($a_field_name, $a_dest_type)
string;
Component logger with individual log levels by component id.
This class gives all kind of DB information using the database 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")
$cols
Definition: xhr_table.php:11
migrateAllTablesToEngine($engine=ilDBConstants::MYSQL_ENGINE_INNODB)
INIFile Parser.
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)
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
getIndexName($index_name_base)
$i
Definition: metadata.php:24
checkColumnDefinition($a_def, $a_modify_mode=false)