public function testGetTables() { $manager = ConnectionManager::getInstance(); $conn = $manager->getConnection('mysql'); $driver = $manager->getQueryDriver('mysql'); $conn->query("DROP TABLE IF EXISTS t1"); $conn->query("CREATE TABLE t1 (val enum('a','b','c') );"); $parser = new MysqlTableParser($driver, $conn); $tables = $parser->getTables(); $this->assertNotEmpty($tables); $schema = $parser->reverseTableSchema('t1'); $this->assertNotNull($schema); /* $sql = $parser->getTableSql('foo'); ok($sql); $columns = $parser->parseTableSql('foo'); $this->assertNotEmpty($columns); $columns = $parser->parseTableSql('bar'); $this->assertNotEmpty($columns); $schema = $parser->reverseTableSchema('bar'); $this->assertNotNull($schema); $id = $schema->getColumn('id'); $this->assertNotNull($id); $this->assertTrue($id->autoIncrement); $this->assertEquals('INTEGER',$id->type); $this->assertEquals('int',$id->isa); $this->assertTrue($id->primary); */ }
public function execute() { $options = $this->options; $logger = $this->logger; $id = $this->getCurrentDataSourceId(); $logger->debug("Finding schema classes..."); $schemas = $this->findSchemasByArguments(func_get_args()); $logger->debug("Initialize schema builder..."); $connectionManager = ConnectionManager::getInstance(); $conn = $connectionManager->getConnection($id); $driver = $connectionManager->getQueryDriver($id); $sqlBuilder = SqlBuilder::create($driver, array('rebuild' => $options->rebuild, 'clean' => $options->clean)); $builder = new DatabaseBuilder($conn, $sqlBuilder, $this->logger); $sqls = $builder->build($schemas); $sqlOutput = join("\n", $sqls); if ($file = $this->options->file) { $fp = fopen($file, 'w'); fwrite($fp, $sqlOutput); fclose($fp); } if ($this->options->basedata) { $collection = new SchemaCollection($schemas); $collection = $collection->evaluate(); $seedBuilder = new SeedBuilder($this->getConfigLoader(), $this->logger); $seedBuilder->build($collection); } $time = time(); $logger->info("Setting migration timestamp to {$time}"); $metadata = new Metadata($driver, $conn); // update migration timestamp $metadata['migration'] = $time; $logger->info($logger->formatter->format('Done. ' . count($schemas) . " schema tables were generated into data source '{$id}'.", 'green')); }
public static function createWithDataSource($dsId) { $connm = ConnectionManager::getInstance(); $connection = $connm->getConnection($dsId); $driver = $connm->getQueryDriver($dsId); return new self($driver, $connection); }
public function __construct($dsIds) { $c = ServiceContainer::getInstance(); $this->logger = $c['logger']; $this->connectionManager = ConnectionManager::getInstance(); // XXX: get data source id list from config loader $this->dataSourceIds = (array) $dsIds; }
public function execute() { $options = $this->options; $logger = $this->logger; $configLoader = $this->getConfigLoader(true); $id = $this->getCurrentDataSourceId(); $logger->debug('Finding schema classes...'); $schemas = SchemaUtils::findSchemasByArguments($configLoader, func_get_args(), $this->logger); $logger->debug('Initialize schema builder...'); if ($output = $this->options->output) { $dataSourceConfig = $configLoader->getDataSource($id); $driverType = $dataSourceConfig['driver']; switch ($driverType) { case 'sqlite': $driver = new SQLiteDriver(); break; case 'mysql': $driver = new MySQLDriver(); break; case 'pgsql': $driver = new PgSQLDriver(); break; default: throw new Exception("Unsupported driver type: {$driverType}"); break; } $sqlBuilder = SqlBuilder::create($driver, ['rebuild' => $options->rebuild, 'clean' => $options->clean]); $fp = fopen($output, 'w'); foreach ($schemas as $schema) { $sqls = $sqlBuilder->buildTable($schema); fwrite($fp, implode("\n", $sqls)); $sqls = $sqlBuilder->buildIndex($schema); fwrite($fp, implode("\n", $sqls)); $sqls = $sqlBuilder->buildForeignKeys($schema); fwrite($fp, implode("\n", $sqls)); } fclose($fp); $this->logger->warn('Warning: seeding is not supported when using --output option.'); } else { $connectionManager = ConnectionManager::getInstance(); $conn = $connectionManager->getConnection($id); $driver = $connectionManager->getQueryDriver($id); $sqlBuilder = SqlBuilder::create($driver, ['rebuild' => $options->rebuild, 'clean' => $options->clean]); $bootstrap = new Bootstrap($conn, $sqlBuilder, $this->logger); $bootstrap->build($schemas); if ($this->options->basedata) { $bootstrap->seed($schemas, $configLoader); } $time = time(); $logger->info("Setting migration timestamp to {$time}"); $metadata = new Metadata($conn, $driver); // update migration timestamp $metadata['migration'] = $time; $logger->info($logger->formatter->format('Done. ' . count($schemas) . " schema tables were generated into data source '{$id}'.", 'green')); } }
public function execute() { // support for schema file or schema class names $options = $this->options; $logger = $this->logger; $dataSource = $this->getCurrentDataSourceId(); $connectionManager = \LazyRecord\ConnectionManager::getInstance(); $this->createDB($connectionManager->getDataSource($dataSource)); $this->logger->info('Done'); }
public function setUp() { $annnotations = $this->getAnnotations(); $configLoader = ConfigLoader::getInstance(); $configLoader->loadFromSymbol(true); $configLoader->setDefaultDataSourceId($this->getDriverType()); $connManager = ConnectionManager::getInstance(); $connManager->init($configLoader); try { $dbh = $connManager->getConnection($this->getDriverType()); } catch (PDOException $e) { if ($this->allowConnectionFailure) { $this->markTestSkipped(sprintf("Can not connect to database by data source '%s' message:'%s' config:'%s'", $this->getDriverType(), $e->getMessage(), var_export($configLoader->getDataSource($this->getDriverType()), true))); return; } else { echo sprintf("Can not connect to database by data source '%s' message:'%s' config:'%s'", $this->getDriverType(), $e->getMessage(), var_export($configLoader->getDataSource($this->getDriverType()), true)); throw $e; } } $driver = $connManager->getQueryDriver($this->getDriverType()); $this->assertInstanceOf('SQLBuilder\\Driver\\BaseDriver', $driver, 'QueryDriver object OK'); // Rebuild means rebuild the database for new tests $rebuild = true; $basedata = true; if (isset($annnotations['method']['rebuild'][0]) && $annnotations['method']['rebuild'][0] == 'false') { $rebuild = false; } if (isset($annnotations['method']['basedata'][0]) && $annnotations['method']['basedata'][0] == 'false') { $basedata = false; } if ($rebuild) { $builder = SqlBuilder::create($driver, array('rebuild' => true)); $this->assertNotNull($builder); // $schemas = ClassUtils::schema_classes_to_objects($this->getModels()); $schemas = ClassUtils::schema_classes_to_objects($this->getModels()); foreach ($schemas as $schema) { $sqls = $builder->build($schema); $this->assertNotEmpty($sqls); foreach ($sqls as $sql) { $dbh->query($sql); } } if ($basedata) { $runner = new SeedBuilder($this->config, $this->logger); foreach ($schemas as $schema) { $runner->buildSchemaSeeds($schema); } if ($scripts = $this->config->getSeedScripts()) { foreach ($scripts as $script) { $runner->buildScriptSeed($script); } } } } }
public function getRuleLoader() { if ($this->ruleLoader) { return $this->ruleLoader; } $dataSource = $this->options['RuleLoader']['PDORuleLoader']['DataSource']; $connectionManager = ConnectionManager::getInstance(); $conn = $connectionManager->getConnection($dataSource); $this->ruleLoader = new PDORuleLoader(); $this->ruleLoader->load($conn); return $this->ruleLoader; }
public function setUp() { $annnotations = $this->getAnnotations(); $connManager = ConnectionManager::getInstance(); $dataSourceConfig = self::createDataSourceConfig($this->driver); if ($dataSourceConfig) { $connManager->addDataSource('default', $dataSourceConfig); } else { $this->markTestSkipped("{$this->driver} database configuration is missing."); } try { $dbh = $connManager->getConnection('default'); } catch (PDOException $e) { $this->markTestSkipped('Can not connect to database, test skipped: ' . $e->getMessage()); return; } $driver = ConnectionManager::getInstance()->getQueryDriver('default'); ok($driver, 'QueryDriver object OK'); // Rebuild means rebuild the database for new tests $rebuild = true; $basedata = true; if (isset($annnotations['method']['rebuild'][0]) && $annnotations['method']['rebuild'][0] == 'false') { $rebuild = false; } if (isset($annnotations['method']['basedata'][0]) && $annnotations['method']['basedata'][0] == 'false') { $basedata = false; } if ($rebuild) { $builder = SqlBuilder::create($driver, array('rebuild' => true)); $this->assertNotNull($builder); // $schemas = ClassUtils::schema_classes_to_objects($this->getModels()); $schemas = ClassUtils::schema_classes_to_objects($this->getModels()); foreach ($schemas as $schema) { $sqls = $builder->build($schema); $this->assertNotEmpty($sqls); foreach ($sqls as $sql) { $dbh->query($sql); } } if ($basedata) { $runner = new SeedBuilder($this->config, $this->logger); foreach ($schemas as $schema) { $runner->buildSchemaSeeds($schema); } if ($scripts = $this->config->getSeedScripts()) { foreach ($scripts as $script) { $runner->buildScriptSeed($script); } } } } }
public function register($kernel, $options = array()) { $config = $kernel->config->stashes['database']; $loader = \LazyRecord\ConfigLoader::getInstance(); if (!$loader->loaded) { $loader->load($config); $loader->init(); // init data source and connection } $kernel->db = function () { return ConnectionManager::getInstance()->getConnection(); }; }
public function register(Kernel $kernel, $options = array()) { // TODO: move to generate prepare... $loader = \LazyRecord\ConfigLoader::getInstance(); if (!$loader->loaded) { $loader->load($this->config); $loader->init(); // init data source and connection } $kernel->db = function () { return ConnectionManager::getInstance()->getConnection('default'); }; }
public function execute() { $dsId = $this->getCurrentDataSourceId(); $connectionManager = ConnectionManager::getInstance(); $conn = $connectionManager->getConnection($dsId); $driver = $connectionManager->getQueryDriver($dsId); $runner = new MigrationRunner($this->logger, $dsId); $runner->load($this->options->{'script-dir'} ?: 'db/migrations'); $scripts = $runner->getUpgradeScripts($conn, $driver); $count = count($scripts); $this->logger->info('Found ' . $count . ($count > 1 ? ' migration scripts' : ' migration script') . ' to be executed.'); foreach ($scripts as $script) { $this->logger->info('- ' . $script, 1); } }
public function execute() { $formatter = new \CLIFramework\Formatter(); $options = $this->options; $logger = $this->logger; $connectionManager = \LazyRecord\ConnectionManager::getInstance(); $dsId = $this->getCurrentDataSourceId(); $conn = $connectionManager->getConnection($dsId); $driver = $connectionManager->getQueryDriver($dsId); $this->logger->info('Performing Comparison...'); $parser = TableParser::create($driver, $conn); $existingTables = $parser->getTables(); $tableSchemas = $parser->getDeclareSchemaMap(); $found = false; $comparator = new Comparator(); foreach ($tableSchemas as $table => $currentSchema) { $this->logger->debug("Checking table {$table}"); $ref = new ReflectionObject($currentSchema); $filepath = $ref->getFilename(); $filepath = substr($filepath, strlen(getcwd()) + 1); if (in_array($table, $existingTables)) { $before = $parser->reverseTableSchema($table); $diffs = $comparator->compare($before, $currentSchema); if (count($diffs)) { $found = true; $printer = new ComparatorConsolePrinter($diffs); $printer->beforeName = $table . ":data source [{$dsId}]"; $printer->afterName = $table . ':' . $filepath; $printer->output(); } } else { $msg = sprintf("+ table %-20s %s", "'" . $table . "'", $filepath); echo $formatter->format($msg, 'green'), "\n"; $a = isset($tableSchemas[$table]) ? $tableSchemas[$table] : null; $diff = $comparator->compare(new DeclareSchema(), $currentSchema); foreach ($diff as $diffItem) { echo " ", $diffItem->toColumnAttrsString(), "\n"; } $found = true; } } if (!$found) { $this->logger->info("No diff found"); } }
public function insertIntoDataSource($schema) { $connManager = LazyRecord\ConnectionManager::getInstance(); $configLoader = ConfigLoader::getInstance(); $configLoader->loadFromSymbol(true); $connManager->init($configLoader); $pdo = $connManager->getConnection(self::getCurrentDriverType()); $this->assertInstanceOf('PDO', $pdo); $queryDriver = $connManager->getQueryDriver(self::getCurrentDriverType()); $builder = SqlBuilder::create($queryDriver, array('rebuild' => true)); $builder->build($schema); $sqls = $builder->build($schema); $this->assertNotEmpty($sqls); foreach ($sqls as $sql) { $this->assertQueryOK($pdo, $sql); } $this->assertTableExists($pdo, $schema->getTable()); }
/** * @dataProvider driverTypeDataProvider */ public function testTableParserFor($driverType) { $config = self::createNeutralConfigLoader(); $manager = ConnectionManager::getInstance(); $manager->free(); $this->registerDataSource($driverType); $conn = $manager->getConnection($driverType); $driver = $manager->getQueryDriver($driverType); $parser = TableParser::create($driver, $conn); $tables = $parser->getTables(); $this->assertNotNull($tables); foreach ($tables as $table) { $this->assertNotNull($table); $schema = $parser->reverseTableSchema($table); $this->assertNotNull($schema); $columns = $schema->getColumns(); $this->assertNotEmpty($columns); } }
public function testMigrationByDiff() { if ($this->getDriverType() == 'sqlite') { $this->markTestSkipped('sqlite migration tests skipped'); return; } $connectionManager = ConnectionManager::getInstance(); $pdo = $connectionManager->getConnection($this->getDriverType()); $pdo->query('DROP TABLE IF EXISTS users'); $pdo->query('DROP TABLE IF EXISTS test'); $pdo->query('CREATE TABLE users (account VARCHAR(128) UNIQUE)'); if (!file_exists('tests/migrations_testing')) { mkdir('tests/migrations_testing'); } $generator = new MigrationGenerator(Console::getInstance()->getLogger(), 'tests/migrations_testing'); ok(class_exists('TestApp\\Model\\UserSchema', true)); $finder = new SchemaFinder(); $finder->find(); list($class, $path) = $generator->generateWithDiff('DiffMigration', $this->getDriverType(), [new TestApp\Model\UserSchema()], '20120101'); require_once $path; ok($class::getId()); /* $userSchema = new TestApp\Model\UserSchema; $column = $userSchema->getColumn('account'); */ /* */ // run migration $runner = new MigrationRunner($this->getDriverType()); $runner->resetMigrationId($this->getDriverType()); $runner->load('tests/migrations_testing'); // XXX: PHPUnit can't run this test in separated unit test since // there is a bug of serializing the global array, this assertion will get 5 instead of the expected 1. $scripts = $runner->getMigrationScripts(); $this->assertNotEmpty($scripts); // $this->assertCount(1, $scripts); // $this->expectOutputRegex('#DiffMigration_1325347200#'); $runner->runUpgrade([$class]); # echo file_get_contents($path); unlink($path); $pdo->query('DROP TABLE IF EXISTS users'); }
public function __construct($name = null, array $data = array(), $dataName = '') { parent::__construct($name, $data, $dataName); if (!extension_loaded('pdo')) { return $this->markTestSkipped('pdo extension is required for model testing'); } // The config loader is used to initialize connection manager $this->config = ConfigLoader::getInstance(); $this->config->loadFromSymbol(true); $this->config->setDefaultDataSourceId($this->getDataSource()); // Always true $configStash = $this->config->getConfigStash(); $cnofigStash['schema']['auto_id'] = true; // free and override default connection $this->connManager = ConnectionManager::getInstance(); $this->connManager->init($this->config); // $config = self::createNeutralConfigLoader(); $this->logger = new Logger(); $this->logger->setQuiet(); }
/** * Get PDO connection for reading data. * * @return PDO */ public function getReadConnection() { return ConnectionManager::getInstance()->getConnection($this->getReadSourceId()); }
/** * load data sources to connection manager */ public function loadDataSources() { // load data source into connection manager $manager = ConnectionManager::getInstance(); foreach ($this->getDataSources() as $sourceId => $ds) { $manager->addDataSource($sourceId, $ds); } }
public function registerDataSource($driverType) { $connManager = ConnectionManager::getInstance(); if ($dataSource = BaseTestCase::createDataSourceConfig($driverType)) { $connManager->addDataSource($driverType, $dataSource); } else { $this->markTestSkipped("Data source for {$driverType} is undefined"); } }
/** * Get PDO connection for reading data. * * @return PDO */ public function getReadConnection() { return $this->_readConnection ? $this->_readConnection : ($this->_readConnection = ConnectionManager::getInstance()->getConnection($this->readSourceId)); }
public function tearDown() { $connm = ConnectionManager::getInstance(); $connm->removeDataSource('default'); $connm->close('default'); }
/** * load data sources to connection manager */ public function loadDataSources() { // load data source into connection manager $manager = ConnectionManager::getInstance(); $manager->init($this); }
public function generateWithDiff($taskName, $dataSourceId, array $schemas, $time = null) { $connectionManager = \LazyRecord\ConnectionManager::getInstance(); $connection = $connectionManager->getConnection($dataSourceId); $driver = $connectionManager->getQueryDriver($dataSourceId); $parser = TableParser::create($connection, $driver); $tableSchemas = $schemas; $existingTables = $parser->getTables(); $this->logger->info('Found ' . count($schemas) . ' schemas to compare.'); $template = $this->createClassTemplate($taskName, $time); $upgradeMethod = $template->addMethod('public', 'upgrade', array(), ''); $downgradeMethod = $template->addMethod('public', 'downgrade', array(), ''); $comparator = new Comparator($driver); // schema from runtime foreach ($tableSchemas as $key => $a) { $table = is_numeric($key) ? $a->getTable() : $key; if (!in_array($table, $existingTables)) { $this->logger->info(sprintf("Found schema '%s' to be imported to '%s'", $a, $table), 1); // generate create table statement. // use sqlbuilder to build schema sql $upcall = new MethodCallExpr('$this', 'importSchema', [new Raw('new ' . get_class($a))]); $upgradeMethod->getBlock()->appendLine(new Statement($upcall)); $downcall = new MethodCallExpr('$this', 'dropTable', [$table]); $downgradeMethod->getBlock()->appendLine(new Statement($downcall)); continue; } // revsersed schema $b = $parser->reverseTableSchema($table, $a); $diffs = $comparator->compare($b, $a); if (empty($diffs)) { continue; } // generate alter table statement. foreach ($diffs as $diff) { switch ($diff->flag) { case 'A': $alterTable = new AlterTableQuery($table); $alterTable->addColumn($diff->getAfterColumn()); $this->appendQueryStatement($upgradeMethod, $driver, $alterTable, new ArgumentArray()); $alterTable = new AlterTableQuery($table); $alterTable->dropColumn($diff->getAfterColumn()); $this->appendQueryStatement($downgradeMethod, $driver, $alterTable, new ArgumentArray()); break; case 'M': $alterTable = new AlterTableQuery($table); $after = $diff->getAfterColumn(); $before = $diff->getBeforeColumn(); if (!$after || !$before) { throw new LogicException('afterColumn or beforeColumn is undefined.'); } // Check primary key if ($before->primary != $after->primary) { // primary key requires another sub-statement "ADD PRIMARY KEY .." $alterTable->add()->primaryKey([$after->name]); } $alterTable->modifyColumn($after); $this->appendQueryStatement($upgradeMethod, $driver, $alterTable, new ArgumentArray()); $alterTable = new AlterTableQuery($table); $alterTable->modifyColumn($before); $this->appendQueryStatement($downgradeMethod, $driver, $alterTable, new ArgumentArray()); break; case 'D': $alterTable = new AlterTableQuery($table); $alterTable->dropColumnByName($diff->name); $this->appendQueryStatement($upgradeMethod, $driver, $alterTable, new ArgumentArray()); $alterTable = new AlterTableQuery($table); $alterTable->addColumn($diff->getBeforeColumn()); $this->appendQueryStatement($downgradeMethod, $driver, $alterTable, new ArgumentArray()); break; default: $this->logger->warn('** unsupported flag.'); continue; } } } $filename = $this->generateFilename($taskName, $time); $path = $this->migrationDir . DIRECTORY_SEPARATOR . $filename; if (false === file_put_contents($path, $template->render())) { throw new RuntimeException("Can't write migration script to {$path}."); } return array($template->class->name, $path); }
public function __construct($name = NULL, array $data = array(), $dataName = '') { parent::__construct($name, $data, $dataName); if (!extension_loaded('pdo')) { $this->markTestSkipped('pdo extension is required for model testing'); return; } // free and override default connection ConnectionManager::getInstance()->free(); $config = self::createNeutralConfigLoader(); $this->setConfig($config); $this->logger = new Logger(); $this->logger->setQuiet(); if (method_exists($this, 'getModels')) { $generator = new SchemaGenerator($this->config, $this->logger); $schemas = ClassUtils::schema_classes_to_objects($this->getModels()); $classMap = $generator->generate($schemas); } }
<?php use LazyRecord\Schema\SchemaGenerator; use LazyRecord\Schema\SchemaLoader; use LazyRecord\ConfigLoader; use LazyRecord\ConnectionManager; define('ROOT', dirname(__DIR__)); $loader = (require ROOT . '/vendor/autoload.php'); $loader->add(null, ROOT . '/tests'); $config = ConfigLoader::getInstance(); $config->loadFromArray(array('bootstrap' => ['tests/bootstrap.php'], 'schema' => ['auto_id' => 1, 'paths' => ['tests']], 'data_source' => ['default' => 'sqlite', 'nodes' => ['sqlite' => ['dsn' => 'sqlite::memory:', 'user' => NULL, 'pass' => NULL]]])); $connectionManager = ConnectionManager::getInstance(); $connectionManager->init($config); $logger = new CLIFramework\Logger(); // $logger->setQuiet(); $logger->info("Updating schema class files..."); $schemas = array(new \User\Model\UserSchema(), new \OrderBundle\Model\OrderSchema(), new \OrderBundle\Model\OrderItemSchema()); $g = new \LazyRecord\Schema\SchemaGenerator($config, $logger); $g->setForceUpdate(true); $g->generate($schemas); /** * Clean up cache files */ const CACHE_DIR = 'src/ActionKit/Cache'; const UPLOAD_DIR = 'tests/upload'; if (file_exists(CACHE_DIR)) { futil_rmtree(CACHE_DIR); mkdir(CACHE_DIR, 0755, true); } else { mkdir(CACHE_DIR, 0755, true); }
public function getCurrentConnection() { $dataSource = $this->getCurrentDataSourceId(); $connectionManager = ConnectionManager::getInstance(); return $connectionManager->getConnection($dataSource); }
public function generateWithDiff($taskName, $dataSourceId, $schemas, $time = null) { $connectionManager = \LazyRecord\ConnectionManager::getInstance(); $connection = $connectionManager->getConnection($dataSourceId); $driver = $connectionManager->getQueryDriver($dataSourceId); $parser = TableParser::create($driver, $connection); $tableSchemas = $parser->getTableSchemaMap(); $this->logger->info('Found ' . count($schemas) . ' schemas to compare.'); $template = $this->createClassTemplate($taskName, $time); $template->useClass('SQLBuilder\\Universal\\Syntax\\Column'); $upgradeMethod = $template->addMethod('public', 'upgrade', array(), ''); $downgradeMethod = $template->addMethod('public', 'downgrade', array(), ''); $comparator = new Comparator(); // schema from runtime foreach ($schemas as $b) { $tableName = $b->getTable(); $foundTable = isset($tableSchemas[$tableName]); if ($foundTable) { $a = $tableSchemas[$tableName]; // schema object, extracted from database. $diffs = $comparator->compare($a, $b); // generate alter table statement. foreach ($diffs as $diff) { if ($diff->flag == 'A') { $this->logger->info(sprintf("'%s': add column %s", $tableName, $diff->name), 1); $column = $diff->getAfterColumn(); $upcall = new MethodCallExpr('$this', 'addColumn', [$tableName, $column]); $upgradeMethod[] = new Statement($upcall); $downcall = new MethodCallExpr('$this', 'dropColumnByName', [$tableName, $diff->name]); $downgradeMethod[] = new Statement($downcall); } else { if ($diff->flag == 'D') { $upcall = new MethodCallExpr('$this', 'dropColumnByName', [$tableName, $diff->name]); $upgradeMethod->getBlock()->appendLine(new Statement($upcall)); } else { if ($diff->flag == 'M') { if ($afterColumn = $diff->getAfterColumn()) { $upcall = new MethodCallExpr('$this', 'modifyColumn', [$tableName, $afterColumn]); $upgradeMethod[] = new Statement($upcall); } else { throw new \Exception("afterColumn is undefined."); } continue; } else { $this->logger->warn("** unsupported flag."); continue; } } } } } else { $this->logger->info(sprintf("Found schema '%s' to be imported to '%s'", $b, $tableName), 1); // generate create table statement. // use sqlbuilder to build schema sql $upcall = new MethodCallExpr('$this', 'importSchema', [new Raw('new ' . get_class($b))]); $upgradeMethod->getBlock()->appendLine(new Statement($upcall)); $downcall = new MethodCallExpr('$this', 'dropTable', [$tableName]); $downgradeMethod->getBlock()->appendLine(new Statement($downcall)); } } $filename = $this->generateFilename($taskName, $time); $path = $this->migrationDir . DIRECTORY_SEPARATOR . $filename; if (false === file_put_contents($path, $template->render())) { throw new RuntimeException("Can't write migration script to {$path}."); } return array($template->class->name, $path); }
/** * Load Collection from a SQL query statement. * * @param string $sql * @param array $args * @param string $dsId */ public function loadQuery($sql, array $args = array(), $dsId = null) { if (!$dsId) { $dsId = $this->getSchema()->getReadSourceId(); } $this->handle = ConnectionManager::getInstance()->getConnection($dsId)->prepareAndExecute($sql, $args); }
public static function create(DeclareSchema $schema, $baseClass) { $cTemplate = new ClassFile($schema->getBaseModelClass()); $cTemplate->useClass('LazyRecord\\Schema\\SchemaLoader'); $cTemplate->useClass('LazyRecord\\Result'); $cTemplate->useClass('SQLBuilder\\Bind'); $cTemplate->useClass('SQLBuilder\\ArgumentArray'); $cTemplate->useClass('PDO'); $cTemplate->useClass('SQLBuilder\\Universal\\Query\\InsertQuery'); $cTemplate->addConsts(array('SCHEMA_PROXY_CLASS' => $schema->getSchemaProxyClass(), 'COLLECTION_CLASS' => $schema->getCollectionClass(), 'MODEL_CLASS' => $schema->getModelClass(), 'TABLE' => $schema->getTable(), 'READ_SOURCE_ID' => $schema->getReadSourceId(), 'WRITE_SOURCE_ID' => $schema->getWriteSourceId(), 'PRIMARY_KEY' => $schema->primaryKey)); $cTemplate->addProtectedProperty('table', $schema->getTable()); $cTemplate->addPublicProperty('readSourceId', $schema->getReadSourceId() ?: 'default'); $cTemplate->addPublicProperty('writeSourceId', $schema->getWriteSourceId() ?: 'default'); $cTemplate->addMethod('public', 'getSchema', [], ['if ($this->_schema) {', ' return $this->_schema;', '}', 'return $this->_schema = SchemaLoader::load(' . var_export($schema->getSchemaProxyClass(), true) . ');']); $cTemplate->addStaticVar('column_names', $schema->getColumnNames()); $cTemplate->addStaticVar('column_hash', array_fill_keys($schema->getColumnNames(), 1)); $cTemplate->addStaticVar('mixin_classes', array_reverse($schema->getMixinSchemaClasses())); if ($traitClasses = $schema->getModelTraitClasses()) { foreach ($traitClasses as $traitClass) { $cTemplate->useTrait($traitClass); } } $schemaReflection = new ReflectionClass($schema); $schemaDocComment = $schemaReflection->getDocComment(); // TODO: apply settings from schema... $codegenSettings = []; preg_match_all('/@codegen (\\w+)(?:\\s*=\\s*(\\S+))?$/m', $schemaDocComment, $allMatches); for ($i = 0; $i < count($allMatches[0]); $i++) { $key = $allMatches[1][$i]; $value = $allMatches[2][$i]; if ($value === "") { $value = true; } else { if (strcasecmp($value, "true") == 0 || strcasecmp($value, "false") == 0) { $value = filter_var($value, FILTER_VALIDATE_BOOLEAN); } else { if (preg_match('/^\\d+$/', $value)) { $value = intval($value); } } } $codegenSettings[$key] = $value; } /* if ($codegenSettings['validateColumn']) { $codegenSettings['handleValidationError'] = true; } */ if (!empty($codegenSettings)) { $reflectionModel = new ReflectionClass('LazyRecord\\BaseModel'); $createMethod = $reflectionModel->getMethod('create'); $methodFile = $createMethod->getFilename(); $startLine = $createMethod->getStartLine(); $endLine = $createMethod->getEndLine(); $lines = file($methodFile); $methodLines = array_slice($lines, $startLine + 1, $endLine - $startLine - 2); // exclude '{', '}' $blockRanges = array(); $blockLines = array(); // parse code blocks for ($i = 0; $i < count($methodLines); $i++) { $line = rtrim($methodLines[$i]); if (preg_match('/@codegenBlock (\\w+)/', $line, $matches)) { $blockId = $matches[1]; for ($j = $i; $j < count($methodLines); $j++) { $line = rtrim($methodLines[$j]); $blockLines[$blockId][] = $line; if (preg_match('/@codegenBlockEnd/', $line)) { $blockRanges[$blockId] = [$i, $j]; $i = $j; break; } } } } $overrideCreateMethod = $cTemplate->addMethod('public', 'create', ['array $args', 'array $options = array()']); $overrideBlock = $overrideCreateMethod->getBlock(); for ($i = 0; $i < count($methodLines); $i++) { $line = rtrim($methodLines[$i]); if (preg_match('/@codegenBlock (\\w+)/', $line, $matches)) { $blockId = $matches[1]; if (isset($codegenSettings[$matches[1]]) && isset($blockLines[$blockId])) { if ($codegenSettings[$matches[1]]) { $overrideBlock[] = $blockLines[$blockId]; list($startLine, $endLine) = $blockRanges[$blockId]; $i = $endLine; continue; } else { list($startLine, $endLine) = $blockRanges[$blockId]; $i = $endLine; continue; } } } $overrideBlock[] = $line; } } // TODO: refacory this into factory method // Generate findByPrimaryKey SQL query $arguments = new ArgumentArray(); $findByPrimaryKeyQuery = new SelectQuery(); $findByPrimaryKeyQuery->from($schema->getTable()); $primaryKey = $schema->primaryKey; $readFrom = $schema->getReadSourceId(); $readConnection = ConnectionManager::getInstance()->getConnection($readFrom); $readQueryDriver = $readConnection->createQueryDriver(); $primaryKeyColumn = $schema->getColumn($primaryKey); $findByPrimaryKeyQuery->select('*')->where()->equal($primaryKey, new Bind($primaryKey)); $findByPrimaryKeyQuery->limit(1); $findByPrimaryKeySql = $findByPrimaryKeyQuery->toSql($readQueryDriver, $arguments); $cTemplate->addConst('FIND_BY_PRIMARY_KEY_SQL', $findByPrimaryKeySql); foreach ($schema->getColumns() as $column) { if (!$column->findable) { continue; } $columnName = $column->name; $findMethodName = 'findBy' . ucfirst(Inflector::camelize($columnName)); $findMethod = $cTemplate->addMethod('public', $findMethodName, ['$value']); $block = $findMethod->block; $arguments = new ArgumentArray(); $findByColumnQuery = new SelectQuery(); $findByColumnQuery->from($schema->getTable()); $columnName = $column->name; $readFrom = $schema->getReadSourceId(); $findByColumnQuery->select('*')->where()->equal($columnName, new Bind($columnName)); $findByColumnQuery->limit(1); $findByColumnSql = $findByColumnQuery->toSql($readQueryDriver, $arguments); $block[] = '$conn = $this->getReadConnection();'; $block[] = 'if (!isset($this->_preparedFindStms[' . var_export($columnName, true) . '])) {'; $block[] = ' $this->_preparedFindStms[' . var_export($columnName, true) . '] = $conn->prepare(' . var_export($findByColumnSql, true) . ');'; $block[] = '}'; $block[] = '$this->_preparedFindStms[' . var_export($columnName, true) . ']->execute([' . var_export(":{$columnName}", true) . ' => $value ]);'; $block[] = 'if (false === ($this->_data = $this->_preparedFindStms[' . var_export($columnName, true) . ']->fetch(PDO::FETCH_ASSOC)) ) {'; $block[] = ' return $this->reportError("Record not found", ['; $block[] = ' "sql" => ' . var_export($findByColumnSql, true) . ','; $block[] = ' ]);'; $block[] = '}'; $block[] = '$this->_preparedFindStms[' . var_export($columnName, true) . ']->closeCursor();'; $block[] = 'return $this->reportSuccess( "Data loaded", array( '; $block[] = ' "sql" => ' . var_export($findByColumnSql, true) . ','; $block[] = ' "type" => Result::TYPE_LOAD,'; $block[] = '));'; } $cTemplate->extendClass('\\' . $baseClass); // interfaces if ($ifs = $schema->getModelInterfaces()) { foreach ($ifs as $iface) { $cTemplate->implementClass($iface); } } // Create column accessor if ($schema->enableColumnAccessors) { foreach ($schema->getColumnNames() as $columnName) { $accessorMethodName = 'get' . ucfirst(Inflector::camelize($columnName)); $cTemplate->addMethod('public', $accessorMethodName, [], [' return $this->get(' . var_export($columnName, true) . ');']); } } return $cTemplate; }