%PDF- %PDF-
| Direktori : /www/varak.net/losik.varak.net/vendor/nette/database/src/Database/Drivers/ |
| Current File : //www/varak.net/losik.varak.net/vendor/nette/database/src/Database/Drivers/MsSqlDriver.php |
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare(strict_types=1);
namespace Nette\Database\Drivers;
use Nette;
/**
* Supplemental MS SQL database driver.
*/
class MsSqlDriver implements Nette\Database\Driver
{
use Nette\SmartObject;
/** @var Nette\Database\Connection */
private $connection;
public function initialize(Nette\Database\Connection $connection, array $options): void
{
$this->connection = $connection;
}
public function convertException(\PDOException $e): Nette\Database\DriverException
{
return Nette\Database\DriverException::from($e);
}
/********************* SQL ****************d*g**/
public function delimite(string $name): string
{
// @see https://msdn.microsoft.com/en-us/library/ms176027.aspx
return '[' . str_replace(['[', ']'], ['[[', ']]'], $name) . ']';
}
public function formatDateTime(\DateTimeInterface $value): string
{
return $value->format("'Y-m-d H:i:s'");
}
public function formatDateInterval(\DateInterval $value): string
{
throw new Nette\NotSupportedException;
}
public function formatLike(string $value, int $pos): string
{
$value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
}
public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
{
if ($offset) {
throw new Nette\NotSupportedException('Offset is not supported by this database.');
} elseif ($limit < 0) {
throw new Nette\InvalidArgumentException('Negative offset or limit.');
} elseif ($limit !== null) {
$sql = preg_replace('#^\s*(SELECT(\s+DISTINCT|\s+ALL)?|UPDATE|DELETE)#i', '$0 TOP ' . (int) $limit, $sql, 1, $count);
if (!$count) {
throw new Nette\InvalidArgumentException('SQL query must begin with SELECT, UPDATE or DELETE command.');
}
}
}
/********************* reflection ****************d*g**/
public function getTables(): array
{
$tables = [];
foreach ($this->connection->query('SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES') as $row) {
$tables[] = [
'name' => $row['TABLE_SCHEMA'] . '.' . $row['TABLE_NAME'],
'view' => ($row['TABLE_TYPE'] ?? null) === 'VIEW',
];
}
return $tables;
}
public function getColumns(string $table): array
{
[$table_schema, $table_name] = explode('.', $table);
$columns = [];
$query = "
SELECT
COLUMN_NAME,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH,
NUMERIC_PRECISION,
IS_NULLABLE,
COLUMN_DEFAULT,
DOMAIN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = {$this->connection->quote($table_schema)}
AND TABLE_NAME = {$this->connection->quote($table_name)}";
foreach ($this->connection->query($query) as $row) {
$columns[] = [
'name' => $row['COLUMN_NAME'],
'table' => $table,
'nativetype' => strtoupper($row['DATA_TYPE']),
'size' => $row['CHARACTER_MAXIMUM_LENGTH'] ?? ($row['NUMERIC_PRECISION'] ?? null),
'unsigned' => false,
'nullable' => $row['IS_NULLABLE'] === 'YES',
'default' => $row['COLUMN_DEFAULT'],
'autoincrement' => $row['DOMAIN_NAME'] === 'COUNTER',
'primary' => $row['COLUMN_NAME'] === 'ID',
'vendor' => (array) $row,
];
}
return $columns;
}
public function getIndexes(string $table): array
{
[, $table_name] = explode('.', $table);
$indexes = [];
$query = "
SELECT
name_index = ind.name,
id_column = ic.index_column_id,
name_column = col.name,
ind.is_unique,
ind.is_primary_key
FROM
sys.indexes ind
INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
INNER JOIN sys.tables t ON ind.object_id = t.object_id
WHERE
t.name = {$this->connection->quote($table_name)}
ORDER BY
t.name, ind.name, ind.index_id, ic.index_column_id";
foreach ($this->connection->query($query) as $row) {
$id = $row['name_index'];
$indexes[$id]['name'] = $id;
$indexes[$id]['unique'] = $row['is_unique'] !== 'False';
$indexes[$id]['primary'] = $row['is_primary_key'] !== 'False';
$indexes[$id]['columns'][$row['id_column'] - 1] = $row['name_column'];
}
return array_values($indexes);
}
public function getForeignKeys(string $table): array
{
[$table_schema, $table_name] = explode('.', $table);
$keys = [];
$query = "
SELECT
obj.name AS [fk_name],
col1.name AS [column],
tab2.name AS [referenced_table],
col2.name AS [referenced_column]
FROM
sys.foreign_key_columns fkc
INNER JOIN sys.objects obj
ON obj.object_id = fkc.constraint_object_id
INNER JOIN sys.tables tab1
ON tab1.object_id = fkc.parent_object_id
INNER JOIN sys.schemas sch
ON tab1.schema_id = sch.schema_id
INNER JOIN sys.columns col1
ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
INNER JOIN sys.tables tab2
ON tab2.object_id = fkc.referenced_object_id
INNER JOIN sys.columns col2
ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
WHERE
tab1.name = {$this->connection->quote($table_name)}";
foreach ($this->connection->query($query) as $id => $row) {
$keys[$id]['name'] = $row['fk_name'];
$keys[$id]['local'] = $row['column'];
$keys[$id]['table'] = $table_schema . '.' . $row['referenced_table'];
$keys[$id]['foreign'] = $row['referenced_column'];
}
return array_values($keys);
}
public function getColumnTypes(\PDOStatement $statement): array
{
return Nette\Database\Helpers::detectTypes($statement);
}
public function isSupported(string $item): bool
{
return $item === self::SUPPORT_SUBSELECT;
}
}