Final Class Yiisoft\Db\Mssql\Schema
| Inheritance | Yiisoft\Db\Mssql\Schema » Yiisoft\Db\Driver\Pdo\AbstractPdoSchema |
|---|
Implements the MSSQL Server specific schema, supporting MSSQL Server 2017 and above.
Psalm Types
| Name | Value |
|---|---|
| ColumnArray | array{check: string|null, collation_name: string|null, column_name: string, column_default: string|null, is_nullable: string, data_type: string, size: integer|string|null, numeric_scale: integer|string|null, is_identity: string, is_computed: string, comment: string|null, primaryKey: boolean, schema: string|null, table: string} |
Protected Properties
| Property | Type | Description | Defined By |
|---|---|---|---|
| $defaultSchema | string | The default schema used for the current session. | Yiisoft\Db\Mssql\Schema |
Protected Methods
Property Details
The default schema used for the current session.
Method Details
Collects the metadata of table columns.
| protected boolean findColumns ( Yiisoft\Db\Mssql\TableSchema $table ) | ||
| $table | Yiisoft\Db\Mssql\TableSchema |
The table metadata. |
| return | boolean |
Whether the table exists in the database. |
|---|---|---|
protected function findColumns(TableSchemaInterface $table): bool
{
$schemaName = $table->getSchemaName();
$tableName = $table->getName();
$catalogName = $table->getCatalogName();
$columnsTableName = '[INFORMATION_SCHEMA].[COLUMNS]';
$whereSql = '[t].[table_name] = :table_name';
$whereParams = [':table_name' => $tableName];
if ($catalogName !== '') {
$columnsTableName = "[$catalogName].$columnsTableName";
$whereSql .= ' AND [t].[table_catalog] = :catalog';
$whereParams[':catalog'] = $catalogName;
}
if ($schemaName !== '') {
$whereSql .= ' AND [t].[table_schema] = :schema_name';
$whereParams[':schema_name'] = $schemaName;
}
$sql = <<<SQL
SELECT
[t].[column_name],
[t].[column_default],
[t].[is_nullable],
[t].[data_type],
COALESCE(NULLIF([t].[character_maximum_length], -1), [t].[numeric_precision], [t].[datetime_precision]) AS [size],
[t].[numeric_scale],
[t].[collation_name],
COLUMNPROPERTY(OBJECT_ID([t].[table_schema] + '.' + [t].[table_name]), [t].[column_name], 'IsIdentity') AS [is_identity],
COLUMNPROPERTY(OBJECT_ID([t].[table_schema] + '.' + [t].[table_name]), [t].[column_name], 'IsComputed') AS [is_computed],
[ext].[value] as [comment],
[c].[definition] AS [check]
FROM $columnsTableName AS [t]
LEFT JOIN [sys].[extended_properties] AS [ext]
ON [ext].[class] = 1
AND [ext].[class_desc] = 'OBJECT_OR_COLUMN'
AND [ext].[name] = 'MS_Description'
AND [ext].[major_id] = OBJECT_ID([t].[table_schema] + '.' + [t].[table_name])
AND [ext].[minor_id] = COLUMNPROPERTY([ext].[major_id], [t].[column_name], 'ColumnID')
LEFT JOIN [sys].[check_constraints] AS [c]
ON [c].[parent_object_id] = OBJECT_ID([t].[table_schema] + '.' + [t].[table_name])
AND [c].[parent_column_id] = COLUMNPROPERTY([c].[parent_object_id], [t].[column_name], 'ColumnID')
WHERE $whereSql
SQL;
try {
$columns = $this->db->createCommand($sql, $whereParams)->queryAll();
if (empty($columns)) {
return false;
}
} catch (Exception) {
return false;
}
$primaryKey = $this->getTablePrimaryKey($table->getFullName(), true);
/** @psalm-suppress MixedArgumentTypeCoercion */
$primaryKeys = array_fill_keys((array) $primaryKey?->columnNames, true);
foreach ($columns as $info) {
$info = array_change_key_case($info);
/** @psalm-var ColumnArray $info */
$info['primaryKey'] = isset($primaryKeys[$info['column_name']]);
$info['schema'] = $schemaName;
$info['table'] = $tableName;
$column = $this->loadColumn($info);
if ($column->isPrimaryKey() && $column->isAutoIncrement()) {
$table->sequenceName('');
}
$table->column($info['column_name'], $column);
}
return true;
}
| protected array findSchemaNames ( ) |
protected function findSchemaNames(): array
{
$sql = <<<SQL
SELECT [s].[name]
FROM [sys].[schemas] AS [s]
INNER JOIN [sys].[database_principals] AS [p] ON [p].[principal_id] = [s].[principal_id]
WHERE [p].[is_fixed_role] = 0 AND [p].[sid] IS NOT NULL
ORDER BY [s].[name] ASC
SQL;
/** @var string[] */
return $this->db->createCommand($sql)->queryColumn();
}
| protected void findTableComment ( \Yiisoft\Db\Schema\TableSchemaInterface $tableSchema ) | ||
| $tableSchema | \Yiisoft\Db\Schema\TableSchemaInterface | |
protected function findTableComment(TableSchemaInterface $tableSchema): void
{
$schemaName = $tableSchema->getSchemaName() ?: $this->defaultSchema;
$schemaName = "N'$schemaName'";
$tableName = 'N' . $this->db->getQuoter()->quoteValue($tableSchema->getName());
$sql = <<<SQL
SELECT [value]
FROM fn_listextendedproperty (
N'MS_description',
'SCHEMA', $schemaName,
'TABLE', $tableName,
DEFAULT, DEFAULT)
SQL;
$comment = $this->db->createCommand($sql)->queryScalar();
$tableSchema->comment(is_string($comment) ? $comment : null);
}
| protected array findTableNames ( string $schema = '' ) | ||
| $schema | string | |
protected function findTableNames(string $schema = ''): array
{
if ($schema === '') {
$schema = $this->defaultSchema;
}
$sql = <<<SQL
SELECT [t].[table_name]
FROM [INFORMATION_SCHEMA].[TABLES] AS [t]
WHERE [t].[table_schema] = :schema AND [t].[table_type] IN ('BASE TABLE', 'VIEW')
ORDER BY [t].[table_name]
SQL;
/** @var string[] */
return $this->db->createCommand($sql, [':schema' => $schema])->queryColumn();
}
| protected array findViewNames ( string $schema = '' ) | ||
| $schema | string | |
protected function findViewNames(string $schema = ''): array
{
if ($schema === '') {
$schema = $this->defaultSchema;
}
$sql = <<<SQL
SELECT [t].[table_name]
FROM [INFORMATION_SCHEMA].[TABLES] AS [t]
WHERE [t].[table_schema] = :schema AND [t].[table_type] = 'VIEW'
ORDER BY [t].[table_name]
SQL;
/** @var string[] */
return $this->db->createCommand($sql, [':schema' => $schema])->queryColumn();
}
| protected \Yiisoft\Db\Schema\Column\ColumnInterface|null loadResultColumn ( array $metadata ) | ||
| $metadata | array | |
protected function loadResultColumn(array $metadata): ?ColumnInterface
{
if (empty($metadata['sqlsrv:decl_type'])) {
return null;
}
$dbType = $metadata['sqlsrv:decl_type'];
$columnInfo = ['source' => ColumnInfoSource::QUERY_RESULT];
if (str_ends_with($dbType, ' identity')) {
$columnInfo['autoIncrement'] = true;
$dbType = substr($dbType, 0, -9);
}
if (!empty($metadata['table'])) {
$columnInfo['table'] = $metadata['table'];
$columnInfo['name'] = $metadata['name'];
} elseif (!empty($metadata['name'])) {
$columnInfo['name'] = $metadata['name'];
}
if (!empty($metadata['len'])) {
$columnInfo['size'] = match ($dbType) {
'time', 'datetime', 'datetime2', 'datetimeoffset' => $metadata['precision'],
default => $metadata['len'],
};
}
match ($dbType) {
'decimal', 'numeric' => $columnInfo['scale'] = $metadata['precision'],
default => null,
};
return $this->db->getColumnFactory()->fromDbType($dbType, $columnInfo);
}
| protected array loadTableChecks ( string $tableName ) | ||
| $tableName | string | |
protected function loadTableChecks(string $tableName): array
{
/** @var Check[] */
return $this->loadTableConstraints($tableName, self::CHECKS);
}
| protected array loadTableDefaultValues ( string $tableName ) | ||
| $tableName | string | |
protected function loadTableDefaultValues(string $tableName): array
{
/** @var DefaultValue[] */
return $this->loadTableConstraints($tableName, self::DEFAULTS);
}
| protected array loadTableForeignKeys ( string $tableName ) | ||
| $tableName | string | |
protected function loadTableForeignKeys(string $tableName): array
{
/** @var ForeignKey[] */
return $this->loadTableConstraints($tableName, self::FOREIGN_KEYS);
}
| protected array loadTableIndexes ( string $tableName ) | ||
| $tableName | string | |
protected function loadTableIndexes(string $tableName): array
{
$sql = <<<SQL
SELECT
[i].[name] AS [name],
[iccol].[name] AS [column_name],
[i].[is_unique],
[i].[is_primary_key]
FROM [sys].[indexes] AS [i]
INNER JOIN [sys].[index_columns] AS [ic]
ON [ic].[object_id] = [i].[object_id] AND [ic].[index_id] = [i].[index_id]
INNER JOIN [sys].[columns] AS [iccol]
ON [iccol].[object_id] = [ic].[object_id] AND [iccol].[column_id] = [ic].[column_id]
WHERE [i].[object_id] = OBJECT_ID(:fullName)
ORDER BY [ic].[key_ordinal] ASC
SQL;
$indexes = $this->db->createCommand($sql, [':fullName' => $tableName])->queryAll();
/** @psalm-var list<array<string,mixed>> $indexes */
$indexes = array_map(array_change_key_case(...), $indexes);
$indexes = DbArrayHelper::arrange($indexes, ['name']);
$result = [];
/**
* @psalm-var array<
* string,
* list<array{name: string, column_name: string, is_unique: string, is_primary_key: string}>
* > $indexes
*/
foreach ($indexes as $name => $index) {
$result[$name] = new Index(
$name,
array_column($index, 'column_name'),
(bool) $index[0]['is_unique'],
(bool) $index[0]['is_primary_key'],
);
}
return $result;
}
| protected \Yiisoft\Db\Schema\TableSchemaInterface|null loadTableSchema ( string $name ) | ||
| $name | string | |
protected function loadTableSchema(string $name): ?TableSchemaInterface
{
/** @psalm-suppress MixedArgument */
$table = new TableSchema(...$this->db->getQuoter()->getTableNameParts($name));
if ($this->findColumns($table)) {
$this->findTableComment($table);
$this->findConstraints($table);
return $table;
}
return null;
}
| protected string resolveFullName ( string $name, string $schemaName = '', string $catalogName = '', string $serverName = '' ) | ||
| $name | string | |
| $schemaName | string | |
| $catalogName | string | |
| $serverName | string | |
protected function resolveFullName(
string $name,
string $schemaName = '',
string $catalogName = '',
string $serverName = '',
): string {
$quoter = $this->db->getQuoter();
$fullName = $quoter->getRawTableName($name);
if ($schemaName === '' || $schemaName === $this->defaultSchema) {
return $fullName;
}
$fullName = $quoter->getRawTableName($schemaName) . ".$fullName";
if ($catalogName === '') {
return $fullName;
}
$fullName = $quoter->getRawTableName($catalogName) . ".$fullName";
if ($serverName === '') {
return $fullName;
}
return $quoter->getRawTableName($serverName) . ".$fullName";
}
Signup or Login in order to comment.