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; } }