Commit 3f5b8b64 authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Merge branch 'oracle_support' of https://git.unicaen.fr/lib/unicaen/db-import into oracle_support

parents fd2334a7 2afc8fed
......@@ -10,6 +10,7 @@ use UnicaenDbImport\CodeGenerator\Helper\TableHelper;
use UnicaenDbImport\CodeGenerator\Helper\TableValidationHelper;
use UnicaenDbImport\Config\ConfigAwareTrait;
use UnicaenDbImport\Domain\DestinationInterface;
use UnicaenDbImport\Domain\Operation;
use UnicaenDbImport\Domain\ResultInterface;
use UnicaenDbImport\Domain\SourceInterface;
......@@ -254,8 +255,8 @@ abstract class CodeGenerator implements CodeGeneratorInterface
/**
* @inheritDoc
*/
public function generateSQLForDestinationUpdateFromDiffViewRequestResult(
array $rows,
public function generateSQLForDestinationOperation(
$operation,
SourceInterface $source,
DestinationInterface $destination)
{
......@@ -264,12 +265,40 @@ abstract class CodeGenerator implements CodeGeneratorInterface
$sourceCodeColumn = $source->getSourceCodeColumn();
$columns = $source->getColumns();
return $this->tableHelper->generateSQLForOperationInDestinationTableFromDiffViewRequestResult(
$rows,
$destinationTable,
$sourceCodeColumn,
$columns,
$idColumnSequence);
// colonne ID écartée
$columns = array_diff($columns, ['ID', 'id']);
switch ($operation) {
case Operation::OPERATION_INSERT;
$sql = $this->tableHelper->generateSQLForInsertOperationInDestinationTable(
$destinationTable,
$sourceCodeColumn,
$columns,
$idColumnSequence);
break;
case Operation::OPERATION_UPDATE;
$sql = $this->tableHelper->generateSQLForUpdateOperationInDestinationTable(
$destinationTable,
$sourceCodeColumn,
$columns);
break;
case Operation::OPERATION_DELETE;
$sql = $this->tableHelper->generateSQLForDeleteOperationInDestinationTable(
$destinationTable,
$sourceCodeColumn,
$columns);
break;
case Operation::OPERATION_UNDELETE;
$sql = $this->tableHelper->generateSQLForUndeleteOperationInDestinationTable(
$destinationTable,
$sourceCodeColumn,
$columns);
break;
default:
throw new RuntimeException("Opération inattendue");
}
return $sql . PHP_EOL;
}
/**
......
......@@ -124,13 +124,13 @@ interface CodeGeneratorInterface
public function generateSQLForDiffViewSelect(SourceInterface $source, DestinationInterface $destination);
/**
* @param array $rows
* @param SourceInterface $source
* @param string $operation
* @param SourceInterface $source
* @param DestinationInterface $destination
* @return string
* @return string[]
*/
public function generateSQLForDestinationUpdateFromDiffViewRequestResult(
array $rows,
public function generateSQLForDestinationOperation(
$operation,
SourceInterface $source,
DestinationInterface $destination);
......
......@@ -65,7 +65,7 @@ EOT;
throw new RuntimeException("Type de résultat inattendu");
break;
}
$success = $result->getException() ? 0 : 1;
$success = $result->getFailure() ? 0 : 1;
$startDate = $result->getStartDate()->format("Y-m-d H:i:s");
$endDate = $result->getEndDate()->format("Y-m-d H:i:s");
......
......@@ -243,7 +243,7 @@ EOT;
* @param string $sourceCodeColumn
* @param string[] $columns
* @param string|null|false $idColumnSequence
* @return string
* @return string[]
*/
public function generateSQLForOperationInDestinationTableFromDiffViewRequestResult(
array $rows,
......@@ -272,16 +272,29 @@ EOT;
foreach ($operations as $operation) {
switch ($operation) {
case Operation::OPERATION_INSERT:
$sqls[] = $this->generateSQLForInsertOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns, $idColumnSequence) . ';' . PHP_EOL;
$sqls[] = $this->generateSQLForInsertOperationInDestinationTable(
$destinationTable,
$sourceCodeColumn,
$columns,
$idColumnSequence) . PHP_EOL;
break;
case Operation::OPERATION_UPDATE:
$sqls[] = $this->generateSQLForUpdateOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
$sqls[] = $this->generateSQLForUpdateOperationInDestinationTable(
$destinationTable,
$sourceCodeColumn,
$columns) . PHP_EOL;
break;
case Operation::OPERATION_UNDELETE:
$sqls[] = $this->generateSQLForUndeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
$sqls[] = $this->generateSQLForUndeleteOperationInDestinationTable(
$destinationTable,
$sourceCodeColumn,
$columns) . PHP_EOL;
break;
case Operation::OPERATION_DELETE:
$sqls[] = $this->generateSQLForDeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, $columns) . ';' . PHP_EOL;
$sqls[] = $this->generateSQLForDeleteOperationInDestinationTable(
$destinationTable,
$sourceCodeColumn,
$columns) . PHP_EOL;
break;
default:
throw new RuntimeException("Opération inconnue rencontrée : " . $operation);
......@@ -289,7 +302,8 @@ EOT;
}
}
return empty($sqls) ? '' : implode(PHP_EOL, $sqls);
// return empty($sqls) ? '' : implode(PHP_EOL, $sqls);
return $sqls;
}
/**
......@@ -363,7 +377,7 @@ EOT;
* @param string|null|false $idColumnSequence
* @return string
*/
protected function generateSQLForInsertOperationInDestinationTable(
public function generateSQLForInsertOperationInDestinationTable(
$destinationTable,
$sourceCodeColumn,
array $columns,
......@@ -502,7 +516,7 @@ EOT;
* @param array $columns
* @return string
*/
abstract protected function generateSQLForUpdateOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
abstract public function generateSQLForUpdateOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
/**
* @param string $destinationTable
......@@ -510,7 +524,7 @@ EOT;
* @param array $columns
* @return string
*/
abstract protected function generateSQLForUndeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
abstract public function generateSQLForUndeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
/**
* @param string $destinationTable
......@@ -518,5 +532,5 @@ EOT;
* @param array $columns
* @return string
*/
abstract protected function generateSQLForDeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
abstract public function generateSQLForDeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns);
}
\ No newline at end of file
......@@ -3,8 +3,6 @@
namespace UnicaenDbImport\CodeGenerator\Oracle;
use UnicaenDbImport\CodeGenerator\Oracle;
use UnicaenDbImport\Domain\DestinationInterface;
use UnicaenDbImport\Domain\SourceInterface;
use UnicaenDbImport\Platforms\OraclePlatform;
/**
......@@ -42,27 +40,6 @@ class CodeGenerator extends \UnicaenDbImport\CodeGenerator\CodeGenerator
'END;';
}
/**
* @inheritDoc
*/
public function generateSQLForDestinationUpdateFromDiffViewRequestResult(
array $rows,
SourceInterface $source,
DestinationInterface $destination)
{
$sql = parent::generateSQLForDestinationUpdateFromDiffViewRequestResult($rows, $source, $destination);
if ($sql === '') {
return '';
}
// les ; séparant les INSERT/MERGE perturbent le driver Oracle donc on met ça dans un bloc BEGIN END et miracle...
return
'BEGIN ' . PHP_EOL .
$sql . PHP_EOL .
'END;';
}
/**
* @inheritDoc
*/
......
......@@ -80,7 +80,7 @@ class TableHelper extends \UnicaenDbImport\CodeGenerator\Helper\TableHelper
/**
* {@inheritDoc}
*/
protected function generateSQLForUpdateOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns)
public function generateSQLForUpdateOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns)
{
return $this->generateSQLUpdate(Operation::OPERATION_UPDATE, $destinationTable, $sourceCodeColumn, $columns);
}
......@@ -88,7 +88,7 @@ class TableHelper extends \UnicaenDbImport\CodeGenerator\Helper\TableHelper
/**
* {@inheritDoc}
*/
protected function generateSQLForUndeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns)
public function generateSQLForUndeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns)
{
return $this->generateSQLUpdate(Operation::OPERATION_UNDELETE, $destinationTable, $sourceCodeColumn, $columns);
}
......@@ -96,7 +96,7 @@ class TableHelper extends \UnicaenDbImport\CodeGenerator\Helper\TableHelper
/**
* {@inheritDoc}
*/
protected function generateSQLForDeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns)
public function generateSQLForDeleteOperationInDestinationTable($destinationTable, $sourceCodeColumn, array $columns)
{
return $this->generateSQLUpdate(Operation::OPERATION_DELETE, $destinationTable, $sourceCodeColumn, $columns);
}
......
......@@ -61,7 +61,7 @@ class ConsoleController extends AbstractConsoleController
$result = $this->importService->runImport($import);
if ($exception = $result->getException()) {
if ($exception = $result->getFailure()) {
$this->getConsole()->writeLine("Une erreur a été rencontrée!", ColorInterface::RED);
$this->getConsole()->writeLine($exception->getMessage(), ColorInterface::RED);
if ($previous = $exception->getPrevious()) {
......@@ -101,7 +101,7 @@ class ConsoleController extends AbstractConsoleController
$result = $this->synchroService->runSynchro($synchro);
if ($exception = $result->getException()) {
if ($exception = $result->getFailure()) {
$this->getConsole()->writeLine("Une erreur a été rencontrée!", ColorInterface::RED);
$this->getConsole()->writeLine($exception->getMessage(), ColorInterface::RED);
if ($previous = $exception->getPrevious()) {
......
......@@ -14,11 +14,9 @@ class ImportResult extends Result
*/
public function setDestinationTablePopulateResult($count)
{
$data = [
'count' => $count,
'details' => null,
];
$this->setResultsForOperation($data, Operation::OPERATION_INSERT);
$this->setResultsByOperation([
Operation::OPERATION_INSERT => $count,
]);
}
/**
......
......@@ -4,16 +4,17 @@ namespace UnicaenDbImport\Domain;
use DateTime;
use Exception;
use UnicaenApp\Exception\RuntimeException;
abstract class Result implements ResultInterface
{
/**
* @var Exception
*/
private $exception;
private $failure;
/**
* @var array
* @var array [operation => int|Exception]
*/
private $resultsByOperation = [];
......@@ -27,9 +28,21 @@ abstract class Result implements ResultInterface
*/
private $endDate;
/**
* @param array $results
*/
public function setResultsByOperation(array $results)
{
foreach ($results as $operation => $result) {
/** @var int|Exception $result */
$this->resultsByOperation[$operation] = $result;
}
}
/**
* @param array $data
* @param string $operation
* @deprecated Le résultat pour une opération peut être une Exception !
*/
public function setResultsForOperation(array $data, $operation)
{
......@@ -39,17 +52,17 @@ abstract class Result implements ResultInterface
/**
* @return Exception
*/
public function getException()
public function getFailure()
{
return $this->exception;
return $this->failure;
}
/**
* @param Exception $exception
* @param Exception $failure
*/
public function setException(Exception $exception = null)
public function setFailure(Exception $failure = null)
{
$this->exception = $exception;
$this->failure = $failure;
}
/**
......@@ -90,7 +103,38 @@ abstract class Result implements ResultInterface
*/
public function toString($includeDetails = false)
{
if ($ex = $this->getException()) {
if (count($this->resultsByOperation) === 0) {
return "Aucune instruction exécutée.";
}
$str = '';
foreach ($this->resultsByOperation as $operation => $result) {
$str .= "# " . $operation . " : " . PHP_EOL;
if (is_array($result)) {
$str .= $result['count'] . " instructions exécutées.";
} elseif ($result instanceof Exception){
$str .= $result->getMessage();
if ($includeDetails) {
$str .= PHP_EOL . $result->getTraceAsString();
}
} elseif (is_int($result)) {
$str .= $result . " enregistrement(s).";
} else {
throw new RuntimeException("Type de résultat spécifié inattendu : " . gettype($result));
}
$str .= PHP_EOL;
}
return $str;
}
/**
* @param bool $includeDetails
* @return string
*/
public function toStringOld($includeDetails = false)
{
if ($ex = $this->getFailure()) {
return $ex->getMessage() . PHP_EOL . $ex->getTraceAsString();
}
......
......@@ -10,13 +10,13 @@ interface ResultInterface
/**
* @return Exception
*/
public function getException();
public function getFailure();
/**
* @param Exception $exception
* @param Exception $failure
* @return self
*/
public function setException(Exception $exception = null);
public function setFailure(Exception $failure = null);
/**
* @param DateTime $startDate
......
......@@ -11,6 +11,7 @@ class SynchroResult extends Result
/**
* @param $rows
* @deprecated Ce n'est pas vraiment le résultat de la synchro !
*/
public function setDiffViewRequestResult(array $rows)
{
......
......@@ -10,6 +10,7 @@ use Exception;
use UnicaenApp\Exception\RuntimeException;
use UnicaenDbImport\CodeGenerator\CodeGenerator;
use UnicaenDbImport\Domain\DestinationInterface;
use UnicaenDbImport\Domain\Operation;
use UnicaenDbImport\Domain\ResultInterface;
use UnicaenDbImport\Domain\SourceInterface;
use UnicaenDbImport\Entity\Db\Service\ImportObserv\ImportObservServiceAwareTrait;
......@@ -232,7 +233,11 @@ class DatabaseService
// create table
$sql = $this->codeGenerator->generateSQLForImportLogTableCreation($this->destination->getLogTable());
$this->queryExecutor->exec($sql, $connection);
try {
$this->queryExecutor->exec($sql, $connection);
} catch (DBALException $e) {
throw new RuntimeException("Erreur rencontrée lors de la création de la table de log", null, $e);
}
}
public function checkIntermediateTableNotExists($intermediateTable)
......@@ -252,26 +257,38 @@ class DatabaseService
{
$sql = $this->codeGenerator->generateSQLForIntermediateTableCreation($this->source, $this->destination, $intermediateTable);
$this->queryExecutor->exec($sql, $this->destination->getConnection());
try {
$this->queryExecutor->exec($sql, $this->destination->getConnection());
} catch (DBALException $e) {
throw new RuntimeException("Erreur rencontrée lors de la création de la table intermédiaire", null, $e);
}
}
public function dropIntermediateTable($intermediateTable)
{
$sql = $this->codeGenerator->generateSQLForIntermmediateTableDrop($intermediateTable);
$this->queryExecutor->exec($sql, $this->destination->getConnection());
try {
$this->queryExecutor->exec($sql, $this->destination->getConnection());
} catch (DBALException $e) {
throw new RuntimeException("Erreur rencontrée lors de la suppression de la table intermédiaire", null, $e);
}
}
public function truncateDestinationTable()
{
$sql = $this->codeGenerator->generateSQLForClearTable($this->destination->getTable());
$this->queryExecutor->exec($sql, $this->destination->getConnection());
try {
$this->queryExecutor->exec($sql, $this->destination->getConnection());
} catch (DBALException $e) {
$tableName = $this->destination->getTable();
throw new RuntimeException("Erreur rencontrée lors du vidage de la table destination $tableName", null, $e);
}
}
/**
* @return int
* @throws Exception
*/
public function populateDestinationTableFromSource()
{
......@@ -308,9 +325,14 @@ class DatabaseService
$insertsSQL = $this->codeGenerator->generateSQLForInsertIntoTable($tableName, $rows, $sourceCode, $idColumnSequence);
// insert into destination
$this->queryExecutor->exec($insertsSQL, $this->destination->getConnection()); //Exécution de la requêtes (inserts) dans la base destination
try {
//Exécution de la requêtes (inserts) dans la base destination
$count = $this->queryExecutor->exec($insertsSQL, $this->destination->getConnection());
} catch (DBALException $e) {
throw new RuntimeException("Erreur rencontrée lors de l'écriture dans la table $tableName", null, $e);
}
return count($rows);
return $count;
}
private function prepareSourceDataForDestination(array $row)
......@@ -334,7 +356,11 @@ class DatabaseService
throw new RuntimeException("Erreur rencontrées lors de la création de la vue diff", null, $e);
}
$this->queryExecutor->exec($sql, $this->destination->getConnection());
try {
$this->queryExecutor->exec($sql, $this->destination->getConnection());
} catch (DBALException $e) {
throw new RuntimeException("Erreur rencontrée lors de la création de la vue différentielle", null, $e);
}
}
/**
......@@ -355,7 +381,11 @@ class DatabaseService
if (!empty($importObservRows)) {
$sql = $this->codeGenerator->generateSQLForInsertionIntoImportObservResult($importObservRows);
$this->queryExecutor->exec($sql, $this->destination->getConnection());
try {
$this->queryExecutor->exec($sql, $this->destination->getConnection());
} catch (DBALException $e) {
throw new RuntimeException("Erreur rencontrée lors de l'écriture dans la table IMPORT_OBSERV_RESULT", null, $e);
}
}
}
......@@ -382,6 +412,57 @@ class DatabaseService
}
}
/**
* @return array [operation => int|Exception]
*/
public function updateDestination()
{
$results = [];
$sql = $this->codeGenerator->generateSQLForDestinationOperation(
Operation::OPERATION_INSERT,
$this->source,
$this->destination
);
$results[Operation::OPERATION_INSERT] = $this->executeSql($sql);
$sql = $this->codeGenerator->generateSQLForDestinationOperation(
Operation::OPERATION_UPDATE,
$this->source,
$this->destination
);
$results[Operation::OPERATION_UPDATE] = $this->executeSql($sql);
$sql = $this->codeGenerator->generateSQLForDestinationOperation(
Operation::OPERATION_DELETE,
$this->source,
$this->destination
);
$results[Operation::OPERATION_DELETE] = $this->executeSql($sql);
$sql = $this->codeGenerator->generateSQLForDestinationOperation(
Operation::OPERATION_UNDELETE,
$this->source,
$this->destination
);
$results[Operation::OPERATION_UNDELETE] = $this->executeSql($sql);
return $results;
}
/**
* @param string $sql
* @return DBALException|int
*/
private function executeSql($sql)
{
try {
return $this->queryExecutor->exec($sql, $this->destination->getConnection());
} catch (DBALException $e) {
return $e;
}
}
/**
* Requête la Source pour obtenir les données sources.
*
......@@ -415,6 +496,10 @@ class DatabaseService
$sql = $this->codeGenerator->generateSQLForInsertResultIntoLogTable($result, $importLogTable);
$this->queryExecutor->exec($sql, $this->destination->getConnection());
try {
$this->queryExecutor->exec($sql, $this->destination->getConnection());
} catch (DBALException $e) {
throw new RuntimeException("Erreur rencontrée lors de l'écriture des logs dans la table $importLogTable", null, $e);
}
}
}
\ No newline at end of file
......@@ -3,14 +3,15 @@
namespace UnicaenDbImport\Service;
use Doctrine\DBAL\Connection as DbConnection;
use Exception;
use stdClass;
use UnicaenApp\Exception\RuntimeException;
use UnicaenDbImport\Connection\ApiConnection;
use UnicaenDbImport\Domain\DestinationInterface;
use UnicaenDbImport\Domain\Exception\ConnectionException;
use UnicaenDbImport\Domain\ImportResult;
use UnicaenDbImport\Domain\ResultInterface;
use UnicaenDbImport\Domain\SourceInterface;
use UnicaenDbImport\Domain\SynchroResult;
use Zend\Log\Logger;