-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Schema::match() with strict/evolving matchers (#1027)
- Loading branch information
1 parent
fd4671d
commit 8d16fcd
Showing
9 changed files
with
368 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
src/core/etl/src/Flow/ETL/Row/Schema/Matcher/EvolvingSchemaMatcher.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Flow\ETL\Row\Schema\Matcher; | ||
|
||
use Flow\ETL\Row\Schema; | ||
use Flow\ETL\Row\Schema\SchemaMatcher; | ||
|
||
final class EvolvingSchemaMatcher implements SchemaMatcher | ||
{ | ||
/** | ||
* Rules of evolving schema matching: | ||
* - if schemas are the same, return true | ||
* - if right schema has less fields than left schema, return false | ||
* - if right schema is making a nullable field non-nullable, return false | ||
* - if right schema is making a non-nullable field nullable, return true | ||
* - if right schema is changing the type of a field, return false | ||
* - if right schema is adding a field, return true | ||
*/ | ||
public function match(Schema $left, Schema $right) : bool | ||
{ | ||
if ($right->count() < $left->count()) { | ||
return false; | ||
} | ||
|
||
foreach ($right->definitions() as $rightDefinition) { | ||
$leftDefinition = $left->findDefinition($rightDefinition->entry()); | ||
|
||
if ($leftDefinition === null) { | ||
if ($right->count() === $left->count()) { | ||
return false; | ||
} | ||
|
||
continue; | ||
} | ||
|
||
if (!$rightDefinition->isNullable() && $leftDefinition->isNullable()) { | ||
return false; | ||
} | ||
|
||
// making both sides nullable to compare just types of the fields | ||
if (!$rightDefinition->type()->makeNullable(true)->isEqual($leftDefinition->type()->makeNullable(true))) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
src/core/etl/src/Flow/ETL/Row/Schema/Matcher/StrictSchemaMatcher.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Flow\ETL\Row\Schema\Matcher; | ||
|
||
use Flow\ETL\Row\Schema; | ||
use Flow\ETL\Row\Schema\SchemaMatcher; | ||
|
||
final class StrictSchemaMatcher implements SchemaMatcher | ||
{ | ||
public function match(Schema $left, Schema $right) : bool | ||
{ | ||
if (\count($left->definitions()) !== \count($right->definitions())) { | ||
return false; | ||
} | ||
|
||
foreach ($left->definitions() as $leftDefinition) { | ||
$rightDefinition = $right->findDefinition($leftDefinition->entry()); | ||
|
||
if ($rightDefinition === null) { | ||
return false; | ||
} | ||
|
||
if (!$leftDefinition->isEqual($rightDefinition)) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Flow\ETL\Row\Schema; | ||
|
||
use Flow\ETL\Row\Schema; | ||
|
||
interface SchemaMatcher | ||
{ | ||
public function match(Schema $left, Schema $right) : bool; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Schema/Matcher/EvolvingSchemaMatcherTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Flow\ETL\Tests\Unit\Row\Schema\Matcher; | ||
|
||
use function Flow\ETL\DSL\{bool_schema, int_schema, schema, str_schema}; | ||
use Flow\ETL\Row\Schema\Matcher\EvolvingSchemaMatcher; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
final class EvolvingSchemaMatcherTest extends TestCase | ||
{ | ||
public function test_right_having_less_definitions_than_left() : void | ||
{ | ||
$left = schema( | ||
int_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
$right = schema( | ||
int_schema('id'), | ||
); | ||
|
||
self::assertFalse((new EvolvingSchemaMatcher())->match($left, $right)); | ||
} | ||
|
||
public function test_right_having_same_number_of_definitions_but_different_names() : void | ||
{ | ||
$left = schema( | ||
int_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
$right = schema( | ||
int_schema('id'), | ||
str_schema('surname'), | ||
); | ||
|
||
self::assertFalse((new EvolvingSchemaMatcher())->match($left, $right)); | ||
} | ||
|
||
public function test_right_schema_adding_new_field() : void | ||
{ | ||
$left = schema( | ||
int_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
$right = schema( | ||
int_schema('id'), | ||
str_schema('name'), | ||
bool_schema('active'), | ||
); | ||
|
||
self::assertTrue((new EvolvingSchemaMatcher())->match($left, $right)); | ||
} | ||
|
||
public function test_right_schema_changing_nullable_field_to_non_nullable() : void | ||
{ | ||
$left = schema( | ||
int_schema('id'), | ||
str_schema('name', nullable: true), | ||
); | ||
|
||
$right = schema( | ||
int_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
self::assertFalse((new EvolvingSchemaMatcher())->match($left, $right)); | ||
} | ||
|
||
public function test_right_schema_changing_type_of_field() : void | ||
{ | ||
$left = schema( | ||
int_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
$right = schema( | ||
int_schema('id'), | ||
bool_schema('name'), | ||
); | ||
|
||
self::assertFalse((new EvolvingSchemaMatcher())->match($left, $right)); | ||
} | ||
|
||
public function test_right_schema_is_the_same_as_left_schema() : void | ||
{ | ||
$left = schema( | ||
int_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
$right = schema( | ||
int_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
self::assertTrue((new EvolvingSchemaMatcher())->match($left, $right)); | ||
} | ||
|
||
public function test_right_schema_making_non_nullable_field_into_nullable() : void | ||
{ | ||
$left = schema( | ||
int_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
$right = schema( | ||
int_schema('id'), | ||
str_schema('name', nullable: true), | ||
); | ||
|
||
self::assertTrue((new EvolvingSchemaMatcher())->match($left, $right)); | ||
} | ||
} |
73 changes: 73 additions & 0 deletions
73
src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Schema/Matcher/StrictSchemaMatcherTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Flow\ETL\Tests\Unit\Row\Schema\Matcher; | ||
|
||
use function Flow\ETL\DSL\{int_schema, schema, str_schema}; | ||
use Flow\ETL\Row\Schema\Matcher\StrictSchemaMatcher; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
final class StrictSchemaMatcherTest extends TestCase | ||
{ | ||
public function test_matching_different_schemas() : void | ||
{ | ||
$left = schema( | ||
str_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
$right = schema( | ||
str_schema('id'), | ||
str_schema('name'), | ||
int_schema('age'), | ||
); | ||
|
||
self::assertFalse((new StrictSchemaMatcher())->match($left, $right)); | ||
} | ||
|
||
public function test_matching_same_number_of_definitions_but_different_names() : void | ||
{ | ||
$left = schema( | ||
str_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
$right = schema( | ||
str_schema('id'), | ||
str_schema('surname'), | ||
); | ||
|
||
self::assertFalse((new StrictSchemaMatcher())->match($left, $right)); | ||
} | ||
|
||
public function test_matching_schemas_with_different_nullable_fields() : void | ||
{ | ||
$left = schema( | ||
str_schema('id'), | ||
str_schema('name', nullable: true), | ||
); | ||
|
||
$right = schema( | ||
str_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
self::assertFalse((new StrictSchemaMatcher())->match($left, $right)); | ||
} | ||
|
||
public function test_matching_the_same_schema() : void | ||
{ | ||
$left = schema( | ||
str_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
$right = schema( | ||
str_schema('id'), | ||
str_schema('name'), | ||
); | ||
|
||
self::assertTrue((new StrictSchemaMatcher())->match($left, $right)); | ||
} | ||
} |
Oops, something went wrong.