From b3c30549359f19cd398a29dc3a20654b1a623603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Tue, 6 Feb 2024 13:00:32 +0000 Subject: [PATCH 01/10] CT-1169 add parsing of precision&scale to SNFLK --- .../src/Definition/Snowflake.php | 25 +++++++++++++ .../tests/SnowflakeDatatypeTest.php | 35 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/packages/php-datatypes/src/Definition/Snowflake.php b/packages/php-datatypes/src/Definition/Snowflake.php index 934ff4456..1a62610e8 100644 --- a/packages/php-datatypes/src/Definition/Snowflake.php +++ b/packages/php-datatypes/src/Definition/Snowflake.php @@ -11,6 +11,7 @@ class Snowflake extends Common { + public const TYPES_WITH_COMPLEX_LENGTH = [self::TYPE_NUMBER, self::TYPE_DECIMAL, self::TYPE_NUMERIC]; public const METADATA_BACKEND = 'snowflake'; public const TYPE_NUMBER = 'NUMBER'; public const TYPE_DECIMAL = 'DECIMAL'; @@ -195,6 +196,30 @@ private function getLengthFromArray(array $lengthOptions): ?string return $numericPrecision === null ? null : (string) $numericPrecision; } + /** + * @return array{ + * character_maximum?:string|int|null, + * numeric_precision?:string|int|null, + * numeric_scale?:string|int|null + * } + */ + public function getArrayFromLength(): array + { + if ($this->getLength() === null || $this->getLength() === '') { + return []; + } + if ($this->isTypeWithComplexLength()) { + $parsed = array_map(intval(...), explode(',', $this->getLength())); + return ['numeric_precision' => $parsed[0], 'numeric_scale' => $parsed[1]]; + } + return ['character_maximum' => $this->getLength()]; + } + + public function isTypeWithComplexLength(): bool + { + return in_array($this->getType(), self::TYPES_WITH_COMPLEX_LENGTH, true); + } + /** * @throws InvalidTypeException */ diff --git a/packages/php-datatypes/tests/SnowflakeDatatypeTest.php b/packages/php-datatypes/tests/SnowflakeDatatypeTest.php index 427c45781..4ec87548d 100644 --- a/packages/php-datatypes/tests/SnowflakeDatatypeTest.php +++ b/packages/php-datatypes/tests/SnowflakeDatatypeTest.php @@ -4,6 +4,7 @@ namespace Keboola\DatatypeTest; +use Generator; use Keboola\Datatype\Definition\Exception\InvalidLengthException; use Keboola\Datatype\Definition\Exception\InvalidOptionException; use Keboola\Datatype\Definition\Exception\InvalidTypeException; @@ -381,4 +382,38 @@ public function testGetTypeByBasetype(): void $this->expectExceptionMessage('Base type "FOO" is not valid.'); Snowflake::getTypeByBasetype('foo'); } + + /** + * @param array $expectedArray + * @dataProvider arrayFromLengthProvider + */ + public function testArrayFromLength(string $type, ?string $length, array $expectedArray): void + { + $definition = new Snowflake($type, ['length' => $length]); + $this->assertSame($expectedArray, $definition->getArrayFromLength()); + } + + public function arrayFromLengthProvider(): Generator + { + yield 'simple' => [ + 'VARCHAR', + '10', + ['character_maximum' => '10'] + ]; + yield 'decimal' => [ + 'NUMERIC', + '38,2', + ['numeric_precision' => 38, 'numeric_scale' => 2] + ]; + yield 'with zero scale' => [ + 'NUMERIC', + '38,0', + ['numeric_precision' => 38, 'numeric_scale' => 0] + ]; + yield 'with null length' => [ + 'NUMERIC', + null, + [] + ]; + } } From 422bcb85849f3945d31d1e90777f74f39dd8f1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Wed, 7 Feb 2024 15:27:31 +0000 Subject: [PATCH 02/10] CT-1169 Update Table query builder --- .../Snowflake/SnowflakeTableQueryBuilder.php | 128 ++++++++++++++++++ .../SnowflakeTableQueryBuilderTest.php | 32 +++++ 2 files changed, 160 insertions(+) diff --git a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php index 81ab42cbf..5b38a7bb1 100644 --- a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php +++ b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php @@ -14,6 +14,12 @@ class SnowflakeTableQueryBuilder implements TableQueryBuilderInterface { + private const CANNOT_CHANGE_DEFAULT_VALUE = 'cannotChangeDefaultValue'; + private const CANNOT_CHANGE_SCALE = 'cannotChangeScale'; + private const CANNOT_DECREASE_LENGTH = 'cannotDecreaseLength'; + private const CANNOT_DECREASE_PRECISION = 'cannotDecreasePrecision'; + private const CANNOT_INTRODUCE_COMPLEX_LENGTH = 'cannotIntroduceComplexLength'; + private const CANNOT_REDUCE_COMPLEX_LENGTH = 'cannotReduceComplexLength'; private const INVALID_PKS_FOR_TABLE = 'invalidPKs'; private const INVALID_TABLE_NAME = 'invalidTableName'; public const TEMP_TABLE_PREFIX = '__temp_'; @@ -214,4 +220,126 @@ public static function buildTempTableName(string $realTableName): string { return self::TEMP_TABLE_PREFIX . $realTableName; } + + public function getUpdateColumnFromDefinitionQuery( + Snowflake $existingColumnDefinition, + Snowflake $desiredColumnDefinition, + string $schemaName, + string $tableName, + string $columnName + ): string { + $sql = sprintf( + 'ALTER TABLE %s.%s MODIFY ', + SnowflakeQuote::quoteSingleIdentifier($schemaName), + SnowflakeQuote::quoteSingleIdentifier($tableName), + ); + $sqlParts = []; + // allowed from https://docs.snowflake.com/en/sql-reference/sql/alter-table-column + + // drop default + if ($existingColumnDefinition->getDefault() !== null + && $desiredColumnDefinition->getDefault() === null) { + $sqlParts[] = ' DROP DEFAULT'; + } elseif ($existingColumnDefinition->getDefault() !== $desiredColumnDefinition->getDefault()) { + throw new QueryBuilderException( + sprintf( + 'Cannot change default value of column "%s"', + $columnName, + ), + self::CANNOT_CHANGE_DEFAULT_VALUE, + ); + } + + if ($existingColumnDefinition->isNullable() !== $desiredColumnDefinition->isNullable()) { + $sqlParts[] = $desiredColumnDefinition->isNullable() ? ' DROP NOT NULL' : ' SET NOT NULL'; + } + + $notSameLength = $existingColumnDefinition->getLength() !== $desiredColumnDefinition->getLength(); + $isNewLengthBigger = $existingColumnDefinition->getLength() < $desiredColumnDefinition->getLength(); + + // increase precision + if ($existingColumnDefinition->isTypeWithComplexLength() && $notSameLength) { + if (!$desiredColumnDefinition->isTypeWithComplexLength()) { + throw new QueryBuilderException( + sprintf( + 'Cannot reduce column "%s" with complex length "%s" to simple length "%s"', + $columnName, + $existingColumnDefinition->getLength(), + $desiredColumnDefinition->getLength(), + ), + self::CANNOT_REDUCE_COMPLEX_LENGTH, + ); + } + [ + 'numeric_precision' => $existingPrecision, + 'numeric_scale' => $existingScale, + ] = $existingColumnDefinition->getArrayFromLength(); + [ + 'numeric_precision' => $desiredPrecision, + 'numeric_scale' => $desiredScale, + ] = $desiredColumnDefinition->getArrayFromLength(); + + if ($existingScale !== $desiredScale) { + throw new QueryBuilderException( + sprintf( + 'Cannot change scale of a column "%s" from "%s" to "%s"', + $columnName, + $existingScale, + $desiredScale, + ), + self::CANNOT_CHANGE_SCALE,); + } + + if ($existingPrecision < $desiredPrecision) { + $sqlParts[] = sprintf( + 'SET DATA TYPE %s(%s, %s)', + $desiredColumnDefinition->getType(), + $desiredPrecision, + $desiredScale, + ); + } else { + throw new QueryBuilderException( + sprintf( + 'Cannot decrease precision of column "%s"', + $columnName, + ) + , self::CANNOT_DECREASE_PRECISION); + } + } elseif ($notSameLength && $isNewLengthBigger) { + if ($desiredColumnDefinition->isTypeWithComplexLength()) { + throw new QueryBuilderException( + sprintf( + 'Cannot convert column "%s" from simple length "%s" to complex length "%s"', + $columnName, + $existingColumnDefinition->getLength(), + $desiredColumnDefinition->getLength(), + ) + , + self::CANNOT_INTRODUCE_COMPLEX_LENGTH, + ); + } + // increase length + $sqlParts[] = sprintf( + 'SET DATA TYPE %s(%s)', + $desiredColumnDefinition->getType(), + $desiredColumnDefinition->getLength(), + ); + } else { + throw new QueryBuilderException( + sprintf( + 'Cannot decrease length of column "%s"', + $columnName, + ), + self::CANNOT_DECREASE_LENGTH); + } + + $partsWithColumnPrefix = array_map(function (string $part) use ($columnName) { + return sprintf( + 'COLUMN %s %s', + SnowflakeQuote::quoteSingleIdentifier($columnName), + $part + ); + }, $sqlParts); + return $sql . implode(', ', $partsWithColumnPrefix); + } } diff --git a/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php b/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php index 8f3e6c41e..c9353fe43 100644 --- a/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php +++ b/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php @@ -93,4 +93,36 @@ public function testGetTruncateTable(): void $dropTableCommand = $this->qb->getTruncateTableCommand('testDb', 'testTable'); self::assertEquals('TRUNCATE TABLE "testDb"."testTable"', $dropTableCommand); } + + /** + * @dataProvider provideGetColumnDefinitionUpdate + */ + public function testGetColumnDefinitionUpdate( + Snowflake $existingColumn, + Snowflake $desiredColumn, + string $expectedQuery, + ): void { + $existingColumnDefinition = $existingColumn; + $desiredColumnDefinition = $desiredColumn; + $sql = $this->qb->getUpdateColumnFromDefinitionQuery( + $existingColumnDefinition, + $desiredColumnDefinition, + 'testDb', + 'testTable', + 'testColumn', + ); + self::assertEquals( + $expectedQuery, + $sql, + ); + } + + public function provideGetColumnDefinitionUpdate() + { + yield 'change length' => [ + new Snowflake('VARCHAR', ['length' =>12, 'nullable' => true, 'default' => '']), + new Snowflake('VARCHAR', ['length' =>38, 'nullable' => true, 'default' => '']), + 'ALTER TABLE "testDb"."testTable" MODIFY COLUMN "testColumn" SET DATA TYPE VARCHAR(38)', + ]; + } } From d1141962b26ca4d88e0293b4b2f00ce7a01d8e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Thu, 8 Feb 2024 13:39:19 +0000 Subject: [PATCH 03/10] CT-1169 Update Table query builder --- .../Snowflake/SnowflakeTableQueryBuilder.php | 18 ++-- .../SnowflakeTableQueryBuilderTest.php | 85 ++++++++++++++++++- 2 files changed, 93 insertions(+), 10 deletions(-) diff --git a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php index 5b38a7bb1..74b632e90 100644 --- a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php +++ b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php @@ -239,19 +239,21 @@ public function getUpdateColumnFromDefinitionQuery( // drop default if ($existingColumnDefinition->getDefault() !== null && $desiredColumnDefinition->getDefault() === null) { - $sqlParts[] = ' DROP DEFAULT'; + $sqlParts[] = 'DROP DEFAULT'; } elseif ($existingColumnDefinition->getDefault() !== $desiredColumnDefinition->getDefault()) { throw new QueryBuilderException( sprintf( - 'Cannot change default value of column "%s"', + 'Cannot change default value of column "%s" from "%s" to "%s"', $columnName, + $existingColumnDefinition->getDefault(), + $desiredColumnDefinition->getDefault(), ), self::CANNOT_CHANGE_DEFAULT_VALUE, ); } if ($existingColumnDefinition->isNullable() !== $desiredColumnDefinition->isNullable()) { - $sqlParts[] = $desiredColumnDefinition->isNullable() ? ' DROP NOT NULL' : ' SET NOT NULL'; + $sqlParts[] = $desiredColumnDefinition->isNullable() ? 'DROP NOT NULL' : 'SET NOT NULL'; } $notSameLength = $existingColumnDefinition->getLength() !== $desiredColumnDefinition->getLength(); @@ -300,8 +302,10 @@ public function getUpdateColumnFromDefinitionQuery( } else { throw new QueryBuilderException( sprintf( - 'Cannot decrease precision of column "%s"', + 'Cannot decrease precision of column "%s" from "%s" to "%s"', $columnName, + $existingPrecision, + $desiredPrecision, ) , self::CANNOT_DECREASE_PRECISION); } @@ -324,11 +328,13 @@ public function getUpdateColumnFromDefinitionQuery( $desiredColumnDefinition->getType(), $desiredColumnDefinition->getLength(), ); - } else { + } elseif ($notSameLength) { throw new QueryBuilderException( sprintf( - 'Cannot decrease length of column "%s"', + 'Cannot decrease length of column "%s" from "%s" to "%s"', $columnName, + $existingColumnDefinition->getLength(), + $desiredColumnDefinition->getLength(), ), self::CANNOT_DECREASE_LENGTH); } diff --git a/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php b/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php index c9353fe43..35997a68a 100644 --- a/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php +++ b/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php @@ -117,12 +117,89 @@ public function testGetColumnDefinitionUpdate( ); } - public function provideGetColumnDefinitionUpdate() + /** + * @dataProvider provideInvalidGetColumnDefinitionUpdate + */ + public function testInvalidGetColumnDefinitionUpdate( + Snowflake $existingColumn, + Snowflake $desiredColumn, + string $expectedExceptionMessage, + ): void { + $existingColumnDefinition = $existingColumn; + $desiredColumnDefinition = $desiredColumn; + $this->expectExceptionMessage($expectedExceptionMessage); + $this->qb->getUpdateColumnFromDefinitionQuery( + $existingColumnDefinition, + $desiredColumnDefinition, + 'testDb', + 'testTable', + 'testColumn', + ); + } + + /** + * @return \Generator + */ + public function provideGetColumnDefinitionUpdate(): Generator { - yield 'change length' => [ - new Snowflake('VARCHAR', ['length' =>12, 'nullable' => true, 'default' => '']), - new Snowflake('VARCHAR', ['length' =>38, 'nullable' => true, 'default' => '']), + yield 'drop default' => [ + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => true, 'default' => '10']), + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => true, 'default' => null]), + /** @lang Snowflake */ + 'ALTER TABLE "testDb"."testTable" MODIFY COLUMN "testColumn" DROP DEFAULT', + ]; + yield 'add nullable' => [ + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => false, 'default' => '']), + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => true, 'default' => '']), + /** @lang Snowflake */ + 'ALTER TABLE "testDb"."testTable" MODIFY COLUMN "testColumn" DROP NOT NULL', + ]; + yield 'drop nullable' => [ + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => true, 'default' => '']), + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => false, 'default' => '']), + /** @lang Snowflake */ + 'ALTER TABLE "testDb"."testTable" MODIFY COLUMN "testColumn" SET NOT NULL', + ]; + yield 'increase length of text column' => [ + new Snowflake('VARCHAR', ['length' => '12', 'nullable' => true, 'default' => '']), + new Snowflake('VARCHAR', ['length' => '38', 'nullable' => true, 'default' => '']), + /** @lang Snowflake */ 'ALTER TABLE "testDb"."testTable" MODIFY COLUMN "testColumn" SET DATA TYPE VARCHAR(38)', ]; + yield 'increase precision of numeric column' => [ + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => true, 'default' => '']), + new Snowflake('NUMERIC', ['length' => '14,8', 'nullable' => true, 'default' => '']), + /** @lang Snowflake */ + 'ALTER TABLE "testDb"."testTable" MODIFY COLUMN "testColumn" SET DATA TYPE NUMERIC(14, 8)', + ]; + } + + public function provideInvalidGetColumnDefinitionUpdate(): Generator + { + yield 'add default' => [ + new Snowflake('VARCHAR', ['length' => '10', 'nullable' => true, 'default' => '']), + new Snowflake('VARCHAR', ['length' => '10', 'nullable' => true, 'default' => 'Bedight']), + 'Cannot change default value of column "testColumn" from "" to "Bedight"', + ]; + yield 'change default' => [ + new Snowflake('VARCHAR', ['length' => '10', 'nullable' => true, 'default' => 'Bedight']), + new Snowflake('VARCHAR', ['length' => '10', 'nullable' => true, 'default' => 'Brabble']), + 'Cannot change default value of column "testColumn" from "Bedight" to "Brabble"', + ]; + yield 'descrease length of string' => [ + new Snowflake('VARCHAR', ['length' => '10', 'nullable' => true, 'default' => 'Bedight']), + new Snowflake('VARCHAR', ['length' => '8', 'nullable' => true, 'default' => 'Bedight']), + 'Cannot decrease length of column "testColumn" from "10" to "8"', + ]; + yield 'descrease precision of number' => [ + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => true, 'default' => '']), + new Snowflake('NUMERIC', ['length' => '10,8', 'nullable' => true, 'default' => '']), + 'Cannot decrease precision of column "testColumn" from "12" to "10"', + ]; + yield 'change scale of number' => [ + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => true, 'default' => '']), + new Snowflake('NUMERIC', ['length' => '12,10', 'nullable' => true, 'default' => '']), + 'Cannot change scale of a column "testColumn" from "8" to "10"', + ]; } } From ec6fe65626196060ab0561d305dc73ecd0ff3af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Fri, 9 Feb 2024 08:23:38 +0000 Subject: [PATCH 04/10] CT-1169 fix phpcs --- packages/php-datatypes/tests/SnowflakeDatatypeTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/php-datatypes/tests/SnowflakeDatatypeTest.php b/packages/php-datatypes/tests/SnowflakeDatatypeTest.php index 4ec87548d..1b8d363c1 100644 --- a/packages/php-datatypes/tests/SnowflakeDatatypeTest.php +++ b/packages/php-datatypes/tests/SnowflakeDatatypeTest.php @@ -384,7 +384,7 @@ public function testGetTypeByBasetype(): void } /** - * @param array $expectedArray + * @param array $expectedArray * @dataProvider arrayFromLengthProvider */ public function testArrayFromLength(string $type, ?string $length, array $expectedArray): void @@ -398,22 +398,22 @@ public function arrayFromLengthProvider(): Generator yield 'simple' => [ 'VARCHAR', '10', - ['character_maximum' => '10'] + ['character_maximum' => '10'], ]; yield 'decimal' => [ 'NUMERIC', '38,2', - ['numeric_precision' => 38, 'numeric_scale' => 2] + ['numeric_precision' => 38, 'numeric_scale' => 2], ]; yield 'with zero scale' => [ 'NUMERIC', '38,0', - ['numeric_precision' => 38, 'numeric_scale' => 0] + ['numeric_precision' => 38, 'numeric_scale' => 0], ]; yield 'with null length' => [ 'NUMERIC', null, - [] + [], ]; } } From 1903d507d44be812947f581ea60af88b9980e5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Fri, 9 Feb 2024 08:37:21 +0000 Subject: [PATCH 05/10] CT-1169 fix phpcs --- .../src/Table/Snowflake/SnowflakeTableQueryBuilder.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php index 74b632e90..c273d32a4 100644 --- a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php +++ b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php @@ -226,7 +226,7 @@ public function getUpdateColumnFromDefinitionQuery( Snowflake $desiredColumnDefinition, string $schemaName, string $tableName, - string $columnName + string $columnName, ): string { $sql = sprintf( 'ALTER TABLE %s.%s MODIFY ', @@ -343,7 +343,7 @@ public function getUpdateColumnFromDefinitionQuery( return sprintf( 'COLUMN %s %s', SnowflakeQuote::quoteSingleIdentifier($columnName), - $part + $part, ); }, $sqlParts); return $sql . implode(', ', $partsWithColumnPrefix); From ff32c733f0328ce9088587a055ae0b03b2c0377d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Tue, 13 Feb 2024 12:21:28 +0000 Subject: [PATCH 06/10] CT-1169 list of metadata for column sync --- packages/php-datatypes/src/Definition/Common.php | 6 ++++++ .../Table/Snowflake/SnowflakeTableQueryBuilder.php | 12 +++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/php-datatypes/src/Definition/Common.php b/packages/php-datatypes/src/Definition/Common.php index ddfe1968c..57796be83 100644 --- a/packages/php-datatypes/src/Definition/Common.php +++ b/packages/php-datatypes/src/Definition/Common.php @@ -17,6 +17,12 @@ abstract class Common implements DefinitionInterface public const KBC_METADATA_KEY_COMPRESSION = 'KBC.datatype.compression'; public const KBC_METADATA_KEY_FORMAT = 'KBC.datatype.format'; + public const KBC_METADATA_KEYS_FOR_COLUMNS_SYNC = [ + self::KBC_METADATA_KEY_NULLABLE, + self::KBC_METADATA_KEY_LENGTH, + self::KBC_METADATA_KEY_DEFAULT, + ]; + protected string $type; protected ?string $length = null; diff --git a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php index c273d32a4..067f9bd66 100644 --- a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php +++ b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php @@ -289,7 +289,8 @@ public function getUpdateColumnFromDefinitionQuery( $existingScale, $desiredScale, ), - self::CANNOT_CHANGE_SCALE,); + self::CANNOT_CHANGE_SCALE, + ); } if ($existingPrecision < $desiredPrecision) { @@ -306,8 +307,9 @@ public function getUpdateColumnFromDefinitionQuery( $columnName, $existingPrecision, $desiredPrecision, - ) - , self::CANNOT_DECREASE_PRECISION); + ), + self::CANNOT_DECREASE_PRECISION, + ); } } elseif ($notSameLength && $isNewLengthBigger) { if ($desiredColumnDefinition->isTypeWithComplexLength()) { @@ -317,8 +319,8 @@ public function getUpdateColumnFromDefinitionQuery( $columnName, $existingColumnDefinition->getLength(), $desiredColumnDefinition->getLength(), - ) - , + ), + self::CANNOT_INTRODUCE_COMPLEX_LENGTH, ); } From 4447bc2558d3ea5ffe6eb1fb8ffaa620fda6b48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Wed, 14 Feb 2024 10:24:54 +0000 Subject: [PATCH 07/10] CT-1169 phpcs --- .../src/Table/Snowflake/SnowflakeTableQueryBuilder.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php index 067f9bd66..58300dfdd 100644 --- a/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php +++ b/packages/php-table-backend-utils/src/Table/Snowflake/SnowflakeTableQueryBuilder.php @@ -320,7 +320,6 @@ public function getUpdateColumnFromDefinitionQuery( $existingColumnDefinition->getLength(), $desiredColumnDefinition->getLength(), ), - self::CANNOT_INTRODUCE_COMPLEX_LENGTH, ); } @@ -338,7 +337,8 @@ public function getUpdateColumnFromDefinitionQuery( $existingColumnDefinition->getLength(), $desiredColumnDefinition->getLength(), ), - self::CANNOT_DECREASE_LENGTH); + self::CANNOT_DECREASE_LENGTH, + ); } $partsWithColumnPrefix = array_map(function (string $part) use ($columnName) { From 3c395b93a31d631a2c74912fdd1c80a699ab766a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Wed, 14 Feb 2024 13:24:30 +0000 Subject: [PATCH 08/10] CT-1169 phpstan --- packages/php-datatypes/src/Definition/Snowflake.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/php-datatypes/src/Definition/Snowflake.php b/packages/php-datatypes/src/Definition/Snowflake.php index 1a62610e8..2a00cb718 100644 --- a/packages/php-datatypes/src/Definition/Snowflake.php +++ b/packages/php-datatypes/src/Definition/Snowflake.php @@ -215,6 +215,15 @@ public function getArrayFromLength(): array return ['character_maximum' => $this->getLength()]; } + /** + * @phpstan-assert-if-true array{ + * numeric_precision:string, + * numeric_scale:string + * } $this->getArrayFromLength() + * @phpstan-assert-if-false array{ + * character_maximum:string + * } $this->getArrayFromLength() + */ public function isTypeWithComplexLength(): bool { return in_array($this->getType(), self::TYPES_WITH_COMPLEX_LENGTH, true); From a5b769cad0533c8442397337b9b84ba3f43bc914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Thu, 15 Feb 2024 12:54:40 +0000 Subject: [PATCH 09/10] CT-1169 handle default precision for SNFLK --- packages/php-datatypes/src/Definition/Snowflake.php | 10 ++++++---- packages/php-datatypes/tests/SnowflakeDatatypeTest.php | 7 ++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/php-datatypes/src/Definition/Snowflake.php b/packages/php-datatypes/src/Definition/Snowflake.php index 2a00cb718..fbdb42d0e 100644 --- a/packages/php-datatypes/src/Definition/Snowflake.php +++ b/packages/php-datatypes/src/Definition/Snowflake.php @@ -205,11 +205,13 @@ private function getLengthFromArray(array $lengthOptions): ?string */ public function getArrayFromLength(): array { - if ($this->getLength() === null || $this->getLength() === '') { - return []; - } if ($this->isTypeWithComplexLength()) { - $parsed = array_map(intval(...), explode(',', $this->getLength())); + if ($this->getLength() === null || $this->getLength() === '') { + $parsed = []; + } else { + $parsed = array_map(intval(...), explode(',', (string) $this->getLength())); + } + $parsed = $parsed + [38, 0]; return ['numeric_precision' => $parsed[0], 'numeric_scale' => $parsed[1]]; } return ['character_maximum' => $this->getLength()]; diff --git a/packages/php-datatypes/tests/SnowflakeDatatypeTest.php b/packages/php-datatypes/tests/SnowflakeDatatypeTest.php index 1b8d363c1..6105c3846 100644 --- a/packages/php-datatypes/tests/SnowflakeDatatypeTest.php +++ b/packages/php-datatypes/tests/SnowflakeDatatypeTest.php @@ -413,7 +413,12 @@ public function arrayFromLengthProvider(): Generator yield 'with null length' => [ 'NUMERIC', null, - [], + ['numeric_precision' => 38, 'numeric_scale' => 0], + ]; + yield 'numeric with int length' => [ + 'NUMERIC', + '10', + ['numeric_precision' => 10, 'numeric_scale' => 0], ]; } } From f3b83baff0f6c1cb4519090d38270a615b2a636d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Fejfar?= Date: Thu, 15 Feb 2024 12:57:04 +0000 Subject: [PATCH 10/10] CT-1169 test multiple changes in one go --- .../Table/Snowflake/SnowflakeTableQueryBuilderTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php b/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php index 35997a68a..eecc5aeb0 100644 --- a/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php +++ b/packages/php-table-backend-utils/tests/Unit/Table/Snowflake/SnowflakeTableQueryBuilderTest.php @@ -172,6 +172,13 @@ public function provideGetColumnDefinitionUpdate(): Generator /** @lang Snowflake */ 'ALTER TABLE "testDb"."testTable" MODIFY COLUMN "testColumn" SET DATA TYPE NUMERIC(14, 8)', ]; + yield 'full set of changes (increase precision, drop nullable, drop default)' => [ + new Snowflake('NUMERIC', ['length' => '12,8', 'nullable' => true, 'default' => 'grunbread']), + new Snowflake('NUMERIC', ['length' => '14,8', 'nullable' => false, 'default' => '']), + /** @lang Snowflake */ + 'ALTER TABLE "testDb"."testTable" MODIFY COLUMN "testColumn" DROP DEFAULT, ' + . 'COLUMN "testColumn" SET NOT NULL, COLUMN "testColumn" SET DATA TYPE NUMERIC(14, 8)', + ]; } public function provideInvalidGetColumnDefinitionUpdate(): Generator