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
4require_once("./Services/Database/classes/PDO/class.ilPDOStatement.php");
5require_once("./Services/Database/classes/QueryUtils/class.ilMySQLQueryUtils.php");
6require_once('./Services/Database/classes/PDO/Manager/class.ilDBPdoManager.php');
7require_once('./Services/Database/classes/PDO/Reverse/class.ilDBPdoReverse.php');
8require_once('./Services/Database/interfaces/interface.ilDBInterface.php');
9require_once('./Services/Database/classes/class.ilDBConstants.php');
10require_once('./Services/Database/interfaces/interface.ilDBLegacyInterface.php');
11
18abstract 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;
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) {
1387 return $this->supportsTransactions();
1389 return $this->supportsFulltext();
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;
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}
sprintf('%.4f', $callTime)
$column
Definition: 39dropdown.php:62
for($col=0; $col< 50; $col++) $d
$result
if(! $in) $columns
Definition: Utf8Test.php:45
An exception for terminatinating execution or to throw for unit testing.
Class ilAtomQueryLock.
performance measurement class
This class gives all kind of DB information using the MDB2 manager and reverse module.
Class ilDBPdoMySQLFieldDefinition.
Class pdoDB.
upper($a_exp)
supportsTransactions()
update($table_name, $columns, $where)
setUsername($username)
connect($return_false_for_error=false)
renameTable($a_name, $a_new_name)
dropUniqueConstraintByFields($a_table, $a_fields)
concat(array $values, $allow_null=true)
dropPrimaryKey($table_name)
queryRow($query, $types=null, $fetchmode=ilDBConstants::FETCHMODE_DEFAULT)
setDBType($type)
loadModule($module)
sanitizeMB4StringIfNotSupported($query)
string sanitized query
createSequence($table_name, $start=1)
indexExistsByFields($table_name, $fields)
getFieldDefinition()
equals($columns, $value, $type, $emptyOrNull=false)
escape($value, $escape_wildcards=false)
lockTables($tables)
query($query)
quote($value, $type=null)
setStorageEngine($storage_engine)
like($column, $type, $value="?", $case_insensitive=true)
setDBHost($host)
setFieldDefinition($field_definition)
in($field, $values, $negate=false, $type="")
setDBPassword($password)
prepare($query, $types=null, $result_types=null)
prepareManip($query, $types=null)
addIndex($table_name, $fields, $index_name='', $fulltext=false)
setDBUser($user)
dropIndex($a_table, $a_name="i1")
getLastErrorCode()
setPort($port)
supportsEngineMigration()
checkIndexName($name)
dropUniqueConstraint($a_table, $a_name="con")
getPrimaryKeyIdentifier()
getAllowedAttributes()
array
setPassword($password)
checkTableName($a_name)
executeMultiple($stmt, $a_data)
isFulltextIndex($a_table, $a_name)
Is index a fulltext index?
queryF($query, $types, $values)
getSequenceName($table_name)
tableExists($table_name)
createTable($table_name, $fields, $drop_table=false, $ignore_erros=false)
autoExecute($tablename, $fields, $mode=ilDBConstants::MDB2_AUTOQUERY_INSERT, $where=false)
Generate an insert, update or delete query and call prepare() and execute() on it.
initFromIniFile($tmpClientIniFile=null)
addUniqueConstraint($table, $fields, $name="con")
getAdditionalAttributes()
supports($feature)
checkColumnName($a_name)
appendLimit($query)
const FEATURE_SLAVE
supportsCollationMigration()
@inheritDoc
manipulateF($query, $types, $values)
checkTableColumns($a_cols)
replace($table, $primaryKeys, $otherColumns)
Replace into method.
static isReservedWord($a_word)
manipulate($query)
numRows($query_result)
checkColumn($a_col, $a_def)
addFulltextIndex($a_table, $a_fields, $a_name="in")
buildManipSQL($table, $table_fields, $mode, $where=false)
uniqueConstraintExists($table, array $fields)
locate($a_needle, $a_string, $a_start_pos=1)
setDBPort($port)
constraintName($a_table, $a_constraint)
Determine contraint name by table name and constraint name.
escapePattern($text)
dropTableColumn($table_name, $column_name)
migrateAllTablesToEngine($engine=ilDBConstants::MYSQL_ENGINE_INNODB)
fetchAssoc($query_result)
fromUnixtime($a_expr, $a_to_text=true)
substr($a_exp, $a_pos=1, $a_len=-1)
getIndexName($index_name_base)
addPrimaryKey($table_name, $primary_keys)
dropTable($table_name, $error_if_not_existing=true)
doesCollationSupportMB4Strings()
@inheritDoc
createDatabase($a_name, $a_charset="utf8", $a_collation="")
const FEATURE_TRANSACTIONS
sequenceExists($sequence)
groupConcat($a_field_name, $a_seperator=",", $a_order=NULL)
string
renameTableColumn($table_name, $column_old_name, $column_new_name)
getServerVersion($native=false)
dropSequence($table_name)
autoPrepare($table, $table_fields, $mode=ilDBConstants::MDB2_AUTOQUERY_INSERT, $where=false, $types=null, $result_types=ilDBConstants::MDB2_PREPARE_MANIP)
insert($table_name, $values)
tableColumnExists($table_name, $column_name)
cast($a_field_name, $a_dest_type)
string;
lower($a_exp)
const FEATURE_FULLTEXT
setDbname($dbname)
quoteIdentifier($identifier, $check_option=false)
checkColumnDefinition($a_def, $a_modify_mode=false)
setCharset($charset)
dropFulltextIndex($a_table, $a_name)
Drop fulltext index.
nextId($table_name)
enableResultBuffering($a_status)
setLimit($limit, $offset=0)
Set the Limit for the next Query.
modifyTableColumn($table, $a_column, $a_attributes)
addTableColumn($table_name, $column_name, $attributes)
initHelpers()
migrateAllTablesToCollation($collation=ilDBConstants::MYSQL_COLLATION_UTF8MB4)
@inheritDoc
fetchObject($query_result)
setHost($host)
dropIndexByFields($table_name, $fields)
queryCol($query, $type=PDO::FETCH_ASSOC, $colnum=0)
useSlave($bool)
Class ilDatabaseException.
INIFile Parser.
logging
Definition: class.ilLog.php:19
Class ilPDOStatement is a Wrapper Class for PDOStatement.
$text
$r
Definition: example_031.php:79
$params
Definition: example_049.php:96
$info
Definition: example_052.php:80
global $ilBench
Definition: ilias.php:18
Interface ilDBInterface.
static getReservedWords()
Get reserved words.
execute($stmt, $data=array())
fetchAll($query_result, $fetch_mode=ilDBConstants::FETCHMODE_ASSOC)
Interface ilDBPdoInterface.
global $ilDB
if(!is_array($argv)) $options
global $DIC
$engine
Definition: workflow.php:90