Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Application/AuditApplication.php
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace SetBased\Audit\Application;

use SetBased\Audit\Command\AboutCommand;
use SetBased\Audit\MySql\Command\AlterTableCommand;
use SetBased\Audit\MySql\Command\AuditCommand;
use SetBased\Audit\MySql\Command\DiffCommand;
use SetBased\Audit\MySql\Command\DropTriggersCommand;
Expand Down Expand Up @@ -38,6 +39,7 @@ protected function getDefaultCommands()
$commands[] = new AuditCommand();
$commands[] = new DiffCommand();
$commands[] = new DropTriggersCommand();
$commands[] = new AlterTableCommand();

return $commands;
}
Expand Down
252 changes: 252 additions & 0 deletions src/MySql/AuditAlter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
<?php
//----------------------------------------------------------------------------------------------------------------------
namespace SetBased\Audit\MySql;

use SetBased\Audit\MySql\Helper\MySqlAlterTableCodeStore;
use SetBased\Audit\MySql\Metadata\ColumnMetadata;
use SetBased\Audit\MySql\Metadata\MultiSourceColumnMetadata;
use SetBased\Audit\MySql\Metadata\TableColumnsMetadata;
use SetBased\Stratum\MySql\StaticDataLayer;

//----------------------------------------------------------------------------------------------------------------------
/**
* Class for executing auditing actions for tables.
*/
class AuditAlter
{
//--------------------------------------------------------------------------------------------------------------------
/**
* The metadata (additional) audit columns (as stored in the config file).
*
* @var array[]
*/
private $auditColumnsMetadata;

/**
* The names of all tables in audit schema.
*
* @var array
*/
private $auditSchemaTables;

/**
* Code store for alter table statement.
*
* @var MySqlAlterTableCodeStore
*/
private $codeStore;

/**
* The content of the configuration file.
*
* @var array
*/
private $config;

/**
* Config metadata columns.
*
* @var array
*/
private $configMetadata;

/**
* The names of all tables in data schema.
*
* @var array
*/
private $dataSchemaTables;

/**
* Array with columns for each table.
*
* @var array<string,AuditDiffTable>
*/
private $diffColumns;

//--------------------------------------------------------------------------------------------------------------------
/**
* Object constructor.
*
* @param array[] $config The content of the configuration file.
* @param array[] $configMetadata The content of the metadata file.
*/
public function __construct(&$config, $configMetadata)
{
$this->config = &$config;
$this->configMetadata = $configMetadata;
$this->codeStore = new MySqlAlterTableCodeStore();
}

//--------------------------------------------------------------------------------------------------------------------
/**
* Create Sql statement for alter table.
*
* @param string $tableName The table name.
* @param TableColumnsMetadata $columns Columns metadata for alter statement.
*/
public function createSqlStatement($tableName, $columns)
{
$editCharSet = false;
$charSet = '';
$this->codeStore->append(sprintf('ALTER TABLE %s CHANGE', $tableName));
$countMax = $columns->getNumberOfColumns();
$count = 1;
/** @var MultiSourceColumnMetadata $rowMetadata */
foreach ($columns->getColumns() as $columnName => $rowMetadata)
{
$columnProperties = $rowMetadata->getProperties();
/** @var ColumnMetadata $data */
$data = isset($columnProperties['data']) ? $columnProperties['data'] : null;
/** @var ColumnMetadata $config */
$config = isset($columnProperties['config']) ? $columnProperties['config'] : null;

$dataMetadata = isset($data) ? $data->getProperties() : null;
$configMetadata = isset($config) ? $config->getProperties() : null;

if (!isset($dataMetadata))
{
if (isset($configMetadata['character_set_name']))
{
$editCharSet = true;
$charSet = $configMetadata['character_set_name'];
}
$line = sprintf('%s %s %s', $columnName, $columnName, $configMetadata['column_type']);
if ($count!=$countMax) $line .= ',';
$this->codeStore->append($line);
}
else
{
if (isset($dataMetadata['character_set_name']))
{
$editCharSet = true;
$charSet = $dataMetadata['character_set_name'];
}
$line = sprintf('%s %s %s', $columnName, $columnName, $dataMetadata['column_type']);
if ($count!=$countMax) $line .= ',';
$this->codeStore->append($line);
}
$count++;
}
$this->codeStore->append(';');
if ($editCharSet)
{
$this->codeStore->append(sprintf('ALTER TABLE %s DEFAULT CHARACTER SET %s;', $tableName, $charSet));
}
}



//--------------------------------------------------------------------------------------------------------------------
/**
* The main method: executes the create alter table statement actions for tables.
*
* return string
*/
public function main()
{
$this->processData();

return $this->codeStore->getCode();
}

//--------------------------------------------------------------------------------------------------------------------
/**
* Computes the difference between data and audit tables.
*/
private function getDiff()
{
foreach ($this->dataSchemaTables as $table)
{
if ($this->config['tables'][$table['table_name']]['audit'])
{
$res = StaticDataLayer::searchInRowSet('table_name', $table['table_name'], $this->auditSchemaTables);
if (isset($res))
{
$this->diffColumns[$table['table_name']] = new AuditDiffTable($this->config['database']['data_schema'],
$this->config['database']['audit_schema'],
$table['table_name'],
$this->auditColumnsMetadata,
$this->configMetadata[$table['table_name']]);
}
}
}
}

//--------------------------------------------------------------------------------------------------------------------
/**
* Getting list of all tables from information_schema of database from config file.
*/
private function listOfTables()
{
$this->dataSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['data_schema']);

$this->auditSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['audit_schema']);
}

//--------------------------------------------------------------------------------------------------------------------
/**
* Work on data for each table.
*/
private function processData()
{
$this->resolveCanonicalAuditColumns();

$this->listOfTables();

$this->getDiff();

/** @var AuditDiffTable $diffTable */
foreach ($this->diffColumns as $tableName => $diffTable)
{
// Remove matching columns.
$columns = $diffTable->removeMatchingColumns(true);

$this->createSqlStatement($tableName, $columns);
}
}

//--------------------------------------------------------------------------------------------------------------------
/**
* Resolves the canonical column types of the audit table columns.
*/
private function resolveCanonicalAuditColumns()
{
if (empty($this->config['audit_columns']))
{
$this->auditColumnsMetadata = [];
}
else
{
$schema = $this->config['database']['audit_schema'];
$tableName = '_TMP_'.uniqid();
AuditDataLayer::createTemporaryTable($schema, $tableName, $this->config['audit_columns']);
$columns = AuditDataLayer::getTableColumns($schema, $tableName);
AuditDataLayer::dropTemporaryTable($schema, $tableName);

foreach ($this->config['audit_columns'] as $audit_column)
{
$key = StaticDataLayer::searchInRowSet('column_name', $audit_column['column_name'], $columns);

if ($columns[$key]['is_nullable']==='NO')
{
$columns[$key]['column_type'] = sprintf('%s not null', $columns[$key]['column_type']);
}
if (isset($audit_column['value_type']))
{
$columns[$key]['value_type'] = $audit_column['value_type'];
}
if (isset($audit_column['expression']))
{
$columns[$key]['expression'] = $audit_column['expression'];
}
}

$this->auditColumnsMetadata = $columns;
}
}

//--------------------------------------------------------------------------------------------------------------------
}

//----------------------------------------------------------------------------------------------------------------------
2 changes: 1 addition & 1 deletion src/MySql/AuditDiff.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ private function printDiff()
// Remove matching columns unless the full option is used.
if (!$this->full)
{
$columns = $diffTable->removeMatchingColumns();
$columns = $diffTable->removeMatchingColumns(false);
}

if ($columns->getNumberOfColumns()>0)
Expand Down
12 changes: 11 additions & 1 deletion src/MySql/AuditDiffTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ public function getDiffColumns()
/**
* Check full and return array without new or obsolete columns if full not set.
*
* @param bool $skipObsoleteNew Flag for skipping obsolete and new columns.
*
* @return TableColumnsMetadata
*/
public function removeMatchingColumns()
public function removeMatchingColumns($skipObsoleteNew)
{
$metadata = $this->diffColumns->getColumns();
/** @var MultiSourceColumnMetadata $column */
Expand All @@ -126,6 +128,10 @@ public function removeMatchingColumns()
}
}
}
elseif ($skipObsoleteNew)
{
$metadata->removeColumn($columnName);
}
}
else
{
Expand All @@ -137,6 +143,10 @@ public function removeMatchingColumns()
$metadata->removeColumn($columnName);
}
}
elseif ($skipObsoleteNew)
{
$metadata->removeColumn($columnName);
}
}
}

Expand Down
64 changes: 64 additions & 0 deletions src/MySql/Command/AlterTableCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
//----------------------------------------------------------------------------------------------------------------------
namespace SetBased\Audit\MySql\Command;

use SetBased\Audit\MySql\AuditAlter;
use SetBased\Stratum\Style\StratumStyle;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

//----------------------------------------------------------------------------------------------------------------------
/**
* Command for comparing data tables with audit tables.
*/
class AlterTableCommand extends AuditCommand
{
//--------------------------------------------------------------------------------------------------------------------
/**
* Check full full and return array without new or obsolete columns if full not set.
*
* @param array[] $columns The metadata of the columns of a table.
*
* @var StratumStyle
*/
protected $io;

//--------------------------------------------------------------------------------------------------------------------
/**
* {@inheritdoc}
*/
protected function configure()
{
$this->setName('alter-table-sql')
->setDescription('Create alter table SQL commands for audit tables columns that are different from the config columns or from columns data tables')
->addArgument('config file', InputArgument::OPTIONAL, 'The audit configuration file', 'etc/audit.json')
->addArgument('result sql file', InputArgument::OPTIONAL, 'The result file for SQL statement', 'etc/alter-table-sql-result.sql');
}

//--------------------------------------------------------------------------------------------------------------------
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->io = new StratumStyle($input, $output);

$resultSqlFile = $input->getArgument('result sql file');

$this->configFileName = $input->getArgument('config file');
$this->readConfigFile();

$this->connect($this->config);

$alter = new AuditAlter($this->config, $this->configMetadata);
$content = $alter->main();

$this->writeTwoPhases($resultSqlFile, $content);
}

//--------------------------------------------------------------------------------------------------------------------

}

//----------------------------------------------------------------------------------------------------------------------
Loading