Skip to content

Commit

Permalink
Added support for primary key lengths and "IF NOT EXISTS" clause in t…
Browse files Browse the repository at this point in the history
…able definition.
  • Loading branch information
Carlos Cima committed May 1, 2016
1 parent 98aa4ed commit f6078e8
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 5 deletions.
21 changes: 21 additions & 0 deletions src/Model/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ class Column
*/
private $primaryKey;

/**
* @var int
*/
private $primaryKeyLength;

/**
* @var string
*/
Expand Down Expand Up @@ -286,6 +291,22 @@ public function setPrimaryKey($primaryKey)
$this->primaryKey = $primaryKey;
}

/**
* @return int
*/
public function getPrimaryKeyLength()
{
return $this->primaryKeyLength;
}

/**
* @param int $primaryKeyLength
*/
public function setPrimaryKeyLength($primaryKeyLength)
{
$this->primaryKeyLength = $primaryKeyLength;
}

/**
* @return string
*/
Expand Down
37 changes: 35 additions & 2 deletions src/Model/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ class Table
*/
private $name;

/**
* @var bool
*/
private $ifNotExists;

/**
* @var string
*/
Expand Down Expand Up @@ -70,6 +75,22 @@ public function getName()
return $this->name;
}

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

/**
* @param bool $ifNotExists
*/
public function setIfNotExists($ifNotExists)
{
$this->ifNotExists = $ifNotExists;
}

/**
* @return string
*/
Expand Down Expand Up @@ -324,7 +345,13 @@ public function generatePrimaryKeyCreationScript()

$primaryKeys = [];
foreach ($this->primaryKeys as $primaryKeyColumn) {
$primaryKeys[] = sprintf('`%s`', $primaryKeyColumn->getName());
if ($primaryKeyColumn->getPrimaryKeyLength()) {
$primaryKey = sprintf('`%s`(%s)', $primaryKeyColumn->getName(), $primaryKeyColumn->getPrimaryKeyLength());
} else {
$primaryKey = sprintf('`%s`', $primaryKeyColumn->getName());
}

$primaryKeys[] = $primaryKey;
}

return sprintf('PRIMARY KEY (%s)', implode(',', $primaryKeys));
Expand Down Expand Up @@ -369,6 +396,12 @@ public function generateCreationScript($ignoreAutoIncrement = false, $sortKeys =

$tableOptions = [];

if ($this->ifNotExists) {
$ifNotExists = ' IF NOT EXISTS';
} else {
$ifNotExists = '';
}

if ($this->engine) {
$tableOptions[] = sprintf('ENGINE=%s', $this->engine);
}
Expand All @@ -387,6 +420,6 @@ public function generateCreationScript($ignoreAutoIncrement = false, $sortKeys =
$implodedTableOptions = ' ' . $implodedTableOptions;
}

return trim(sprintf('CREATE TABLE `%s` (%s %s%s)%s;', $this->name, PHP_EOL, implode(',' . PHP_EOL . ' ', $tableDefinitions), PHP_EOL, $implodedTableOptions));
return trim(sprintf('CREATE TABLE%s `%s` (%s %s%s)%s;', $ifNotExists, $this->name, PHP_EOL, implode(',' . PHP_EOL . ' ', $tableDefinitions), PHP_EOL, $implodedTableOptions));
}
}
19 changes: 18 additions & 1 deletion src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public function parseTables($sqlScript)
$tables = [];
for ($i = 0; $i < count($matches[0]); $i++) {
$name = $matches['tableName'][$i];
$ifNotExists = $matches['ifNotExists'][$i];
$definition = $matches['tableDefinition'][$i];
$creationScript = $matches['creationScript'][$i];
$engine = $matches['engine'][$i];
Expand All @@ -53,6 +54,10 @@ public function parseTables($sqlScript)
$table->setDefinition(trim($definition));
$table->setCreationScript(trim($creationScript) . ';');

if ($ifNotExists) {
$table->setIfNotExists(true);
}

if ($engine) {
$table->setEngine($engine);
}
Expand Down Expand Up @@ -171,8 +176,20 @@ public function parsePrimaryKey(Table $table)
$primaryKeyNames = explode(',', str_replace('`', '', $matches['primaryKey']));

foreach ($primaryKeyNames as $primaryKeyName) {
$primaryKeyColumn = $table->getColumnByName(trim($primaryKeyName));
if (preg_match('/^(?<columnName>[^\(]+)\((?<keyLength>\d+)\)/', $primaryKeyName, $keyMatches)) {
$columnName = $keyMatches['columnName'];
$keyLength = $keyMatches['keyLength'];
} else {
$columnName = $primaryKeyName;
$keyLength = null;
}
$primaryKeyColumn = $table->getColumnByName(trim($columnName));
$primaryKeyColumn->setPrimaryKey(true);

if ($keyLength) {
$primaryKeyColumn->setPrimaryKeyLength($keyLength);
}

$table->addPrimaryKey($primaryKeyColumn);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/RegExpPattern.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class RegExpPattern
*/
public static function tables()
{
$pattern = '/(?<creationScript>CREATE\s+TABLE\s+`(?<tableName>\S+)`\s+';
$pattern = '/(?<creationScript>CREATE\s+TABLE\s+(?<ifNotExists>IF NOT EXISTS)?\s*`(?<tableName>\S+)`\s+';
$pattern .= '\((?<tableDefinition>[^;\/]+)\)';
$pattern .= '(?:\s+ENGINE=(?<engine>[^;\s]+))?\s*';
$pattern .= '(?:AUTO_INCREMENT=(?<autoIncrement>\d+))?\s*';
Expand Down Expand Up @@ -77,7 +77,7 @@ public static function dataType()
*/
public static function primaryKey()
{
return '/PRIMARY KEY \((?<primaryKey>.+?)\)/';
return '/PRIMARY KEY \((?<primaryKey>(?:`[^`]+`\s*(?:\(\d+\))?,?)+)\)/';
}

/**
Expand Down
16 changes: 16 additions & 0 deletions tests/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -286,4 +286,20 @@ public function testIsParsingDoubleUnsignedType()
$this->assertEquals('double unsigned', $database->getTableByName('jos_finder_links')->getColumnByName('list_price')->getColumnType());
$this->assertEquals('double', $database->getTableByName('jos_finder_links')->getColumnByName('list_price')->getDataType());
}

public function testIsParsingPrimaryKeyLength()
{
$creationScript = $this->getDatabaseFixture('jos_extwebdav_properties.sql');

$parser = new Parser();

$database = $parser->parseDatabase($creationScript);

$this->assertInstanceOf(Database::class, $database);
$this->assertCount(1, $database->getTables());
$this->assertCount(4, $database->getTableByName('jos_extwebdav_properties')->getColumns());
$this->assertCount(3, $database->getTableByName('jos_extwebdav_properties')->getPrimaryKeys());

$this->assertEquals($creationScript, $database->getTableByName('jos_extwebdav_properties')->generateCreationScript());
}
}
8 changes: 8 additions & 0 deletions tests/fixtures/jos_extwebdav_properties.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS `jos_extwebdav_properties` (
`path` varchar(255) NOT NULL DEFAULT '',
`name` varchar(120) NOT NULL DEFAULT '',
`ns` varchar(120) NOT NULL DEFAULT 'DAV:',
`value` text,
PRIMARY KEY (`ns`(100),`path`(100),`name`(50)),
KEY `path` (`path`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

0 comments on commit f6078e8

Please sign in to comment.