Skip to content

Commit

Permalink
Merge pull request #19 from nutsh3ll/consider-table-references
Browse files Browse the repository at this point in the history
Consider table references
  • Loading branch information
howyi authored Sep 5, 2018
2 parents a41a5ea + 017584f commit 5f8721e
Showing 1 changed file with 122 additions and 49 deletions.
171 changes: 122 additions & 49 deletions src/Conv/DatabaseStructureFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@

namespace Conv;

use Conv\Util\Config;
use Conv\Factory\TableStructureFactory;
use Conv\Factory\ViewStructureFactory;
use Conv\Structure\ColumnStructure;
use Conv\Structure\DatabaseStructure;
use Conv\Structure\IndexStructure;
use Conv\Structure\TableStructureType;
use Conv\Util\Config;
use Conv\Util\Evaluator;
use Conv\Util\SchemaKey;
use Conv\Util\SchemaValidator;
use Howyi\Evi;
use Symfony\Component\Console\Helper\ProgressBar;

class DatabaseStructureFactory
{
private const TMP_DBNAME = 'conv_tmp';
private const TMP_DBNAME = 'conv_tmp';

/**
* @param string $path
Expand Down Expand Up @@ -85,51 +86,123 @@ public static function fromPDO(
return new DatabaseStructure($tableList);
}

/**
* @param \PDO $pdo Creatable DB
* @param string $path
* @param Operator $operator
* @param callable|null $filter
* @return DatabaseStructure
*/
public static function fromSqlDir(
\PDO $pdo,
string $path,
Operator $operator,
callable $filter = null
): DatabaseStructure {
$operator->output('<comment>Genarate temporary database</>');
$pdo->exec('DROP DATABASE IF EXISTS ' . self::TMP_DBNAME);
$pdo->exec('CREATE DATABASE ' . self::TMP_DBNAME);
$pdo->exec('USE ' . self::TMP_DBNAME);
$viewQueryList = [];
$progress = $operator->getProgress(count(glob("$path/*.sql")));
$progress->start();
foreach (new \DirectoryIterator($path) as $fileInfo) {
if (!$fileInfo->isFile()) {
continue;
}
if ('sql' !== strtolower($fileInfo->getExtension())) {
continue;
}
$query = file_get_contents($fileInfo->getRealPath());

if (false === strpos($query, 'CREATE ALGORITHM')) {
$pdo->exec($query);
$progress->advance();
} else {
$viewQueryList[] = $query;
}
}
foreach ($viewQueryList as $query) {
$pdo->exec($query);
$progress->advance();
}
$progress->finish();
$operator->output('');
$databaseStructure = self::fromPDO($pdo, self::TMP_DBNAME, $filter);
$pdo->exec('DROP DATABASE IF EXISTS ' . self::TMP_DBNAME);

return $databaseStructure;
}
/**
* @param \PDO $pdo Creatable DB
* @param string $path
* @param Operator $operator
* @param callable|null $filter
* @return DatabaseStructure
*/
public static function fromSqlDir(
\PDO $pdo,
string $path,
Operator $operator,
callable $filter = null
): DatabaseStructure {
$operator->output('<comment>Genarate temporary database</>');
$pdo->exec('DROP DATABASE IF EXISTS ' . self::TMP_DBNAME);
$pdo->exec('CREATE DATABASE ' . self::TMP_DBNAME);
$pdo->exec('USE ' . self::TMP_DBNAME);
$views = [];
$progress = $operator->getProgress(count(glob("$path/*.sql")));
$progress->start();
$ddls = [];
foreach (new \DirectoryIterator($path) as $fileInfo) {
if (!$fileInfo->isFile()) {
continue;
}
if ('sql' !== strtolower($fileInfo->getExtension())) {
continue;
}
$query = file_get_contents($fileInfo->getRealPath());
$ddl = new class($query, $pdo, $progress) {
private $query;
private $isView;
private $hasCreated = false;
private $references = [];
private $pdo;
private $progress;

/**
* @param string $query
* @param \PDO $pdo
* @param ProgressBar $progress
*/
public function __construct(string $query, \PDO $pdo, ProgressBar $progress)
{
$this->query = $query;
$this->isView = false !== strpos($query, 'CREATE ALGORITHM');
preg_match_all('/REFERENCES `?([a-zA-Z][a-zA-Z0-9_\ ]*?)`? /s', $query, $matches);
if (0 < count($matches[1])) {
$this->references = $matches[1];
}
$this->pdo = $pdo;
$this->progress = $progress;
}

/**
* @return bool
*/
public function isView(): bool
{
return $this->isView;
}

/**
* @return string[]
*/
public function getReferences(): array
{
return $this->references;
}

/**
* @return bool
*/
public function hasCreated(): bool
{
return $this->hasCreated;
}

public function create(): void
{
$this->pdo->exec($this->query);
$this->progress->advance();
$this->hasCreated = true;
}
};
$ddls[$fileInfo->getBaseName('.sql')] = $ddl;
}

foreach ($ddls as $name => $ddl) {
if ($ddl->isView()) {
$views[] = $ddl;
}
self::createTableRecursive($ddls, $name);
}

foreach ($views as $view) {
$view->create();
}
$progress->finish();
$operator->output('');
$databaseStructure = self::fromPDO($pdo, self::TMP_DBNAME, $filter);
$pdo->exec('DROP DATABASE IF EXISTS ' . self::TMP_DBNAME);

return $databaseStructure;
}

/**
* @param array $ddls
* @param string $current
*/
private static function createTableRecursive(array $ddls, string $current): void
{
if (!$ddls[$current]->hasCreated()) {
foreach ($ddls[$current]->getReferences() as $reference) {
self::createTableRecursive($ddls, $reference);
}
$ddls[$current]->create();
}
}
}

0 comments on commit 5f8721e

Please sign in to comment.