16 include_once (
"FDL/Class.SearchDoc.php");
37 private $params = array(
40 'outputpgservice' =>
'',
41 'tmppgservice' =>
'tmp_1nf',
42 'tmpschemaname' =>
'1nf',
43 'tmpemptydb' =>
'yes',
51 private $sqlStandardLogHandle = null;
56 private $sqlStandardLogCounter = 0;
61 private $sqlStandardLogBufferSize = 300;
66 private $sqlStandardLogBuffer =
'';
71 private $sqlPostgresLogHandle = null;
76 private $sqlPostgresFileName =
'';
81 private $sqlPostgresLogCounter = 0;
86 private $sqlPostgresLogBufferSize = 300;
91 private $sqlPostgresLogBuffer =
'';
96 private $sqlSequences = array();
101 private $sqlInsertCounter = 0;
106 private $sqlInsertBuffer = array();
111 private $sqlInsertBufferSize = 300;
145 private $config = array();
150 private $conn = null;
155 private $tmp_conn = null;
169 foreach ($params as $key =>
$value) {
170 if (array_key_exists($key, $this->params)) {
171 $this->params[$key] =
$value;
175 $this->freedom_dbaccess = $action->dbaccess;
176 if ($this->freedom_dbaccess ==
"") {
177 $action->error(_(
"Error: empty action->dbaccess"));
181 $this->tmp_dbaccess = sprintf(
"service=%s", $this->params[
'tmppgservice']);
188 private function getPgEscape(
$value, $nullAllowed =
true)
190 if ($nullAllowed &&
"$value" ===
"")
return 'NULL';
191 return "'" . pg_escape_string(
$value) .
"'";
198 private function getPgEscapeCopy(
$value, $nullAllowed =
true)
200 if ($nullAllowed &&
"$value" ===
"")
return "\\N";
202 $value = str_replace(array(
216 private function stdInfo()
218 $args = func_get_args();
219 if (count(
$args) >= 2) {
220 $msg = call_user_func_array(
'sprintf',
$args);
224 $this->action->info(trim($msg));
229 private function stdError()
231 $args = func_get_args();
232 if (count(
$args) >= 2) {
233 $msg = call_user_func_array(
'sprintf',
$args);
237 $this->action->error(trim($msg));
238 $this->sqlLogWrite($msg,
true);
239 $this->sqlLogFlush();
246 private function sqlLogFlush()
248 $this->sqlPostgresLogFlush();
249 $this->sqlStandardLogFlush();
255 private function sqlLogOpen()
257 if (!$this->sqlPostgresLogOpen())
return false;
258 if (!$this->sqlStandardLogOpen())
return false;
264 private function sqlLogClose()
266 if (!$this->sqlPostgresLogClose())
return false;
267 if (!$this->sqlStandardLogClose())
return false;
273 private function sqlLogWrite($line,
$comment =
false)
275 $this->sqlPostgresLogWrite($line,
$comment);
276 $this->sqlStandardLogWrite($line,
$comment);
281 private function sqlStandardLogFlush()
283 if ($this->sqlStandardLogHandle !== null) {
284 @fwrite($this->sqlStandardLogHandle, $this->sqlStandardLogBuffer);
285 $this->sqlStandardLogBuffer =
'';
286 $this->sqlStandardLogCounter = 0;
292 private function sqlStandardLogWrite($line,
$comment =
false, $comma =
true)
294 if ($this->sqlStandardLogHandle !== null) {
296 $line =
"\n--\n-- " . str_replace(
"\n",
"\n-- ", str_replace(
"\r",
"", $line)) .
"\n--\n";
297 } elseif ($comma && substr($line, -1) !=
';') {
300 $line = str_replace(
'"' . $this->params[
'tmpschemaname'] .
'".',
'', $line) .
"\n";
301 $this->sqlStandardLogBuffer.= $line;
302 $this->sqlStandardLogCounter++;
303 if ($this->sqlStandardLogCounter >= $this->sqlStandardLogBufferSize) {
304 $this->sqlStandardLogFlush();
311 private function sqlStandardLogClose()
313 if ($this->sqlStandardLogHandle !== null) {
314 $this->sqlStandardLogFlush();
315 @fwrite($this->sqlStandardLogHandle,
"\n\n\n");
316 @fclose($this->sqlStandardLogHandle);
323 private function sqlStandardLogOpen()
326 if (!empty($this->params[
'outputsql'])) {
327 $this->sqlStandardLogHandle = @fopen($this->params[
'outputsql'],
'w');
328 if (!$this->sqlStandardLogHandle) {
329 $this->stdError(_(
"Error could not open output log file '%s' for writing.") , $this->params[
'outputsql']);
333 catch(Exception $e) {
341 private function sqlPostgresLogFlush()
343 if ($this->sqlPostgresLogHandle !== null) {
344 @fwrite($this->sqlPostgresLogHandle, $this->sqlPostgresLogBuffer);
345 $this->sqlPostgresLogBuffer =
'';
346 $this->sqlPostgresLogCounter = 0;
352 private function sqlPostgresLogWrite($line,
$comment =
false, $comma =
true)
354 if ($this->sqlPostgresLogHandle !== null) {
356 $line =
"\n--\n-- " . str_replace(
"\n",
"\n-- ", str_replace(
"\r",
"", $line)) .
"\n--\n";
357 } elseif ($comma && substr($line, -1) !=
';') {
360 $line = str_replace(
'"' . $this->params[
'tmpschemaname'] .
'".',
'', $line) .
"\n";
361 $this->sqlPostgresLogBuffer.= $line;
362 $this->sqlPostgresLogCounter++;
363 if ($this->sqlPostgresLogCounter >= $this->sqlPostgresLogBufferSize) {
364 $this->sqlPostgresLogFlush();
371 private function sqlPostgresLogClose()
373 if ($this->sqlPostgresLogHandle !== null) {
374 $this->sqlPostgresLogFlush();
375 @fwrite($this->sqlPostgresLogHandle,
"\n\n\n");
376 @fclose($this->sqlPostgresLogHandle);
383 private function sqlPostgresLogOpen()
385 include_once (
'WHAT/Lib.Common.php');
388 if (!empty($this->params[
'outputpgservice']) || !empty($this->params[
'sqllog'])) {
389 if (empty($this->params[
'sqllog'])) {
390 $this->sqlPostgresFileName = tempnam(
getTmpDir() ,
'sqlPostgres.tmp.1nf.');
391 if ($this->sqlPostgresFileName ===
false) {
392 $this->stdError(_(
"Error creating temp file for sql log output."));
395 $this->sqlPostgresFileName = $this->params[
'sqllog'];
398 $this->sqlPostgresLogHandle = @fopen($this->sqlPostgresFileName,
'w');
399 if (!$this->sqlPostgresLogHandle) {
400 $this->stdError(_(
"Error could not open sql log file '%s' for writing.") , $this->sqlPostgresFileName);
404 catch(Exception $e) {
418 if (!$this->configParse())
return false;
420 if (!$this->freedomDatabaseConnection())
return false;
422 if (!$this->tmpDatabaseConnection())
return false;
424 if ($this->params[
'tmpemptydb'] ==
'yes') {
426 if (!$this->tmpDatabaseEmpty())
return false;
428 $dumpFile = $this->databaseDump($this->freedom_pgservice);
429 if ($dumpFile ===
false)
return false;
431 if (!$this->databaseLoad($dumpFile, $this->params[
'tmppgservice']))
return false;
436 if (!$this->sqlLogOpen())
return false;
438 if (!$this->configLoad())
return false;
440 if (!$this->sqlCreateSchema())
return false;
442 if (!$this->sqlCreateTables())
return false;
444 if (!$this->sqlFillTables())
return false;
446 if (!$this->sqlMakeReferences())
return false;
448 if (!$this->sqlLogClose())
return false;
450 if (!empty($this->params[
'outputpgservice'])) {
451 if (!$this->databaseLoad($this->sqlPostgresFileName, $this->params[
'outputpgservice']))
return false;
454 if (!empty($this->sqlPostgresFileName) && empty($this->params[
'sqllog'])) {
455 @unlink($this->sqlPostgresFileName);
458 catch(Exception $e) {
462 $this->stdInfo(_(
"Export 1NF done"));
470 private function sqlExecute($requests,
$log =
true)
472 if (!is_array($requests)) {
477 foreach ($requests as
$sql) {
478 if (preg_match(
"/^\s*--/", $sql)) {
481 if (
$log) $this->sqlLogWrite($sql);
482 $res = @pg_query($this->tmp_conn, $sql);
483 if (!$res) $this->checkErrorPostgresql($sql);
492 private function sqlInsertFlush()
494 foreach ($this->sqlInsertBuffer as $tableName =>
$rows) {
495 $sql =
'COPY "' . $this->params[
'tmpschemaname'] .
'"."' . $tableName .
'" FROM STDIN;';
496 $this->sqlPostgresLogWrite($sql,
false,
false);
497 $res = @pg_query($this->tmp_conn, $sql);
498 if (!$res) $this->checkErrorPostgresql($sql);
499 foreach (
$rows as $row) {
500 $this->sqlPostgresLogWrite($row,
false,
false);
501 $res = @pg_put_line($this->tmp_conn, $row .
"\n");
502 if (!$res) $this->checkErrorPostgresql(
"ROW $row");
504 $this->sqlPostgresLogWrite(
"\\.\n",
false,
false);
505 $res = @pg_put_line($this->tmp_conn,
"\\.\n");
506 if (!$res) $this->checkErrorPostgresql();
507 $res = @pg_end_copy($this->tmp_conn);
508 if (!$res) $this->checkErrorPostgresql();
510 $this->sqlInsertBuffer = array();
511 $this->sqlInsertCounter = 0;
518 private function sqlInsert($table, $fields, $values, $escapedValues)
520 $this->sqlStandardLogWrite(
'INSERT INTO "' . $this->params[
'tmpschemaname'] .
'"."' . $table .
'" ("' . implode(
'","', $fields) .
'") VALUES (' . implode(
',', $escapedValues) .
');');
522 if (!isset($this->sqlInsertBuffer[$table])) {
523 $this->sqlInsertBuffer[$table] = array();
525 $this->sqlInsertBuffer[$table][] = implode(
"\t", $values);
526 $this->sqlInsertCounter++;
528 if ($this->sqlInsertCounter >= $this->sqlInsertBufferSize) {
529 $this->sqlInsertFlush();
537 private function sqlCreateSchema()
540 $this->stdInfo(_(
"Create Schema '%s' ...") , $this->params[
'tmpschemaname']);
541 $this->sqlExecute(
'DROP SCHEMA IF EXISTS "' . $this->params[
'tmpschemaname'] .
'" CASCADE',
false);
542 $this->sqlExecute(
'CREATE SCHEMA "' . $this->params[
'tmpschemaname'] .
'"',
false);
544 catch(Exception $e) {
553 private function sqlCreateTables()
556 $this->stdInfo(_(
"Create Tables ..."));
557 foreach ($this->config as $table) {
559 $insertDefaults =
true;
561 switch ($table->type) {
563 case 'enum_multiple':
565 $fields[] = sprintf(
' "%s" %s PRIMARY KEY',
'id',
'text');
566 $fields[] = sprintf(
' "%s" %s',
'title',
'text');
567 $table->sqlFields[] =
'id';
568 $table->sqlFields[] =
'title';
569 $insertDefaults =
false;
573 $fields[] = sprintf(
' "%s" %s PRIMARY KEY',
'id',
'integer');
574 $fields[] = sprintf(
' "%s" %s',
'title',
'text');
575 $table->sqlFields[] =
'id';
576 $table->sqlFields[] =
'title';
580 $fields[] = sprintf(
' "%s" %s PRIMARY KEY',
'id',
'integer');
581 $table->sqlFields[] =
'id';
584 if ($insertDefaults) {
585 foreach ($table->columns as $column) {
586 $fields[] = sprintf(
' "%s" %s', $column->name, $column->pgType);
587 $table->sqlFields[] = $column->name;
589 foreach ($table->properties as $property) {
590 $fields[] = sprintf(
' "%s" %s', $property->name, $property->pgType);
591 $table->sqlFields[] = $property->name;
593 foreach ($table->references as $reference) {
594 $fields[] = sprintf(
' "%s" %s', $reference->attributeName, $reference->type);
595 $table->sqlFields[] = $reference->attributeName;
599 $this->stdInfo(_(
"Create Table '%s'") , strtolower($table->name));
600 $this->sqlLogWrite(sprintf(
"Create table %s", strtolower($table->name)) ,
true);
602 $sql = sprintf(
'CREATE TABLE "%s"."%s" (', $this->params[
'tmpschemaname'], strtolower($table->name)) .
"\n";
603 $sql.= implode(
",\n", $fields) .
"\n)";
604 $this->sqlExecute($sql);
607 catch(Exception $e) {
616 private function sqlMakeReferences()
620 $this->stdInfo(_(
"Make references ..."));
621 $this->sqlLogWrite(
"Building References",
true);
623 foreach ($this->config as $table) {
624 foreach ($table->references as $reference) {
625 $sql = sprintf(
'ALTER TABLE "%s"."%s" ADD CONSTRAINT "%s" FOREIGN KEY ("%s") REFERENCES "%s"."%s" ("%s") MATCH SIMPLE', $this->params[
'tmpschemaname'], strtolower($table->name) , $reference->attributeName, $reference->attributeName, $this->params[
'tmpschemaname'], strtolower($reference->foreignTable) , $reference->foreignKey);
627 $this->sqlExecute($sql);
631 catch(Exception $e) {
642 private function sqlNextSequenceId($tableName)
644 if (isset($this->sqlSequences[$tableName])) {
645 $this->sqlSequences[$tableName]++;
646 return $this->sqlSequences[$tableName];
648 $this->sqlSequences[$tableName] = 1;
656 private function sqlGetValidDocId(
$docid)
658 $sql = sprintf(
"SELECT id from docread where initid=(select initid from docread where id=%d) and locked != -1 limit 1;",
$docid);
659 $res = @pg_query($this->tmp_conn, $sql);
661 $row = @pg_fetch_row($res);
672 private function sqlFillTables()
675 $this->stdInfo(_(
"Fill Tables ..."));
677 $tablesByName = array();
678 foreach ($this->config as $table) {
679 $tablesByName[strtolower($table->name) ] = $table;
682 foreach ($this->config as $table) {
683 if ($table->type ==
'family') {
684 $this->stdInfo(_(
"Filling family table '%s' and relatives") , strtolower($table->name));
685 $this->sqlLogWrite(sprintf(
"Filling table %s and relatives", strtolower($table->name)) ,
true);
687 $s =
new SearchDoc($this->tmp_dbaccess, $table->name);
688 $s->setObjectReturn();
693 while (
$doc =
$s->getNextDoc()) {
695 $fieldValues = array(
697 $this->getPgEscape(
$doc->getTitle()) ,
699 $fieldCopyValues = array(
701 $this->getPgEscapeCopy(
$doc->getTitle()) ,
704 foreach ($table->columns as $column) {
705 $fieldValues[] = $column->getPgEscape(
$doc->getRawValue($column->name));
706 $fieldCopyValues[] = $column->getPgEscapeCopy(
$doc->getRawValue($column->name));
709 foreach ($table->properties as $property) {
710 $propertyName = $property->name;
711 $fieldValues[] = $property->getPgEscape(
$doc->$propertyName);
712 $fieldCopyValues[] = $property->getPgEscapeCopy(
$doc->$propertyName);
715 foreach ($table->references as $reference) {
716 $fTable = strtolower($reference->foreignTable);
717 if (!array_key_exists($fTable, $tablesByName)) {
718 $this->stdError(_(
"Table '%s' unknown !") , $reference->foreignTable);
721 switch ($tablesByName[$fTable]->
type) {
723 $value =
$doc->getRawValue($reference->attributeName);
724 $id = $this->sqlGetValidDocId(
$value);
725 $fieldValues[] = $id;
726 $fieldCopyValues[] = $id ==
'NULL' ?
"\\N" : $id;
730 case 'enum_multiple':
732 $value =
$doc->getRawValue($reference->attributeName);
733 $tablesByName[$fTable]->checkEnumValue(
$value);
734 $fieldValues[] = $this->getPgEscape(
$value);
735 $fieldCopyValues[] = $this->getPgEscapeCopy(
$value);
739 $fieldValues[] =
"''";
740 $fieldCopyValues[] =
"";
745 $this->sqlInsert(strtolower($table->name) , $table->sqlFields, $fieldCopyValues, $fieldValues);
751 foreach ($table->linkedTables as
$type => $linkedTables) {
752 foreach ($linkedTables as
$data) {
754 case 'enum_multiple_link':
755 $values =
$doc->getMultipleRawValues($data[
'column']->
name);
756 foreach ($values as
$value) {
757 if (isset($data[
'enumtable'])) {
758 $data[
'enumtable']->checkEnumValue($value);
760 $this->sqlInsert(strtolower($data[
'table']->
name) , $data[
'table']->sqlFields, array(
761 $this->getPgEscapeCopy($value) ,
764 $this->getPgEscapeCopy($value) ,
770 case 'docid_multiple_link':
771 $values =
$doc->getMultipleRawValues($data[
'column']->
name);
772 foreach ($values as $value) {
773 $id = $this->sqlGetValidDocId($value);
774 $this->sqlInsert(strtolower($data[
'table']->
name) , $data[
'table']->sqlFields, array(
775 $id ==
'NULL' ?
"\\N" : $id,
786 $array =
$doc->getArrayRawValues($data[
'table']->arrayName);
788 foreach ($array as $iRow => $row) {
790 $arrayId = $this->sqlNextSequenceId($data[
'table']->
name);
792 $fieldValues = array();
793 $fieldValues[] = $arrayId;
794 $fieldCopyValues = array();
795 $fieldCopyValues[] = $arrayId;
797 foreach ($data[
'table']->columns as $col) {
798 $fieldValues[] = $col->getPgEscape($row[$col->name]);
799 $fieldCopyValues[] = $col->getPgEscapeCopy($row[$col->name]);
802 foreach ($data[
'table']->references as $reference) {
803 $fTable = strtolower($reference->foreignTable);
804 if (!array_key_exists($fTable, $tablesByName)) {
805 $this->stdError(_(
"Table '%s' unknown !") , $reference->foreignTable);
807 if ($tablesByName[$fTable]->
type ==
'family' && strtolower($reference->attributeName) == strtolower($reference->foreignTable)) {
809 $fieldValues[] =
$doc->id;
810 $fieldCopyValues[] =
$doc->id;
814 $value = $row[$reference->attributeName];
815 if ($tablesByName[$fTable]->
type ==
'family') {
816 $id = $this->sqlGetValidDocId($value);
817 $fieldValues[] = $id;
818 $fieldCopyValues[] = $id ==
'NULL' ?
"\\N" : $id;
819 } elseif (in_array($tablesByName[$fTable]->
type, array(
824 $tablesByName[$fTable]->checkEnumValue($value);
825 $fieldValues[] = $this->getPgEscape($value);
826 $fieldCopyValues[] = $this->getPgEscapeCopy($value);
828 $fieldValues[] = $this->getPgEscape($value);
829 $fieldCopyValues[] = $this->getPgEscapeCopy($value);
833 $this->sqlInsert(strtolower($data[
'table']->
name) , $data[
'table']->sqlFields, $fieldCopyValues, $fieldValues);
835 foreach ($data[
'linkedTables'] as $data2) {
836 $values =
$doc->rawValueToArray(str_replace(
'<BR>',
"\n", $row[$data2[
'column']->
name]));
837 foreach ($values as $val) {
838 $id = $this->sqlGetValidDocId($val);
839 $this->sqlInsert(strtolower($data2[
'table']->
name) , $data2[
'table']->sqlFields, array(
840 $id ==
'NULL' ?
"\\N" : $id,
861 foreach ($this->config as $table) {
862 if ($table->type ==
'enum' || $table->type ==
'enum_multiple' || $table->type ==
'enum_inarray') {
863 $this->stdInfo(_(
"Filling enum table '%s'") , $table->name);
864 $this->sqlLogWrite(sprintf(
"Filling enum table %s", strtolower($table->name)) ,
true);
865 foreach ($table->enumDatas as $key => $value) {
866 $this->sqlInsert($table->name, array(
870 $this->getPgEscapeCopy($key,
false) ,
871 $this->getPgEscapeCopy($value)
873 $this->getPgEscape($key,
false) ,
874 $this->getPgEscape($value)
880 $this->sqlInsertFlush();
882 catch(Exception $e) {
891 private function configLoad()
894 if (!$this->configLoadFamilies())
return false;
895 if (!$this->configLoadAttributes())
return false;
896 if (!$this->configLoadExplodeContainers())
return false;
897 if (!$this->configLoadTables())
return false;
898 if (!$this->configLoadCheck())
return false;
908 private function getArrayColumns($family, $arrayName)
910 $arrayColumns = array();
911 foreach ($family->columns as $i => $column) {
912 if ($column->arrayName == $arrayName) $arrayColumns[$i] = $column;
914 return $arrayColumns;
920 private function configLoadCheck()
923 foreach ($this->config as $iFamily => $family) {
926 foreach ($family->columns as $i => $column1) {
927 if (in_array($i, $delete))
continue;
928 foreach ($family->columns as $j => $column2) {
929 if ($i == $j)
continue;
930 if ($column1->name == $column2->name) {
935 foreach ($delete as $i) {
936 $this->stdInfo(_(
"Remove duplicate attribute '%s' in family '%s'") , $this->config[$iFamily]->columns[$i]->
name, $family->name);
937 unset($this->config[$iFamily]->columns[$i]);
941 foreach ($family->references as $i => $ref1) {
942 if (in_array($i, $delete))
continue;
943 foreach ($family->references as $j => $ref2) {
944 if ($i == $j)
continue;
945 if ($ref1->isSameAs($ref2)) {
950 foreach ($delete as $i) {
951 $this->stdInfo(_(
"Remove duplicate reference '%s' in family '%s'") , $this->config[$iFamily]->references[$i]->attributeName, $family->name);
952 unset($this->config[$iFamily]->references[$i]);
955 if ($family->type !=
'family')
continue;
958 foreach ($family->properties as $i => $property1) {
959 if (in_array($i, $delete))
continue;
960 foreach ($family->properties as $j => $property2) {
961 if ($i == $j)
continue;
962 if ($property1->name == $property2->name) {
967 foreach ($delete as $i) {
968 $this->stdInfo(_(
"Remove duplicate property '%s' in family '%s'") , $this->config[$iFamily]->properties[$i]->
name, $family->name);
969 unset($this->config[$iFamily]->properties[$i]);
977 foreach ($family->properties as $i => $property) {
978 if (in_array($property->name, $special)) {
982 foreach ($delete as $i) {
983 $this->stdInfo(_(
"Skip already added property '%s' in family '%s'") , $this->config[$iFamily]->properties[$i]->
name, $family->name);
984 unset($this->config[$iFamily]->properties[$i]);
988 catch(Exception $e) {
998 private function getDocidFamily($column, $table)
1000 if (!empty($column->docidFamily))
return $column->docidFamily;
1002 foreach ($table->famAttributes as
$attribute) {
1003 if (!empty($attribute->phpfunc)) {
1004 if (preg_match(
'/lfamill?y\([a-z]+\s*,\s*([a-z0-9_]+).*\):' . $column->name .
'/si', $attribute->phpfunc, $m)) {
1011 if (empty($found)) {
1012 $this->stdError(_(
"Attribute Error: impossible to found the family for docid attribute '%s'") , $column->name);
1015 $fam =
new_Doc($this->tmp_dbaccess, $found,
true);
1016 if (!is_object($fam) || !$fam->isAlive()) {
1017 $this->stdError(_(
"Attribute Error: family '%s' is not valid or alive for docid '%s'.") , $found, $column->name);
1025 private function configLoadTables()
1028 foreach ($this->config as $iFamily => $family) {
1030 if ($family->type !=
'family')
continue;
1034 foreach ($family->columns as $iColumn => $column) {
1035 if (in_array($iColumn, $delete))
continue;
1036 switch ($column->fullType) {
1042 $tableName = $this->getUniqueTableName($column->name);
1044 $newTable->enumDatas = $column->enumDatas;
1045 $family->references[] =
new Form1NF_Reference($tableName, $column->name,
'text');
1046 $this->config[] = $newTable;
1047 $delete[] = $iColumn;
1051 if (empty($column->docidLinkedColumn)) {
1053 $table = $this->getConfigTable($this->getDocidFamily($column, $family) ,
true);
1057 $table = $this->getConfigTable($column->docidLinkedColumn->family,
true);
1058 if (!$table->hasColumn($column->docidLinkedColumn->name)) {
1059 $table->columns[] = $column->docidLinkedColumn;
1062 $table->type =
'family';
1063 $delete[] = $iColumn;
1066 case 'enum_multiple':
1067 $tableNameLink = $this->getUniqueTableName($family->name .
'_' . $column->name);
1068 $newTableLink =
new Form1NF_Table(
'enum_multiple_link', $tableNameLink);
1070 $tableNameEnum = $this->getUniqueTableName($column->name);
1071 $newTableEnum =
new Form1NF_Table(
'enum_multiple', $tableNameEnum);
1072 $newTableEnum->enumDatas = $column->enumDatas;
1074 $newTableLink->references[] =
new Form1NF_Reference($tableNameEnum,
'idenum',
'text');
1076 $family->linkedTables[
'enum_multiple_link'][] = array(
1077 'table' => $newTableLink,
1078 'enumtable' => $newTableEnum,
1079 'column' => $column,
1082 $this->config[] = $newTableEnum;
1083 $this->config[] = $newTableLink;
1085 $delete[] = $iColumn;
1088 case 'docid_multiple':
1089 $tableNameLink = $this->getUniqueTableName($family->name .
'_' . $column->name);
1090 $newTableLink =
new Form1NF_Table(
'docid_multiple_link', $tableNameLink);
1092 $newTableDocid = $this->getConfigTable($this->getDocidFamily($column, $family) ,
true);
1094 $newTableLink->references[] =
new Form1NF_Reference($newTableDocid->name,
'iddoc');
1096 $family->linkedTables[
'docid_multiple_link'][] = array(
1097 'table' => $newTableLink,
1098 'column' => $column,
1101 $this->config[] = $newTableLink;
1102 $newTableDocid->type =
'family';
1103 $delete[] = $iColumn;
1106 case 'simple_inarray':
1108 case 'enum_inarray':
1109 case 'docid_inarray':
1110 case 'docid_multiple_inarray':
1112 $arrayColumns = $this->getArrayColumns($family, $column->arrayName);
1113 if ($arrayColumns ===
false) {
1114 $this->stdError(_(
"Error: No column found in array '%s'") , $column->arrayName);
1117 $tableArrayName = $family->name .
'_' . $column->arrayName;
1118 $tableArray = $this->getConfigTable($tableArrayName,
true);
1119 $tableArray->type =
'array';
1120 $tableArray->arrayName = $column->arrayName;
1122 $linkedTable = array(
1123 'table' => $tableArray,
1124 'linkedTables' => array() ,
1127 foreach ($arrayColumns as $i => $col) {
1128 switch ($col->fullType) {
1129 case 'simple_inarray':
1130 if (!$tableArray->hasColumn($col->name)) {
1131 $tableArray->columns[] = $col;
1135 case 'enum_inarray':
1136 $tableEnumName = $this->getUniqueTableName($col->name);
1137 $newTable =
new Form1NF_Table(
'enum_inarray', $tableEnumName);
1138 $newTable->enumDatas = $col->enumDatas;
1139 $tableArray->references[] =
new Form1NF_Reference($tableEnumName, $col->name,
'text');
1140 $this->config[] = $newTable;
1143 case 'docid_inarray':
1144 $tableDocid = $this->getConfigTable($this->getDocidFamily($col, $family) ,
true);
1145 $tableArray->references[] =
new Form1NF_Reference($tableDocid->name, $col->name);
1146 $tableDocid->type =
'family';
1149 case 'docid_multiple_inarray':
1150 $tableNameLink = $this->getUniqueTableName($tableArrayName .
'_' . $col->name);
1151 $newTableLink =
new Form1NF_Table(
'docid_multiple_inarray_link', $tableNameLink);
1153 $newTableDocid = $this->getConfigTable($this->getDocidFamily($col, $family) ,
true);
1156 $newTableLink->references[] =
new Form1NF_Reference($tableArrayName,
'idarray');
1158 $linkedTable[
'linkedTables'][] = array(
1159 'table' => $newTableLink,
1163 $newTableDocid->type =
'family';
1164 $this->config[] = $newTableLink;
1168 $this->stdError(_(
"Incoherent column type '%s' in array '%s'.") , $colType, $column->arrayName);
1173 $family->linkedTables[
'array'][] = $linkedTable;
1177 $this->stdError(_(
"Column type '%s' is not managed for export.") , $column->fullType);
1181 foreach ($delete as $iColumn) unset($this->config[$iFamily]->columns[$iColumn]);
1184 catch(Exception $e) {
1193 private function configLoadFamilies()
1196 foreach ($this->config as $family) {
1206 $this->stdError(_(
"Could not get family id for '%s'.") , $family->name);
1212 if (!is_object($fam) || !$fam->isAlive()) {
1213 $this->stdError(_(
"Family '%s' is not valid or alive.") ,
$famId);
1216 $famAttributes = $fam->GetAttributes();
1218 foreach ($famAttributes as $attribute) {
1223 foreach ($family->properties as $property) {
1224 if (!in_array($property->name, $allowedProperties)) {
1225 $this->stdError(_(
"Property '%s' is not valid (family '%s').") , $property->name, $family->name);
1232 catch(Exception $e) {
1241 private function configLoadExplodeContainers()
1244 foreach ($this->config as $family) {
1247 foreach ($family->columns as $i => $column) {
1248 if (in_array($i, $delete))
continue;
1249 if ($column->isContainer) {
1250 $columns = $family->getChildAttributes($column->name);
1251 if ($columns ===
false) {
1252 $this->stdError($family->error);
1254 foreach ($columns as $col) {
1255 $family->columns[] = $col;
1260 foreach ($delete as $i) unset($family->columns[$i]);
1263 catch(Exception $e) {
1272 private function configLoadAttributes()
1275 foreach ($this->config as $family) {
1277 foreach ($family->columns as $column) {
1279 $columnName = $column->name;
1280 $columnLinkedName =
'';
1282 if (strpos($columnName,
':') !==
false) {
1284 list($columnName, $columnLinkedName) = explode(
':', $columnName);
1287 $attributeFound = null;
1288 foreach ($family->famAttributes as $attribute) {
1289 if ($attribute->name == $columnName) {
1295 if ($attributeFound === null) {
1296 $this->stdError(_(
"Could not find attribute '%s' in family '%s'.") , $column->name, $family->name);
1299 $column->copyFromColumn($attributeFound);
1301 if (!empty($columnLinkedName)) {
1303 if ($attributeFound->type !=
'docid') {
1304 $this->stdError(_(
"Attribute '%s' should reference a docid attribute in family '%s'.") , $column->name, $family->name);
1307 if (empty($attributeFound->docidFamily)) {
1308 $this->stdError(_(
"Attribute format should not be empty on attribute '%s' in family '%s'.") , $column->name, $family->name);
1311 $doc =
new_Doc($this->tmp_dbaccess, $attributeFound->docidFamily);
1313 if (!is_object(
$doc) || !
$doc->isAlive()) {
1314 $this->stdError(_(
"Family '%s' is not valid or alive.") , $attributeFound->docidFamily);
1317 $attribute =
$doc->getAttribute($columnLinkedName);
1319 if (!is_object($attribute) || empty($attribute)) {
1320 $this->stdError(_(
"Attribute '%s' could not be found in family '%s'.") , $columnLinkedName, $attributeFound->docidFamily);
1327 catch(Exception $e) {
1338 private function getConfigTable($name, $autocreate =
false)
1342 $this->stdError(_(
"Name of table cannot be empty"));
1344 foreach ($this->config as $table) {
1345 if (strtolower($table->name) == strtolower($name)) {
1349 if (empty($return) && $autocreate) {
1351 $this->config[] = $table;
1360 private function getUniqueTableName($name)
1364 while (($found = $this->getConfigTable($newName)) !==
false) {
1365 $newName = $name . $i;
1368 return strtolower($newName);
1374 private function checkErrorPostgresql($str =
'')
1376 if ($this->tmp_conn) {
1377 $err = pg_last_error($this->tmp_conn);
1379 $this->stdError(
'PG Error: ' .
$err . (!empty($str) ?
"\n" . $str :
''));
1387 private function checkErrorLibXML()
1389 $err = libxml_get_last_error();
1390 if (is_object(
$err)) {
1391 $this->stdError(
'XML Error: ' .
$err->message);
1398 private function configParse()
1405 $xml =
new DOMDocument();
1406 $ret = @$xml->load($this->params[
'config']);
1407 $this->checkErrorLibXML();
1409 $this->config = array();
1411 $databaseNodes = @$xml->getElementsByTagName(
'database');
1412 $this->checkErrorLibXML();
1413 if ($databaseNodes->length == 0) {
1414 $this->stdError(_(
"XML Error: no <database/> root node."));
1416 if ($databaseNodes->length > 1) {
1417 $this->stdError(_(
"XML Error: only one <database/> root node allowed."));
1420 $databaseNode = $databaseNodes->item(0);
1422 $tableNodes = @$databaseNode->getElementsByTagName(
'table');
1423 $this->checkErrorLibXML();
1424 foreach ($tableNodes as $tableNode) {
1426 $familyName = $tableNode->getAttribute(
'family');
1427 if (empty($familyName)) {
1428 $this->stdError(_(
"XML Error: no 'family' attribute on <table/> node."));
1432 $columnNodes = @$tableNode->getElementsByTagName(
'column');
1433 $this->checkErrorLibXML();
1434 foreach ($columnNodes as $columnNode) {
1436 $columnName = strtolower($columnNode->getAttribute(
'attribute'));
1437 $propertyName = strtolower($columnNode->getAttribute(
'property'));
1439 if (empty($columnName) && empty($propertyName)) {
1440 $this->stdError(_(
"XML Error: no property or attribute on <column/> node."));
1443 if (!empty($columnName)) {
1447 $column->isProperty =
true;
1448 $table->properties[] = $column;
1451 $this->config[] = $table;
1453 if (empty($this->config)) {
1454 $this->stdError(_(
"XML Error: no table defined."));
1456 $this->stdInfo(_(
"XML config parsed OK !"));
1458 catch(Exception $e) {
1469 private function databaseDump($pgservice)
1471 include_once (
'WHAT/Lib.Common.php');
1474 $this->stdInfo(_(
"Dump pgservice '%s' ...") , $pgservice);
1476 $tmp_dump = tempnam(
getTmpDir() ,
'pg_dump.tmp.1nf.');
1477 if ($tmp_dump ===
false) {
1478 $this->stdError(_(
"Error creating temp file for pg_dump output."));
1482 if ($pg_dump_cmd ===
false) {
1483 $this->stdError(_(
"Could not find pg_dump command in PATH."));
1488 '--disable-triggers',
1492 'closestdin' =>
true,
1493 'closestdout' =>
true,
1495 'PGSERVICE' => $pgservice,
1500 $this->stdError(_(
"Dump to '%s' returned with exitcode %s") , $tmp_dump,
$ret);
1503 catch(Exception $e) {
1513 private function databaseLoad($dumpFile, $pgservice)
1516 $this->stdInfo(_(
"Load dump file into '%s' ...") , $pgservice);
1519 if ($psql_cmd ===
false) {
1520 $this->stdError(_(
"Could not find psql command in PATH."));
1529 'closestdin' =>
true,
1530 'closestdout' =>
true,
1532 'PGSERVICE' => $pgservice
1536 $this->stdError(_(
"Loading of dump '%s' returned with exitcode %s") , $dumpFile,
$ret);
1539 catch(Exception $e) {
1549 private function freedomDatabaseConnection()
1552 $this->conn = @pg_connect($this->freedom_dbaccess);
1553 if ($this->conn ===
false) {
1554 $this->stdError(_(
"PG Error: Connection to freedom pg service '%s' failed !") , $this->freedom_pgservice);
1557 catch(Exception $e) {
1560 $this->stdInfo(_(
"Connection to freedom pg service '%s' OK !") , $this->freedom_pgservice);
1568 private function tmpDatabaseConnection()
1571 $this->tmp_conn = @pg_connect($this->tmp_dbaccess);
1572 if ($this->tmp_conn ===
false) {
1573 $this->stdError(_(
"PG Error: Connection to temporary pg service '%s' failed !") , $this->params[
'tmppgservice']);
1576 catch(Exception $e) {
1579 $this->stdInfo(_(
"Connection to temporary pg service '%s' OK !") , $this->params[
'tmppgservice']);
1580 return $this->tmp_conn;
1586 private function tmpDatabaseEmpty()
1589 $this->stdInfo(_(
"Emptying temporary database '%s' ...") , $this->params[
'tmppgservice']);
1590 foreach ($this->dropSchemas as $schema) {
1591 $this->sqlExecute(sprintf(
'DROP SCHEMA IF EXISTS "%s" CASCADE', $schema) ,
false);
1593 $this->sqlExecute(
'CREATE SCHEMA "public"',
false);
1595 catch(Exception $e) {
1642 if ($this->attributeName != $ref->attributeName)
return false;
1643 if ($this->foreignTable != $ref->foreignTable)
return false;
1644 if ($this->foreignKey != $ref->foreignKey)
return false;
1645 if ($this->
type != $ref->type)
return false;
1727 if (
"$value" ===
"")
return false;
1728 if (!array_key_exists($value, $this->enumDatas)) {
1741 foreach ($this->famAttributes as $attribute) {
1742 if ($attribute->type ==
'array')
continue;
1743 if ($attribute->type ==
'frame')
continue;
1744 if ($attribute->type ==
'tab')
continue;
1745 if (in_array(
$name, $attribute->containers)) {
1759 foreach ($this->columns as $column) {
1760 if (strtolower($column->name) == strtolower(
$name))
return $column;
1809 public $family =
'';
1863 if (is_object(
$name)) {
1876 $this->
name = $attribute->id;
1877 $this->
type = $attribute->type;
1878 $this->family = $attribute->docname;
1879 $this->phpfunc = $attribute->phpfunc;
1880 $this->docidFamily = $attribute->format;
1881 $this->isMultiple = ($attribute->getOption(
'multiple') ==
'yes');
1882 $this->inArray = ($attribute->inArray());
1884 if ($this->
type ==
'thesaurus') {
1885 $this->
type =
'docid';
1886 $this->docidFamily =
'THCONCEPT';
1889 $this->isEnum = ($this->
type ==
'enum');
1890 $this->isDocid = ($this->
type ==
'docid');
1891 $this->isContainer = ($this->
type ==
'tab' || $this->
type ==
'frame' || $this->
type ==
'array');
1893 if ($this->isEnum) $this->enumDatas = $attribute->getEnum();
1895 $this->pgType = $this->getPgType();
1896 $this->fullType = $this->getFullType();
1897 $this->loadContainers($attribute->fieldSet);
1906 $this->pgType = $this->getPgType();
1907 $this->fullType = $this->getFullType();
1915 foreach ($this as $ppt => $value) {
1916 $this->$ppt = $column->$ppt;
1923 private function loadContainers($fieldset)
1925 if (!is_object($fieldset))
return;
1926 if ($fieldset->id == \Adoc::HIDDENFIELD)
return;
1927 if (empty($this->arrayName) && $fieldset->type ==
'array') $this->arrayName = $fieldset->id;
1928 $this->containers[] = $fieldset->id;
1929 if (property_exists($fieldset,
'fieldSet')) {
1930 $this->loadContainers($fieldset->fieldSet);
1943 if (
"$value" ===
"")
return 'NULL';
1945 if ($this->isProperty && $this->
name ==
'revdate') $value = date(
'Y-m-d H:i:s', $value);
1946 return "'" . pg_escape_string($value) .
"'";
1955 if (
"$value" ===
"")
return "\\N";
1956 if ($this->isProperty && $this->
name ==
'revdate') $value = date(
'Y-m-d H:i:s', $value);
1957 $value = pg_escape_string($value);
1958 $value = str_replace(array(
1974 private function getPgType($freedom_type = null)
1976 if ($freedom_type === null) {
1979 switch ($freedom_type) {
1983 return 'time without time zone';
1985 return 'timestamp without time zone';
1994 return 'double precision';
2016 private function getFullType()
2019 if ($this->isEnum)
$type =
'enum';
2022 if ($this->isMultiple)
$type.= '_multiple';
2023 if ($this->inArray)
$type.= '_inarray';
static ssystem($args, $opt=null)
if(substr($wsh, 0, 1)!= '/') $args
print $fam getTitle() $fam name
Exception class use exceptionCode to identifiy correctly exception.
static getCommandPath($cmdname)
getFamIdFromName($dbaccess, $name)
new_Doc($dbaccess, $id= '', $latest=false)
if($file) if($subject==""&&$file) if($subject=="") $err