18 protected $target_encoding =
'UTF-8';
22 protected $whitelist = array();
26 protected $blacklist = array();
30 protected $tables = array();
34 protected $filter = array();
40 public function __construct() {
46 include_once(
"./Services/Database/classes/class.ilDBAnalyzer.php");
49 $this->allowed_attributes =
$ilDB->getAllowedAttributes();
56 public static function lookupAbstractedTables() {
59 $query =
"SELECT DISTINCT(table_name) FROM abstraction_progress ";
69 $abs_tables = array_merge(
$names, array(
71 'acc_user_access_key',
74 'qpl_question_orderinghorizontal',
75 'qpl_question_fileupload',
78 'style_template_class',
82 'page_editor_settings',
103 'qpl_qst_textsubset',
142 public function setTargetEncoding($a_encoding) {
143 $this->target_encoding = $a_encoding;
152 public function getTargetEncoding() {
153 return $this->target_encoding;
163 public function setBlackList($a_blacklist) {
164 $this->blacklist = $a_blacklist;
173 public function getBlackList() {
174 return $this->blacklist;
185 public function setWhiteList($a_whitelist) {
186 $this->whitelist = $a_whitelist;
195 public function getWhiteList() {
196 return $this->whitelist;
204 public function setFilter($a_filter, $a_value) {
205 $this->filter[$a_filter] = $a_value;
212 public function getTables() {
213 $r = $this->manager->listTables();
216 return $this->tables;
223 public function checkProcessing($a_table) {
225 if (in_array($a_table, $this->blacklist)) {
230 if (count($this->whitelist) > 0 && !in_array($a_table, $this->whitelist)) {
238 protected function openFile($a_path) {
240 $file = fopen($a_path,
"w");
241 $start .=
"\t" .
'global $ilDB;' .
"\n\n";
247 $file = fopen($a_path,
"w");
248 $start =
'<?php' .
"\n" .
'function setupILIASDatabase()' .
"\n{\n";
249 $start .=
"\t" .
'global $ilDB;' .
"\n\n";
256 protected function closeFile($fp) {
275 public function buildDBGenerationScript($a_filename =
"") {
276 if (@is_dir($a_filename)) {
280 $isDirectory =
false;
285 if ($a_filename !=
"" and !$isDirectory) {
286 $file = fopen($a_filename,
"w");
288 $start =
'<?php' .
"\n" .
'function setupILIASDatabase()' .
"\n{\n";
289 $start .=
"\t" .
'global $ilDB;' .
"\n\n";
291 } elseif ($isDirectory) {
299 foreach ($this->tables as $table) {
300 if ($this->checkProcessing($table)) {
301 if ($a_filename !=
"") {
306 $file = $this->openFile(
$path .
'/' . $table);
310 $this->buildCreateTableStatement($table,
$file);
313 $this->buildAddPrimaryKeyStatement($table,
$file);
316 $this->buildAddIndexStatements($table,
$file);
319 $this->buildAddUniqueConstraintStatements($table,
$file);
322 $this->buildCreateSequenceStatement($table,
$file);
324 if (in_array($table, array(
'usr_session_stats',
'usr_session_raw',
'il_plugin'))) {
330 $this->buildInsertStatement($table,
$path);
331 #$this->buildInsertStatementsXML($table,$path);
333 $this->buildInsertStatements($table,
$file);
337 $this->closeFile(
$file);
340 if ($a_filename !=
"") {
341 echo
"<br><b>missing: " . $table .
"</b>";
348 $this->buildSingularSequenceStatement(
$file);
350 if ($a_filename ==
"") {
352 } elseif (!$isDirectory) {
367 public function buildCreateTableStatement($a_table, $a_file =
"") {
368 $fields = $this->analyzer->getFieldInformation($a_table,
true);
370 $create_st =
"\n\n//\n// " . $a_table .
"\n//\n";
371 $create_st .=
'$fields = array (' .
"\n";
373 foreach ($fields as $f => $def) {
375 $create_st .=
"\t" . $f_sep .
'"' . $f .
'" => array (' .
"\n";
378 foreach ($def as $k => $v) {
379 if ($k !=
"nativetype" && $k !=
"alt_types" && $k !=
"autoincrement" && !is_null($v)) {
384 $v = $v ?
"true" :
"false";
395 $create_st .=
"\t\t" . $a_sep .
'"' . $k .
'" => ' . $v .
"\n";
399 $create_st .=
"\t" .
')' .
"\n";
401 $create_st .=
');' .
"\n";
402 $create_st .=
'$ilDB->createTable("' . $a_table .
'", $fields);' .
"\n";
407 fwrite($a_file, $create_st);
418 public function buildAddPrimaryKeyStatement($a_table, $a_file =
"") {
419 $pk = $this->analyzer->getPrimaryKeyInformation($a_table);
421 if (is_array($pk[
"fields"]) && count($pk[
"fields"]) > 0) {
422 $pk_st =
"\n" .
'$pk_fields = array(';
424 foreach ($pk[
"fields"] as $f => $pos) {
425 $pk_st .= $sep .
'"' . $f .
'"';
429 $pk_st .=
'$ilDB->addPrimaryKey("' . $a_table .
'", $pk_fields);' .
"\n";
434 fwrite($a_file, $pk_st);
446 public function buildAddIndexStatements($a_table, $a_file =
"") {
447 $ind = $this->analyzer->getIndicesInformation($a_table,
true);
449 if (is_array($ind)) {
450 foreach ($ind as $i) {
451 if ($i[
"fulltext"]) {
456 $in_st =
"\n" .
'$in_fields = array(';
458 foreach ($i[
"fields"] as $f => $pos) {
459 $in_st .= $sep .
'"' . $f .
'"';
463 $in_st .=
'$ilDB->addIndex("' . $a_table .
'", $in_fields, "' . $i[
"name"] .
'"' . $ft .
');' .
"\n";
468 fwrite($a_file, $in_st);
481 public function buildAddUniqueConstraintStatements($a_table, $a_file =
"") {
482 $con = $this->analyzer->getConstraintsInformation($a_table,
true);
484 if (is_array($con)) {
485 foreach ($con as $i) {
486 $in_st =
"\n" .
'$in_fields = array(';
488 foreach ($i[
"fields"] as $f => $pos) {
489 $in_st .= $sep .
'"' . $f .
'"';
493 $in_st .=
'$ilDB->addUniqueConstraint("' . $a_table .
'", $in_fields, "' . $i[
"name"] .
'");' .
"\n";
498 fwrite($a_file, $in_st);
511 public function buildCreateSequenceStatement($a_table, $a_file =
"") {
512 $seq = $this->analyzer->hasSequence($a_table);
513 if ($seq !==
false) {
514 $seq_st =
"\n" .
'$ilDB->createSequence("' . $a_table .
'", ' . (int)$seq .
');' .
"\n";
519 fwrite($a_file, $seq_st);
530 public function buildSingularSequenceStatement($a_file =
"") {
531 $r = $this->manager->listSequences();
533 foreach (
$r as $seq) {
534 if (!in_array($seq, $this->tables)) {
536 if ($seq ==
"sahs_sc13_seq") {
540 $create_st =
"\n" .
'$ilDB->createSequence("' . $seq .
'");' .
"\n";
545 fwrite($a_file, $create_st);
560 public function buildInsertStatement($a_table, $a_basedir) {
563 $ilLog->write(
'Starting export of:' . $a_table);
565 $set = $this->il_db->query(
"SELECT * FROM " . $this->il_db->quoteIdentifier($a_table));
569 mkdir($a_basedir .
'/' . $a_table .
'_inserts', fileperms($a_basedir));
572 while ($rec = $this->il_db->fetchAssoc($set)) {
574 foreach ($rec as $f => $v) {
575 if ($this->
fields[$f][
'type'] ==
'text' and $this->
fields[$f][
'length'] >= 1000) {
576 $v = $this->shortenText($a_table, $f, $v, $this->
fields[$f][
'length']);
580 $this->
fields[$f][
'type'],
585 $rows[$a_table][
$row ++] = $values;
588 $ilLog->write(
'Writing insert statements after 1000 lines...');
589 $fp = fopen($a_basedir .
'/' . $a_table .
'_inserts/' . $filenum ++ .
'.data',
'w');
590 fwrite($fp, serialize((array)$rows));
598 $fp = fopen($a_basedir .
'/' . $a_table .
'_inserts/' . $filenum ++ .
'.data',
'w');
599 fwrite($fp, serialize((array)$rows) .
"\n");
603 $ilLog->write(
'Finished export of: ' . $a_table);
604 if (function_exists(
'memory_get_usage')) {
618 public function buildInsertStatementsXML($a_table, $a_basedir) {
621 include_once
'./Services/Xml/classes/class.ilXmlWriter.php';
623 $w->xmlStartTag(
'Table', array(
'name' => $a_table ));
625 $set = $this->il_db->query(
"SELECT * FROM " . $this->il_db->quoteIdentifier($a_table));
628 while ($rec = $this->il_db->fetchAssoc($set)) {
629 #$ilLog->write('Num: '.$num++);
630 $w->xmlStartTag(
'Row');
635 foreach ($rec as $f => $v) {
636 if ($this->
fields[$f][
'type'] ==
'text' and $this->
fields[$f][
'length'] >= 1000) {
637 $v = $this->shortenText($a_table, $f, $v, $this->
fields[$f][
'length']);
640 $w->xmlElement(
'Value', array(
642 'type' => $this->
fields[$f][
'type'],
646 $w->xmlEndTag(
'Row');
648 $w->xmlEndTag(
'Table');
650 $w->xmlDumpFile($a_basedir .
'/' . $a_table .
'.xml',
false);
660 public function buildInsertStatements($a_table, $a_file =
"") {
661 if ($a_table ==
"lng_data") {
665 $set = $this->il_db->query(
"SELECT * FROM " . $this->il_db->quoteIdentifier($a_table));
668 while ($rec = $this->il_db->fetchAssoc($set)) {
673 foreach ($rec as $f => $v) {
675 $types[] =
'"' . $this->
fields[$f][
"type"] .
'"';
676 $v = str_replace(
'\\',
'\\\\', $v);
677 $values[] =
"'" . str_replace(
"'",
"\'", $v) .
"'";
678 $i_str[] =
"'" . $f .
"' => array('" . $this->
fields[$f][
"type"] .
"', '" . str_replace(
"'",
"\'", $v) .
"')";
680 $fields_str =
"(" . implode($fields,
",") .
")";
681 $types_str =
"array(" . implode($types,
",") .
")";
682 $values_str =
"array(" . implode($values,
",") .
")";
683 $ins_st =
"\n" .
'$ilDB->insert("' . $a_table .
'", array(' .
"\n";
684 $ins_st .= implode($i_str,
", ") .
"));\n";
692 fwrite($a_file, $ins_st);
704 public function getHTMLOverview($a_filename =
"") {
705 $tpl =
new ilTemplate(
"tpl.db_overview.html",
true,
true,
"Services/Database");
709 foreach ($this->tables as $table) {
710 if ($this->checkProcessing($table)) {
712 if ($this->addTableToOverview($table,
$tpl, $cnt)) {
718 $tpl->setVariable(
"TXT_TITLE",
"ILIAS Abstract DB Tables (" .
ILIAS_VERSION .
")");
720 if ($a_filename ==
"") {
729 public function addTableToOverview($a_table, $a_tpl, $a_cnt) {
730 $fields = $this->analyzer->getFieldInformation($a_table);
731 $indices = $this->analyzer->getIndicesInformation($a_table);
732 $constraints = $this->analyzer->getConstraintsInformation($a_table);
733 $pk = $this->analyzer->getPrimaryKeyInformation($a_table);
734 $auto = $this->analyzer->getAutoIncrementField($a_table);
735 $has_sequence = $this->analyzer->hasSequence($a_table);
738 if (isset($this->filter[
"has_sequence"])) {
739 if ((!$has_sequence && $auto ==
"" && $this->filter[
"has_sequence"])
740 || (($has_sequence || $auto !=
"") && !$this->filter[
"has_sequence"])
747 $indices_output =
false;
748 if (is_array($indices) && count($indices) > 0 && !$this->filter[
"skip_indices"]) {
749 foreach ($indices as $index => $def) {
751 foreach ($def[
"fields"] as $f => $pos) {
754 $a_tpl->setCurrentBlock(
"index");
755 $a_tpl->setVariable(
"VAL_INDEX", $def[
"name"]);
756 $a_tpl->setVariable(
"VAL_FIELDS", implode($f2,
", "));
757 $a_tpl->parseCurrentBlock();
758 $indices_output =
true;
760 $a_tpl->setCurrentBlock(
"index_table");
761 $a_tpl->parseCurrentBlock();
765 $constraints_output =
false;
766 if (is_array($constraints) && count($constraints) > 0 && !$this->filter[
"skip_constraints"]) {
767 foreach ($constraints as $index => $def) {
769 foreach ($def[
"fields"] as $f => $pos) {
772 $a_tpl->setCurrentBlock(
"constraint");
773 $a_tpl->setVariable(
"VAL_CONSTRAINT", $def[
"name"]);
774 $a_tpl->setVariable(
"VAL_CTYPE", $def[
"type"]);
775 $a_tpl->setVariable(
"VAL_CFIELDS", implode($f2,
", "));
776 $a_tpl->parseCurrentBlock();
777 $constraints_output =
true;
779 $a_tpl->setCurrentBlock(
"constraint_table");
780 $a_tpl->parseCurrentBlock();
784 $fields_output =
false;
785 foreach ($fields as $field => $def) {
787 if (isset($this->filter[
"alt_types"])) {
788 if (($def[
"alt_types"] ==
"" && $this->filter[
"alt_types"])
789 || ($def[
"alt_types"] !=
"" && !$this->filter[
"alt_types"])
794 if (isset($this->filter[
"type"])) {
795 if ($def[
"type"] != $this->filter[
"type"]) {
799 if (isset($this->filter[
"nativetype"])) {
800 if ($def[
"nativetype"] != $this->filter[
"nativetype"]) {
804 if (isset($this->filter[
"unsigned"])) {
805 if ($def[
"unsigned"] != $this->filter[
"unsigned"]) {
810 $a_tpl->setCurrentBlock(
"field");
811 if (empty($pk[
"fields"][$field])) {
812 $a_tpl->setVariable(
"VAL_FIELD", strtolower($field));
814 $a_tpl->setVariable(
"VAL_FIELD",
"<u>" . strtolower($field) .
"</u>");
816 $a_tpl->setVariable(
"VAL_TYPE", $def[
"type"]);
817 $a_tpl->setVariable(
"VAL_LENGTH", (!is_null($def[
"length"])) ? $def[
"length"] :
" ");
819 if (strtolower($def[
"default"]) ==
"current_timestamp") {
821 unset($def[
"default"]);
824 $a_tpl->setVariable(
"VAL_DEFAULT", (!is_null($def[
"default"])) ? $def[
"default"] :
" ");
825 $a_tpl->setVariable(
"VAL_NOT_NULL", (!is_null($def[
"notnull"])) ? (($def[
"notnull"]) ?
"true" :
"false") :
" ");
826 $a_tpl->setVariable(
"VAL_FIXED", (!is_null($def[
"fixed"])) ? (($def[
"fixed"]) ?
"true" :
"false") :
" ");
827 $a_tpl->setVariable(
"VAL_UNSIGNED", (!is_null($def[
"unsigned"])) ? (($def[
"unsigned"]) ?
"true" :
"false") :
" ");
828 $a_tpl->setVariable(
"VAL_ALTERNATIVE_TYPES", ($def[
"alt_types"] !=
"") ? $def[
"alt_types"] :
" ");
829 $a_tpl->setVariable(
"VAL_NATIVETYPE", ($def[
"nativetype"] !=
"") ? $def[
"nativetype"] :
" ");
830 $a_tpl->parseCurrentBlock();
831 $fields_output =
true;
834 if ($fields_output) {
835 $a_tpl->setCurrentBlock(
"field_table");
836 $a_tpl->parseCurrentBlock();
840 if ($indices_output || $fields_output || $constraints_output) {
841 $a_tpl->setCurrentBlock(
"table");
842 $a_tpl->setVariable(
"TXT_TABLE_NAME", strtolower($a_table));
843 if ($has_sequence || $auto !=
"") {
844 $a_tpl->setVariable(
"TXT_SEQUENCE",
"Has Sequence");
846 $a_tpl->setVariable(
"TXT_SEQUENCE",
"No Sequence");
848 $a_tpl->setVariable(
"VAL_CNT", (
int)$a_cnt);
849 $a_tpl->parseCurrentBlock();
867 protected function shortenText($table, $field, $a_value, $a_size) {
870 if ($this->getTargetEncoding() ==
'UTF-8') {
874 $shortened = mb_convert_encoding($a_value, $this->getTargetEncoding(),
'UTF-8');
876 include_once
'./Services/Utilities/classes/class.ilStr.php';
879 $shortened = mb_convert_encoding($shortened,
'UTF-8', $this->getTargetEncoding());
881 if (strlen($a_value) != strlen($shortened)) {
882 $ilLog->write(
'Table : ' . $table);
883 $ilLog->write(
'Field : ' . $field);
884 $ilLog->write(
'Type : ' . $this->
fields[$field][
'type']);
885 $ilLog->write(
'Length : ' . $this->
fields[$field][
'length']);
886 $ilLog->write(
'Before : ' . $a_value);
887 $ilLog->write(
'Shortened : ' . $shortened);
888 $ilLog->write(
'Strlen Before: ' . strlen($a_value));
889 $ilLog->write(
'Strlen After : ' . strlen($shortened));
memory_get_usage(true)/1024/1024)
An exception for terminatinating execution or to throw for unit testing.
This class gives all kind of DB information using the MDB2 manager and reverse module.
static shortenText($a_string, $a_start_pos, $a_num_bytes, $a_encoding='UTF-8')
Shorten text to the given number of bytes.
special template class to simplify handling of ITX/PEAR
if(!file_exists("$old.txt")) if( $old===$new) if(file_exists("$new.txt")) $file