Loading .gitlab-ci.yml 0 → 100644 +14 −0 Original line number Diff line number Diff line image: registre.unicaen.fr:5000/unicaen-dev-php7.3-apache stages: - publish cache: key: ${CI_COMMIT_REF_SLUG} paths: - vendor/ update-satis: stage: publish script: - curl https://gest.unicaen.fr/packagist/update Module.php +6 −6 Original line number Diff line number Diff line Loading @@ -39,16 +39,16 @@ class Module implements ConsoleUsageProviderInterface public function getConsoleUsage(AdapterInterface $console) { return [ 'run import --name=' => 'Lance un import par son nom (name)', ['--name', "Nom unique de l'import (clé 'name')"], 'run import [--name=<name>]' => 'Lance un import par son nom', ['<name>', "Nom unique de l'import (clé de config 'name')"], 'run import --all' => 'Lance tous les imports', 'run import' => 'Lance tous les imports', [], 'run synchro --name=' => 'Lance une synchronisation par son nom (name)', ['--name', "Nom unique de la synchronisation (clé 'name')"], 'run synchro [--name=<name>]' => 'Lance une synchronisation par son nom', ['<name>', "Nom unique de la synchronisation (clé de config 'name')"], 'run synchro --all' => 'Lance toutes les synchronisations', 'run synchro' => 'Lance toutes les synchronisations', [], ]; } Loading config/module.config.php +25 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,11 @@ use UnicaenDbImport\Entity\Db\Service\ImportObserv\ImportObservService; use UnicaenDbImport\Entity\Db\Service\ImportObserv\ImportObservServiceFactory; use UnicaenDbImport\Entity\Db\Service\ImportObservResult\ImportObservResultService; use UnicaenDbImport\Entity\Db\Service\ImportObservResult\ImportObservResultServiceFactory; use UnicaenDbImport\Entity\Db\Service\Source\SourceService; use UnicaenDbImport\Entity\Db\Service\Source\SourceServiceFactory; use UnicaenDbImport\Entity\Db\Source; use UnicaenDbImport\ORM\Event\Listeners\SourceListener; use UnicaenDbImport\ORM\Event\Listeners\SourceListenerFactory; use UnicaenDbImport\Service\ApiService; use UnicaenDbImport\Service\ApiServiceFactory; use UnicaenDbImport\Service\CodeGeneratorPluginManager; Loading @@ -31,6 +36,9 @@ use UnicaenDbImport\Service\SynchroServiceFactory; return [ 'import' => [ 'source_entity_class' => Source::class, 'default_source_code' => 'app', 'import_observ_entity_class' => ImportObserv::class, 'import_observ_result_entity_class' => ImportObservResult::class, Loading @@ -41,6 +49,9 @@ return [ 'synchros' => [], ], 'UnicaenDbImport.Entity.Db.Source.dcm.xml', 'UnicaenDbImport.Entity.Db.Source.dcm.xml', 'doctrine' => [ 'driver' => [ 'orm_default' => [ Loading @@ -57,6 +68,13 @@ return [ ], ], ], 'eventmanager' => [ 'orm_default' => [ 'subscribers' => [ SourceListener::class, ], ], ], ], 'console' => [ Loading @@ -65,7 +83,7 @@ return [ 'execute_imports' => [ 'type' => 'simple', 'options' => [ 'route' => 'run import [--all|-a] [--name=]', 'route' => 'run import [--name=]', 'defaults' => [ 'controller' => 'UnicaenDbImport\Controller\Console', 'action' => 'runImport', Loading @@ -75,7 +93,7 @@ return [ 'execute_synchro' => [ 'type' => 'simple', 'options' => [ 'route' => 'run synchro [--all|-a] [--name=]', 'route' => 'run synchro [--name=]', 'defaults' => [ 'controller' => 'UnicaenDbImport\Controller\Console', 'action' => 'runSynchro', Loading @@ -95,16 +113,21 @@ return [ 'service_manager' => [ 'factories' => [ Config::class => ConfigFactory::class, ImportService::class => ImportServiceFactory::class, SynchroService::class => SynchroServiceFactory::class, FacadeService::class => FacadeServiceFactory::class, DatabaseService::class => DatabaseServiceFactory::class, ApiService::class => ApiServiceFactory::class, CodeGeneratorPluginManager::class => CodeGeneratorPluginManagerFactory::class, SourceService::class => SourceServiceFactory::class, ImportLogService::class => ImportLogServiceFactory::class, ImportObservService::class => ImportObservServiceFactory::class, ImportObservResultService::class => ImportObservResultServiceFactory::class, SourceListener::class => SourceListenerFactory::class, ], 'abstract_factories' => [ HelperAbstractFactory::class, Loading config/unicaen-db-import.global.php.dist +19 −0 Original line number Diff line number Diff line Loading @@ -5,12 +5,24 @@ namespace Application; use \UnicaenDbImport\Entity\Db\Source; return [ 'import' => [ 'connections' => [ // Cf. `./unicaen-db-import.local.php.dist` ], // // Classe de l'entité Doctrine représentant une "Source". // 'source_entity_class' => Source::class, // // Code de la Source par défaut (injectée dans les entités implémentant SoucreAwareInterface). // 'default_source_code' => 'app', // // Alias éventuels des noms de colonnes d'historique. // Loading Loading @@ -105,6 +117,7 @@ return [ // - 'table' : nom de la table source contenant les données à importer // - 'select' : select SQL de mise en forme des données source à importer (NB: antinomique avec 'table') // - 'source_code_column' : nom de la colonne dans la table/vue source contenant l'identifiant unique // - 'where' : filtre SQL éventuel à appliquer aux données sources. // 'source' => [ 'name' => 'TABLE PAYS DE APOGÉE', Loading @@ -112,6 +125,7 @@ return [ //'table' => 'PAYS', // Équivalent de SELECT * FROM PAYS; 'connection' => 'apogee', 'source_code_column' => 'COD_PAY', //'where' => "TEM_OUV_DRT_SSO_PAY = 'N'", ], // // Configuration de la destination des données importées : Loading Loading @@ -157,12 +171,14 @@ return [ // - 'select' : select SQL de mise en forme des données source à importer (NB: antinomique avec 'table') // - 'connection' : identifiant de la connexion à la bdd source (cf. clé 'connections' plus haut) // - 'source_code_column' : nom de la colonne dans la table/vue source contenant l'identifiant unique // - 'where' : filtre éventuel à apliquer aux données sources // 'source' => [ 'name' => 'TABLE MES_PAYS_TEMPORAIRES', 'table' => 'MES_PAYS_TEMPORAIRES', 'connection' => 'default', 'source_code_column' => 'COD_PAY', //'where' => "TEM_OUV_DRT_SSO_PAY = 'N'", ], // Loading @@ -171,12 +187,15 @@ return [ // - 'connection' : identifiant de la connexion à la bdd destination (cf. clé 'connections' plus haut) // - 'table' : nom de la table destination vers laquelle les données sont synchronisées // - 'source_code_column' : nom de la colonne dans la table destination contenant l'identifiant unique // - 'where' : filtre SQL éventuel permettant de restreindre les données destinations concernées // (les noms de colonnes doivent être préfixés par l'alias de la table destination 'd') // 'destination' => [ 'name' => 'TABLE PAYS', 'table' => 'PAYS', 'connection' => 'default', 'source_code_column' => 'COD_PAY', //'where' => "d.TEM_OUV_DRT_SSO_PAY = 'N'", // // Forçage éventuel du nom de la table où seront inscrits les logs (créée automatiquement si nécessaire). // En l'absence de ce forçage, le nom de la table sera 'import_log'. Loading src/UnicaenDbImport/CodeGenerator/CodeGenerator.php +36 −13 Original line number Diff line number Diff line Loading @@ -198,12 +198,17 @@ abstract class CodeGenerator implements CodeGeneratorInterface public function generateSQLForSelectFromSource(SourceInterface $source) { if ($source->getSelect()) { return $source->getSelect(); $query = $source->getSelect(); } else { $sourceTable = $source->getTable(); $query = $this->tableHelper->generateSQLForSelectFromTable($sourceTable); } $sourceTable = $source->getTable(); if ($where = $source->getWhere()) { $query = sprintf('SELECT * FROM (%s) tmp WHERE (%s)', $query, $where); } return $this->tableHelper->generateSQLForSelectFromTable($sourceTable); return $query; } /** Loading Loading @@ -313,6 +318,7 @@ abstract class CodeGenerator implements CodeGeneratorInterface { $destinationTable = $destination->getTable(); $idColumnSequence = $destination->getIdColumnSequence(); $where = $destination->getWhere(); $sourceCodeColumn = $source->getSourceCodeColumn(); $columns = $source->getColumns(); Loading @@ -331,19 +337,22 @@ abstract class CodeGenerator implements CodeGeneratorInterface $sql = $this->tableHelper->generateSQLForUpdateOperationInDestinationTable( $destinationTable, $sourceCodeColumn, $columns); $columns, $where); break; case Operation::OPERATION_DELETE; $sql = $this->tableHelper->generateSQLForDeleteOperationInDestinationTable( $destinationTable, $sourceCodeColumn, $columns); $columns, $where); break; case Operation::OPERATION_UNDELETE; $sql = $this->tableHelper->generateSQLForUndeleteOperationInDestinationTable( $destinationTable, $sourceCodeColumn, $columns); $columns, $where); break; default: throw new RuntimeException("Opération inattendue"); Loading Loading @@ -386,9 +395,10 @@ EOS; /** * @param array $importObservRow * @param string $where * @return string */ protected function generateSQLForSelectingDiffViewFromImportObservRow(array $importObservRow) protected function generateSQLForSelectingDiffViewFromImportObservRow(array $importObservRow, $where = null) { $id = $importObservRow['id']; $tableName = $importObservRow['tableName']; Loading @@ -408,8 +418,17 @@ EOS; // Ex: "v.COLONNE = 'VALEUR'" ou "v.COLONNE IS NULL". $toValueCond = 'v.' . $sColName . ($toValue === null ? ' is null' : (" = '" . $toValue . "'")); // Eventuel filtre. $andWhere = $filter ? 'and ' . $filter : ''; // Eventuels filtres : celui de la table IMPORT_OBSERV + celui spécifié dans la config de la destination. $wheres = []; if ($filter) $wheres[] = sprintf('(%s)', $filter); if ($where) $wheres[] = sprintf('(%s)', str_ireplace('d.', 't.', $where)); $andWhere = $wheres ? 'and ' . implode(' and ', $wheres) : ''; // Colonne 'detail'. Ex: "coalesce(t.RESULTAT::varchar, '') || '>' || coalesce(v.RESULTAT::varchar, '')" $detail = 'coalesce(' . $this->tableHelper->generateSQLForCastToString("t.$columnName") . ", '')" . " || '>' || " . 'coalesce(' . $this->tableHelper->generateSQLForCastToString("v.$sColName") . ", '')"; // Construction de la requête recherchant dans la vue V_DIFF_X les lignes correspondant à : // une prise de valeur particulière spécifiée par IMPORT_OBSERV.TO_VALUE, Loading @@ -417,7 +436,7 @@ EOS; // dans la table spécifiée par IMPORT_OBSERV.TABLE_NAME. return <<<EOS select $id import_observ_id, v.source_code, t.$columnName || '>' || v.$sColName detail $detail detail from V_DIFF_$tableName v join $tableName t on t.source_code = v.source_code where $uColName = 1 and $toValueCond Loading @@ -426,25 +445,29 @@ EOS; } /** * @param DestinationInterface $destination * @param array $importObservRows * @return string */ public function generateSQLForInsertionIntoImportObservResult(array $importObservRows) public function generateSQLForInsertionIntoImportObservResult(DestinationInterface $destination, array $importObservRows) { $where = $destination->getWhere(); $now = $this->platform->getNowExpression(); $selects = []; foreach ($importObservRows as $importObservRow) { $selects[] = $this->generateSQLForSelectingDiffViewFromImportObservRow($importObservRow); $selects[] = $this->generateSQLForSelectingDiffViewFromImportObservRow($importObservRow, $where); } $selects = implode(PHP_EOL . 'UNION ALL' . PHP_EOL, $selects); $nextval = $this->tableHelper->generateSQLForSequenceNextVal('import_observ_result_id_seq'); return <<<EOS insert into import_observ_result (id, date_creation, import_observ_id, source_code, resultat) with tmp as ( $selects ) select import_observ_result_id_seq.nextval, $now, import_observ_id, source_code, detail select $nextval, $now, import_observ_id, source_code, detail from tmp EOS; } Loading Loading
.gitlab-ci.yml 0 → 100644 +14 −0 Original line number Diff line number Diff line image: registre.unicaen.fr:5000/unicaen-dev-php7.3-apache stages: - publish cache: key: ${CI_COMMIT_REF_SLUG} paths: - vendor/ update-satis: stage: publish script: - curl https://gest.unicaen.fr/packagist/update
Module.php +6 −6 Original line number Diff line number Diff line Loading @@ -39,16 +39,16 @@ class Module implements ConsoleUsageProviderInterface public function getConsoleUsage(AdapterInterface $console) { return [ 'run import --name=' => 'Lance un import par son nom (name)', ['--name', "Nom unique de l'import (clé 'name')"], 'run import [--name=<name>]' => 'Lance un import par son nom', ['<name>', "Nom unique de l'import (clé de config 'name')"], 'run import --all' => 'Lance tous les imports', 'run import' => 'Lance tous les imports', [], 'run synchro --name=' => 'Lance une synchronisation par son nom (name)', ['--name', "Nom unique de la synchronisation (clé 'name')"], 'run synchro [--name=<name>]' => 'Lance une synchronisation par son nom', ['<name>', "Nom unique de la synchronisation (clé de config 'name')"], 'run synchro --all' => 'Lance toutes les synchronisations', 'run synchro' => 'Lance toutes les synchronisations', [], ]; } Loading
config/module.config.php +25 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,11 @@ use UnicaenDbImport\Entity\Db\Service\ImportObserv\ImportObservService; use UnicaenDbImport\Entity\Db\Service\ImportObserv\ImportObservServiceFactory; use UnicaenDbImport\Entity\Db\Service\ImportObservResult\ImportObservResultService; use UnicaenDbImport\Entity\Db\Service\ImportObservResult\ImportObservResultServiceFactory; use UnicaenDbImport\Entity\Db\Service\Source\SourceService; use UnicaenDbImport\Entity\Db\Service\Source\SourceServiceFactory; use UnicaenDbImport\Entity\Db\Source; use UnicaenDbImport\ORM\Event\Listeners\SourceListener; use UnicaenDbImport\ORM\Event\Listeners\SourceListenerFactory; use UnicaenDbImport\Service\ApiService; use UnicaenDbImport\Service\ApiServiceFactory; use UnicaenDbImport\Service\CodeGeneratorPluginManager; Loading @@ -31,6 +36,9 @@ use UnicaenDbImport\Service\SynchroServiceFactory; return [ 'import' => [ 'source_entity_class' => Source::class, 'default_source_code' => 'app', 'import_observ_entity_class' => ImportObserv::class, 'import_observ_result_entity_class' => ImportObservResult::class, Loading @@ -41,6 +49,9 @@ return [ 'synchros' => [], ], 'UnicaenDbImport.Entity.Db.Source.dcm.xml', 'UnicaenDbImport.Entity.Db.Source.dcm.xml', 'doctrine' => [ 'driver' => [ 'orm_default' => [ Loading @@ -57,6 +68,13 @@ return [ ], ], ], 'eventmanager' => [ 'orm_default' => [ 'subscribers' => [ SourceListener::class, ], ], ], ], 'console' => [ Loading @@ -65,7 +83,7 @@ return [ 'execute_imports' => [ 'type' => 'simple', 'options' => [ 'route' => 'run import [--all|-a] [--name=]', 'route' => 'run import [--name=]', 'defaults' => [ 'controller' => 'UnicaenDbImport\Controller\Console', 'action' => 'runImport', Loading @@ -75,7 +93,7 @@ return [ 'execute_synchro' => [ 'type' => 'simple', 'options' => [ 'route' => 'run synchro [--all|-a] [--name=]', 'route' => 'run synchro [--name=]', 'defaults' => [ 'controller' => 'UnicaenDbImport\Controller\Console', 'action' => 'runSynchro', Loading @@ -95,16 +113,21 @@ return [ 'service_manager' => [ 'factories' => [ Config::class => ConfigFactory::class, ImportService::class => ImportServiceFactory::class, SynchroService::class => SynchroServiceFactory::class, FacadeService::class => FacadeServiceFactory::class, DatabaseService::class => DatabaseServiceFactory::class, ApiService::class => ApiServiceFactory::class, CodeGeneratorPluginManager::class => CodeGeneratorPluginManagerFactory::class, SourceService::class => SourceServiceFactory::class, ImportLogService::class => ImportLogServiceFactory::class, ImportObservService::class => ImportObservServiceFactory::class, ImportObservResultService::class => ImportObservResultServiceFactory::class, SourceListener::class => SourceListenerFactory::class, ], 'abstract_factories' => [ HelperAbstractFactory::class, Loading
config/unicaen-db-import.global.php.dist +19 −0 Original line number Diff line number Diff line Loading @@ -5,12 +5,24 @@ namespace Application; use \UnicaenDbImport\Entity\Db\Source; return [ 'import' => [ 'connections' => [ // Cf. `./unicaen-db-import.local.php.dist` ], // // Classe de l'entité Doctrine représentant une "Source". // 'source_entity_class' => Source::class, // // Code de la Source par défaut (injectée dans les entités implémentant SoucreAwareInterface). // 'default_source_code' => 'app', // // Alias éventuels des noms de colonnes d'historique. // Loading Loading @@ -105,6 +117,7 @@ return [ // - 'table' : nom de la table source contenant les données à importer // - 'select' : select SQL de mise en forme des données source à importer (NB: antinomique avec 'table') // - 'source_code_column' : nom de la colonne dans la table/vue source contenant l'identifiant unique // - 'where' : filtre SQL éventuel à appliquer aux données sources. // 'source' => [ 'name' => 'TABLE PAYS DE APOGÉE', Loading @@ -112,6 +125,7 @@ return [ //'table' => 'PAYS', // Équivalent de SELECT * FROM PAYS; 'connection' => 'apogee', 'source_code_column' => 'COD_PAY', //'where' => "TEM_OUV_DRT_SSO_PAY = 'N'", ], // // Configuration de la destination des données importées : Loading Loading @@ -157,12 +171,14 @@ return [ // - 'select' : select SQL de mise en forme des données source à importer (NB: antinomique avec 'table') // - 'connection' : identifiant de la connexion à la bdd source (cf. clé 'connections' plus haut) // - 'source_code_column' : nom de la colonne dans la table/vue source contenant l'identifiant unique // - 'where' : filtre éventuel à apliquer aux données sources // 'source' => [ 'name' => 'TABLE MES_PAYS_TEMPORAIRES', 'table' => 'MES_PAYS_TEMPORAIRES', 'connection' => 'default', 'source_code_column' => 'COD_PAY', //'where' => "TEM_OUV_DRT_SSO_PAY = 'N'", ], // Loading @@ -171,12 +187,15 @@ return [ // - 'connection' : identifiant de la connexion à la bdd destination (cf. clé 'connections' plus haut) // - 'table' : nom de la table destination vers laquelle les données sont synchronisées // - 'source_code_column' : nom de la colonne dans la table destination contenant l'identifiant unique // - 'where' : filtre SQL éventuel permettant de restreindre les données destinations concernées // (les noms de colonnes doivent être préfixés par l'alias de la table destination 'd') // 'destination' => [ 'name' => 'TABLE PAYS', 'table' => 'PAYS', 'connection' => 'default', 'source_code_column' => 'COD_PAY', //'where' => "d.TEM_OUV_DRT_SSO_PAY = 'N'", // // Forçage éventuel du nom de la table où seront inscrits les logs (créée automatiquement si nécessaire). // En l'absence de ce forçage, le nom de la table sera 'import_log'. Loading
src/UnicaenDbImport/CodeGenerator/CodeGenerator.php +36 −13 Original line number Diff line number Diff line Loading @@ -198,12 +198,17 @@ abstract class CodeGenerator implements CodeGeneratorInterface public function generateSQLForSelectFromSource(SourceInterface $source) { if ($source->getSelect()) { return $source->getSelect(); $query = $source->getSelect(); } else { $sourceTable = $source->getTable(); $query = $this->tableHelper->generateSQLForSelectFromTable($sourceTable); } $sourceTable = $source->getTable(); if ($where = $source->getWhere()) { $query = sprintf('SELECT * FROM (%s) tmp WHERE (%s)', $query, $where); } return $this->tableHelper->generateSQLForSelectFromTable($sourceTable); return $query; } /** Loading Loading @@ -313,6 +318,7 @@ abstract class CodeGenerator implements CodeGeneratorInterface { $destinationTable = $destination->getTable(); $idColumnSequence = $destination->getIdColumnSequence(); $where = $destination->getWhere(); $sourceCodeColumn = $source->getSourceCodeColumn(); $columns = $source->getColumns(); Loading @@ -331,19 +337,22 @@ abstract class CodeGenerator implements CodeGeneratorInterface $sql = $this->tableHelper->generateSQLForUpdateOperationInDestinationTable( $destinationTable, $sourceCodeColumn, $columns); $columns, $where); break; case Operation::OPERATION_DELETE; $sql = $this->tableHelper->generateSQLForDeleteOperationInDestinationTable( $destinationTable, $sourceCodeColumn, $columns); $columns, $where); break; case Operation::OPERATION_UNDELETE; $sql = $this->tableHelper->generateSQLForUndeleteOperationInDestinationTable( $destinationTable, $sourceCodeColumn, $columns); $columns, $where); break; default: throw new RuntimeException("Opération inattendue"); Loading Loading @@ -386,9 +395,10 @@ EOS; /** * @param array $importObservRow * @param string $where * @return string */ protected function generateSQLForSelectingDiffViewFromImportObservRow(array $importObservRow) protected function generateSQLForSelectingDiffViewFromImportObservRow(array $importObservRow, $where = null) { $id = $importObservRow['id']; $tableName = $importObservRow['tableName']; Loading @@ -408,8 +418,17 @@ EOS; // Ex: "v.COLONNE = 'VALEUR'" ou "v.COLONNE IS NULL". $toValueCond = 'v.' . $sColName . ($toValue === null ? ' is null' : (" = '" . $toValue . "'")); // Eventuel filtre. $andWhere = $filter ? 'and ' . $filter : ''; // Eventuels filtres : celui de la table IMPORT_OBSERV + celui spécifié dans la config de la destination. $wheres = []; if ($filter) $wheres[] = sprintf('(%s)', $filter); if ($where) $wheres[] = sprintf('(%s)', str_ireplace('d.', 't.', $where)); $andWhere = $wheres ? 'and ' . implode(' and ', $wheres) : ''; // Colonne 'detail'. Ex: "coalesce(t.RESULTAT::varchar, '') || '>' || coalesce(v.RESULTAT::varchar, '')" $detail = 'coalesce(' . $this->tableHelper->generateSQLForCastToString("t.$columnName") . ", '')" . " || '>' || " . 'coalesce(' . $this->tableHelper->generateSQLForCastToString("v.$sColName") . ", '')"; // Construction de la requête recherchant dans la vue V_DIFF_X les lignes correspondant à : // une prise de valeur particulière spécifiée par IMPORT_OBSERV.TO_VALUE, Loading @@ -417,7 +436,7 @@ EOS; // dans la table spécifiée par IMPORT_OBSERV.TABLE_NAME. return <<<EOS select $id import_observ_id, v.source_code, t.$columnName || '>' || v.$sColName detail $detail detail from V_DIFF_$tableName v join $tableName t on t.source_code = v.source_code where $uColName = 1 and $toValueCond Loading @@ -426,25 +445,29 @@ EOS; } /** * @param DestinationInterface $destination * @param array $importObservRows * @return string */ public function generateSQLForInsertionIntoImportObservResult(array $importObservRows) public function generateSQLForInsertionIntoImportObservResult(DestinationInterface $destination, array $importObservRows) { $where = $destination->getWhere(); $now = $this->platform->getNowExpression(); $selects = []; foreach ($importObservRows as $importObservRow) { $selects[] = $this->generateSQLForSelectingDiffViewFromImportObservRow($importObservRow); $selects[] = $this->generateSQLForSelectingDiffViewFromImportObservRow($importObservRow, $where); } $selects = implode(PHP_EOL . 'UNION ALL' . PHP_EOL, $selects); $nextval = $this->tableHelper->generateSQLForSequenceNextVal('import_observ_result_id_seq'); return <<<EOS insert into import_observ_result (id, date_creation, import_observ_id, source_code, resultat) with tmp as ( $selects ) select import_observ_result_id_seq.nextval, $now, import_observ_id, source_code, detail select $nextval, $now, import_observ_id, source_code, detail from tmp EOS; } Loading