Skip to content

Commit

Permalink
DMD-33 add test for empty schema
Browse files Browse the repository at this point in the history
  • Loading branch information
vojtabiberle committed Jan 23, 2025
1 parent ba2394a commit 9222584
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Keboola\TableBackendUtils\Schema\Snowflake;

use Doctrine\DBAL\Connection;
use Keboola\Datatype\Definition\Snowflake;
use Keboola\TableBackendUtils\Column\ColumnCollection;
use Keboola\TableBackendUtils\Column\Snowflake\SnowflakeColumn;
use Keboola\TableBackendUtils\Escaping\Snowflake\SnowflakeQuote;
Expand Down Expand Up @@ -68,18 +69,33 @@ public function getDefinitions(): array
SnowflakeQuote::quote($this->schemaName),
);

// Snowflake maps in DESC TABLE few data-type aliases to their basic types
// but in INFORMATION_SCHEMA.COLUMNS table keep data-type aliases
// here is implemented same mapping as DESC TABLE uses
$columnsQuery = sprintf(
<<<SQL
SELECT
TABLE_NAME,
COLUMN_NAME AS "name",
CASE
-- Map string types to VARCHAR
WHEN DATA_TYPE IN ('CHAR', 'VARCHAR', 'STRING', 'TEXT') THEN
DATA_TYPE || '(' || CHARACTER_MAXIMUM_LENGTH || ')'
'VARCHAR(' || COALESCE(CHARACTER_MAXIMUM_LENGTH::STRING, '16777216') || ')'
-- Map numeric types to NUMBER
WHEN DATA_TYPE IN ('NUMBER', 'DECIMAL', 'NUMERIC') THEN
DATA_TYPE || '(' || COALESCE(NUMERIC_PRECISION::STRING, '') || ',' || COALESCE(NUMERIC_SCALE::STRING, '0') || ')'
ELSE
DATA_TYPE
'NUMBER(' || COALESCE(NUMERIC_PRECISION::STRING, '') || ',' || COALESCE(NUMERIC_SCALE::STRING, '0') || ')'
-- Map date and time types to their respective names - DATE is mapped directly to DATE
WHEN DATA_TYPE IN ('DATETIME', 'TIME', 'TIMESTAMP', 'TIMESTAMP_LTZ', 'TIMESTAMP_TZ', 'TIMESTAMP_NTZ') THEN
DATA_TYPE || '(' || COALESCE(DATETIME_PRECISION::STRING, '') || ')'
-- Map binary and varbinary - Snowflake don't have length for binary in INFORMATION_SCHEMA - handled in code
WHEN DATA_TYPE IN ('BINARY', 'VARBINARY') THEN
'BINARY'
-- Default case for all other types as they are mapped by DESC TABLE direcly to themself
ELSE DATA_TYPE
END AS "type",
COLUMN_DEFAULT AS "default",
IS_NULLABLE AS "null?"
Expand All @@ -96,6 +112,12 @@ public function getDefinitions(): array

/** @var array<int, array{TABLE_NAME: string, TABLE_TYPE: string, BYTES: int, ROW_COUNT: int}> $informations */
$informations = $this->connection->fetchAllAssociative($informationsQuery);

// short-circuit > no tables no need to continue
if (count($informations) === 0) {
return [];
}

/** @var array<int, array{TABLE_NAME: string, name: string, type: string, default: string, null?: string}> $columns */
$columns = $this->connection->fetchAllAssociative($columnsQuery);
/** @var array<int, array{
Expand Down Expand Up @@ -146,6 +168,18 @@ public function getDefinitions(): array
// array{TABLE_NAME: string, name: string, type: string, default: string, null?: string}.
// @phpstan-ignore-next-line
$column['null?'] = ($column['null?'] === 'YES' ? 'Y' : 'N');

// Snowflake have length for binary columns only in DESC TABLE or SHOW COLUMNS
if ($column['type'] === Snowflake::TYPE_BINARY) {
$info = $this->getBinaryColumnLength($column['TABLE_NAME'], $column['name']);
if ($info !== null) {
$column['type'] = sprintf(
'%s(%s)',
Snowflake::TYPE_BINARY,
$info['length'],
);
}
}
$tables[$column['TABLE_NAME']]['COLUMNS'][] = SnowflakeColumn::createFromDB($column);
}

Expand All @@ -166,4 +200,38 @@ public function getDefinitions(): array
}
return $definitions;
}

/**
* @return array{type: string, length: string}|null
*/
private function getBinaryColumnLength(string $tableName, string $columnName): ?array
{
$sql = sprintf('DESCRIBE TABLE %s', SnowflakeQuote::quote($tableName));
/** @var array<
* int,
* array{
* name: string,
* type: string,
* kind: string,
* null?: string,
* default: ?string,
* "primary key": string,
* "unique key": string,
* check: ?string,
* expression: ?string,
* comment: ?string,
* "policy name": ?string,
* "privacy domain": ?string
* }
* > $columns
*/
$columns = $this->connection->fetchAllAssociative($sql);
foreach ($columns as $column) {
if ($column['name'] === $columnName) {
return SnowflakeColumn::extractTypeAndLengthFromDB($column['type']);
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,12 @@ public function testGetDefinitions(): void
self::assertFalse($definitions[$genericViewKey]->isTemporary());
self::assertEquals('view', $definitions[$genericViewKey]->getTableType()->value);
}

public function testGetDefinitionsWithEmptySchema(): void
{
$this->createSchema(self::TEST_SCHEMA);
$definitions = $this->schemaRef->getDefinitions();

self::assertCount(0, $definitions);
}
}

0 comments on commit 9222584

Please sign in to comment.