Skip to content

Commit

Permalink
Preserve not null and default values.
Browse files Browse the repository at this point in the history
  • Loading branch information
prwater committed Oct 9, 2024
1 parent 1163796 commit 160956e
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 14 deletions.
31 changes: 17 additions & 14 deletions src/Loader/Helper/TypeHintHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class TypeHintHelper
private array $typeHints = [];

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

/**
* Adds a type hint with its actual data type.
*
Expand Down Expand Up @@ -167,29 +168,31 @@ public function updateTypes(array $codeLines, CommonDataTypeHelper $dataTypeHelp
throw new RoutineLoaderException("Unknown type hint '%s' found at line %d.", $hint, $index + 1);
}

if (preg_match('/(?<nullable>not\s+null)?\s*(?<punctuation>\s*[;,]\s*)?$/',
if (preg_match('/(?<extra1> not\s+null)?\s*(?<extra2> default.+)?\s*(?<extra3>[;,]\s*)?$/i',
$matches['extra'],
$other,
PREG_UNMATCHED_AS_NULL))
{
$punctuation = $other['punctuation'] ?? '';
$nullable = $other['nullable'] ?? '';
$extra1 = $other['extra1'] ?? '';
$extra2 = $other['extra2'] ?? '';
$extra3 = $other['extra3'] ?? '';
}
else
{
$punctuation = '';
$nullable = '';
$extra1 = '';
$extra2 = '';
$extra3 = '';
}

$actualType = $this->typeHints[$hint];
$newLine = sprintf('%s%s%s%s%s%s',
mb_substr($line, 0, -mb_strlen($matches[0])),
$matches['whitespace'],
$actualType, // <== the real replacement
$nullable,
$punctuation,
$matches['hint']);
$this->typeHints[$hint] = $actualType;
$actualType = $this->typeHints[$hint];
$newLine = sprintf('%s%s%s%s%s%s%s',
mb_substr($line, 0, -mb_strlen($matches[0])),
$matches['whitespace'],
$actualType, // <== the real replacement
$extra1,
$extra2,
$extra3,
$matches['hint']);

if (str_replace(' ', '', $line)!==str_replace(' ', '', $newLine))
{
Expand Down
46 changes: 46 additions & 0 deletions test/Loader/Helper/TestDataTypeHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);

namespace SetBased\Stratum\Common\Test\Loader\Helper;

use SetBased\Exception\LogicException;
use SetBased\Stratum\Common\Helper\CommonDataTypeHelper;

/**
* Implementation of CommonDataTypeHelper for testing purposes.
*/
class TestDataTypeHelper implements CommonDataTypeHelper
{
//--------------------------------------------------------------------------------------------------------------------
/**
* @inheritDoc
*/
public function allColumnTypes(): array
{
return ['enum',
'int',
'varchar'];
}

//--------------------------------------------------------------------------------------------------------------------
/**
* @inheritDoc
*/
public function columnTypeToPhpType(array $dataTypeInfo): string
{
throw new LogicException('Not implemented');
}

//--------------------------------------------------------------------------------------------------------------------
/**
* @inheritDoc
*/
public function escapePhpExpression(array $dataTypeInfo, string $expression): string
{
throw new LogicException('Not implemented');
}

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

//----------------------------------------------------------------------------------------------------------------------
219 changes: 219 additions & 0 deletions test/Loader/Helper/TypeHintHelperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
<?php
declare(strict_types=1);

namespace SetBased\Stratum\Common\Test\Loader\Helper;

use PHPUnit\Framework\TestCase;
use SetBased\Stratum\Common\Loader\Helper\TypeHintHelper;

/**
* Test cases for class TypeHintHelper.
*/
class TypeHintHelperTest extends TestCase
{
//--------------------------------------------------------------------------------------------------------------------
/**
* Test for a type hint with not null;
*/
public function testTypeHintDefault(): void
{
$code = <<<CODE
declare l_var1 int default 1; -- type: TABLE1.col11
declare l_var2 int default 2 -- type: TABLE2.col21
;
create temporary table TMP_TABLE1
(
col11 int not null, -- type: TABLE1.col11
primary key(col11)
);
create temporary table TMP_TABLE2
(
col21 int not null -- type: TABLE2.col21
, primary key(col21)
);
CODE;

$expected = <<<CODE
declare l_var1 int unsigned default 1; -- type: TABLE1.col11
declare l_var2 enum('A', 'B') default 2 -- type: TABLE2.col21
;
create temporary table TMP_TABLE1
(
col11 int unsigned not null, -- type: TABLE1.col11
primary key(col11)
);
create temporary table TMP_TABLE2
(
col21 enum('A', 'B') not null -- type: TABLE2.col21
, primary key(col21)
);
CODE;

$code2 = $this->updateTypeHints($code);
self::assertSame($expected, $code2);

$code3 = $this->updateTypeHints($code2);
self::assertSame($expected, $code3);
}

//--------------------------------------------------------------------------------------------------------------------
/**
* Test for a type hint with not null;
*/
public function testTypeHintNotAndDefaultDefault(): void
{
$code = <<<CODE
--
create temporary table TMP_TABLE1
(
col11 int not null default 1, -- type: TABLE1.col11
primary key(col11)
);
create temporary table TMP_TABLE2
(
col21 int not null default 2 -- type: TABLE2.col21
, primary key(col21)
);
CODE;

$expected = <<<CODE
--
create temporary table TMP_TABLE1
(
col11 int unsigned not null default 1, -- type: TABLE1.col11
primary key(col11)
);
create temporary table TMP_TABLE2
(
col21 enum('A', 'B') not null default 2 -- type: TABLE2.col21
, primary key(col21)
);
CODE;

$code2 = $this->updateTypeHints($code);
self::assertSame($expected, $code2);

$code3 = $this->updateTypeHints($code2);
self::assertSame($expected, $code3);
}

//--------------------------------------------------------------------------------------------------------------------
/**
* Test for a type hint with not null;
*/
public function testTypeHintNotNull(): void
{
$code = <<<CODE
--
create temporary table TMP_TABLE1
(
col11 int not null, -- type: TABLE1.col11
primary key(col11)
);
create temporary table TMP_TABLE2
(
col21 int not null -- type: TABLE2.col21
, primary key(col21)
);
CODE;

$expected = <<<CODE
--
create temporary table TMP_TABLE1
(
col11 int unsigned not null, -- type: TABLE1.col11
primary key(col11)
);
create temporary table TMP_TABLE2
(
col21 enum('A', 'B') not null -- type: TABLE2.col21
, primary key(col21)
);
CODE;

$code2 = $this->updateTypeHints($code);
self::assertSame($expected, $code2);

$code3 = $this->updateTypeHints($code2);
self::assertSame($expected, $code3);
}

//--------------------------------------------------------------------------------------------------------------------
/**
* Test for a type hint without extra code.
*/
public function testTypeHintPlain(): void
{
$code = <<<CODE
declare l_var1 int; -- type: TABLE1.col11
declare l_var2 int -- type: TABLE2.col21
;
create temporary table TMP_TABLE1
(
col11 int, -- type: TABLE1.col11
primary key(col11)
);
create temporary table TMP_TABLE2
(
col21 int -- type: TABLE2.col21
, primary key(col21)
);
CODE;

$expected = <<<CODE
declare l_var1 int unsigned; -- type: TABLE1.col11
declare l_var2 enum('A', 'B') -- type: TABLE2.col21
;
create temporary table TMP_TABLE1
(
col11 int unsigned, -- type: TABLE1.col11
primary key(col11)
);
create temporary table TMP_TABLE2
(
col21 enum('A', 'B') -- type: TABLE2.col21
, primary key(col21)
);
CODE;

$code2 = $this->updateTypeHints($code);
self::assertSame($expected, $code2);

$code3 = $this->updateTypeHints($code2);
self::assertSame($expected, $code3);
}

//--------------------------------------------------------------------------------------------------------------------
/**
* Runs the TypeHintHelper on a piece of code and returns the modified code.
*
* @param string $code The piece of code.
*/
private function updateTypeHints(string $code): string
{
$typeHintHelper = new TypeHintHelper();
$typeHintHelper->addTypeHint('TABLE1.col11', 'int unsigned');
$typeHintHelper->addTypeHint('TABLE2.col21', "enum('A', 'B')");
$dataTypeHelper = new TestDataTypeHelper();
$lines = $typeHintHelper->updateTypes(explode(PHP_EOL, $code), $dataTypeHelper);
$lines = $typeHintHelper->alignTypeHints($lines);

return implode(PHP_EOL, $lines);
}

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

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

0 comments on commit 160956e

Please sign in to comment.