56 lines
2.5 KiB
PHP
56 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace Modules\EcommerceFinance\Services;
|
|
|
|
use InvalidArgumentException;
|
|
|
|
class UpstreamSqlDialect
|
|
{
|
|
public function __construct(public readonly string $driver)
|
|
{
|
|
if (! in_array($driver, ['sqlsrv', 'pgsql', 'mysql'], true)) {
|
|
throw new InvalidArgumentException('不支持的上游数据库类型。');
|
|
}
|
|
}
|
|
|
|
public function quote(string $identifier): string
|
|
{
|
|
if ($identifier === '' || str_contains($identifier, "\0")) throw new InvalidArgumentException('无效的数据库标识符。');
|
|
return match ($this->driver) {
|
|
'pgsql' => '"' . str_replace('"', '""', $identifier) . '"',
|
|
'mysql' => '`' . str_replace('`', '``', $identifier) . '`',
|
|
default => '[' . str_replace(']', ']]', $identifier) . ']',
|
|
};
|
|
}
|
|
|
|
public function select(string $columns, string $tail, int $limit): string
|
|
{
|
|
$limit = min(max($limit, 1), 5000);
|
|
return $this->driver === 'sqlsrv'
|
|
? 'SELECT TOP (' . $limit . ') ' . $columns . ' ' . $tail
|
|
: 'SELECT ' . $columns . ' ' . $tail . ' LIMIT ' . $limit;
|
|
}
|
|
|
|
public function catalogSql(): string
|
|
{
|
|
// Same normalized catalog shape for all engines; MySQL never enumerates other databases.
|
|
$schema = $this->driver === 'sqlsrv' ? 'INFORMATION_SCHEMA' : 'information_schema';
|
|
$sql = "SELECT c.table_schema AS schema_name, c.table_name AS object_name,
|
|
CASE WHEN t.table_type = 'VIEW' THEN 'view' ELSE 'table' END AS object_type,
|
|
c.column_name AS column_name, c.ordinal_position AS ordinal_position,
|
|
c.data_type AS data_type, c.character_maximum_length AS max_length,
|
|
c.numeric_precision AS numeric_precision, c.numeric_scale AS numeric_scale,
|
|
c.is_nullable AS is_nullable
|
|
FROM {$schema}." . ($this->driver === 'sqlsrv' ? 'COLUMNS' : 'columns') . " c
|
|
INNER JOIN {$schema}." . ($this->driver === 'sqlsrv' ? 'TABLES' : 'tables') . " t
|
|
ON t.table_schema = c.table_schema AND t.table_name = c.table_name
|
|
WHERE c.table_schema NOT IN ('sys', 'INFORMATION_SCHEMA', 'information_schema', 'pg_catalog', 'mysql', 'performance_schema')";
|
|
if ($this->driver === 'mysql') $sql .= ' AND c.table_schema = DATABASE()';
|
|
$sql .= ' ORDER BY c.table_schema, c.table_name, c.ordinal_position';
|
|
if ($this->driver === 'sqlsrv') {
|
|
$sql = preg_replace_callback('/\b([ct])\.([a-z_]+)\b/', fn ($m) => $m[1] . '.' . strtoupper($m[2]), $sql);
|
|
}
|
|
return $sql;
|
|
}
|
|
}
|