Skip to content

Commit 1d178bc

Browse files
committed
[BUGFIX] Fix issue #35
Add a.attisdropped = false flag to compile columns sql to fix the output of Schema::getColumns(). Add custom cockroach db driver for loading the custom cockroach schema manager to fix renaming issue #35
1 parent 918c00b commit 1d178bc

File tree

4 files changed

+128
-2
lines changed

4 files changed

+128
-2
lines changed

src/CockroachDbConnection.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
use Illuminate\Database\ConnectionInterface;
66
use Illuminate\Database\Grammar as BaseGrammar;
7-
use Illuminate\Database\PDO\PostgresDriver;
87
use Illuminate\Database\PostgresConnection;
98
use Illuminate\Filesystem\Filesystem;
109
use YlsIdeas\CockroachDb\Builder\CockroachDbBuilder as DbBuilder;
10+
use YlsIdeas\CockroachDb\Driver\CockroachDBDriver;
1111
use YlsIdeas\CockroachDb\Processor\CockroachDbProcessor as DbProcessor;
1212
use YlsIdeas\CockroachDb\Query\CockroachGrammar as QueryGrammar;
1313
use YlsIdeas\CockroachDb\Schema\CockroachGrammar as SchemaGrammar;
@@ -76,7 +76,7 @@ protected function getDefaultPostProcessor(): DbProcessor
7676
*/
7777
protected function getDoctrineDriver()
7878
{
79-
return new PostgresDriver();
79+
return new CockroachDBDriver();
8080
}
8181

8282
/**

src/Driver/CockroachDBDriver.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace YlsIdeas\CockroachDb\Driver;
4+
5+
use Doctrine\DBAL\Connection;
6+
use Doctrine\DBAL\Platforms\AbstractPlatform;
7+
use Doctrine\DBAL\Schema\AbstractSchemaManager;
8+
use Illuminate\Database\PDO\PostgresDriver;
9+
use YlsIdeas\CockroachDb\Schema\CockroachSchemaManager;
10+
11+
class CockroachDBDriver extends PostgresDriver
12+
{
13+
public function getSchemaManager(Connection $conn, AbstractPlatform $platform): AbstractSchemaManager
14+
{
15+
return new CockroachSchemaManager($conn, $platform);
16+
}
17+
}

src/Schema/CockroachGrammar.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,20 @@ public function compileDropUnique(Blueprint $blueprint, Fluent $command)
6868

6969
return "drop index {$this->wrapTable($blueprint)}@{$index} cascade";
7070
}
71+
72+
public function compileColumns($database, $schema, $table): string
73+
{
74+
return sprintf(
75+
'select a.attname as name, t.typname as type_name, format_type(a.atttypid, a.atttypmod) as type, '
76+
.'(select tc.collcollate from pg_catalog.pg_collation tc where tc.oid = a.attcollation) as collation, '
77+
.'not a.attnotnull as nullable, '
78+
.'(select pg_get_expr(adbin, adrelid) from pg_attrdef where c.oid = pg_attrdef.adrelid and pg_attrdef.adnum = a.attnum) as default, '
79+
.'col_description(c.oid, a.attnum) as comment '
80+
.'from pg_attribute a, pg_class c, pg_type t, pg_namespace n '
81+
.'where c.relname = %s and n.nspname = %s and a.attnum > 0 and a.attrelid = c.oid and a.atttypid = t.oid and n.oid = c.relnamespace and a.attisdropped = false '
82+
.'order by a.attnum',
83+
$this->quoteString($table),
84+
$this->quoteString($schema)
85+
);
86+
}
7187
}

src/Schema/CockroachSchemaManager.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
namespace YlsIdeas\CockroachDb\Schema;
4+
5+
use Doctrine\DBAL\Result;
6+
use Doctrine\DBAL\Schema\Identifier;
7+
use Doctrine\DBAL\Schema\PostgreSQLSchemaManager;
8+
9+
class CockroachSchemaManager extends PostgreSQLSchemaManager
10+
{
11+
protected function selectTableColumns(string $databaseName, ?string $tableName = null): Result
12+
{
13+
$sql = 'SELECT';
14+
15+
if ($tableName === null) {
16+
$sql .= ' c.relname AS table_name, n.nspname AS schema_name,';
17+
}
18+
19+
$sql .= <<<'SQL'
20+
a.attnum,
21+
quote_ident(a.attname) AS field,
22+
t.typname AS type,
23+
format_type(a.atttypid, a.atttypmod) AS complete_type,
24+
(SELECT tc.collcollate FROM pg_catalog.pg_collation tc WHERE tc.oid = a.attcollation) AS collation,
25+
(SELECT t1.typname FROM pg_catalog.pg_type t1 WHERE t1.oid = t.typbasetype) AS domain_type,
26+
(SELECT format_type(t2.typbasetype, t2.typtypmod) FROM
27+
pg_catalog.pg_type t2 WHERE t2.typtype = 'd' AND t2.oid = a.atttypid) AS domain_complete_type,
28+
a.attnotnull AS isnotnull,
29+
(SELECT 't'
30+
FROM pg_index
31+
WHERE c.oid = pg_index.indrelid
32+
AND pg_index.indkey[0] = a.attnum
33+
AND pg_index.indisprimary = 't'
34+
) AS pri,
35+
(SELECT pg_get_expr(adbin, adrelid)
36+
FROM pg_attrdef
37+
WHERE c.oid = pg_attrdef.adrelid
38+
AND pg_attrdef.adnum=a.attnum
39+
) AS default,
40+
(SELECT pg_description.description
41+
FROM pg_description WHERE pg_description.objoid = c.oid AND a.attnum = pg_description.objsubid
42+
) AS comment
43+
FROM pg_attribute a
44+
INNER JOIN pg_class c
45+
ON c.oid = a.attrelid
46+
INNER JOIN pg_type t
47+
ON t.oid = a.atttypid
48+
INNER JOIN pg_namespace n
49+
ON n.oid = c.relnamespace
50+
LEFT JOIN pg_depend d
51+
ON d.objid = c.oid
52+
AND d.deptype = 'e'
53+
AND d.classid = (SELECT oid FROM pg_class WHERE relname = 'pg_class')
54+
SQL;
55+
56+
$conditions = array_merge([
57+
'a.attnum > 0',
58+
"c.relkind = 'r'",
59+
'd.refobjid IS NULL',
60+
'a.attisdropped = false',
61+
], $this->buildQueryConditions($tableName));
62+
63+
$sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY a.attnum';
64+
65+
return $this->_conn->executeQuery($sql);
66+
}
67+
68+
/**
69+
* @param string|null $tableName
70+
*
71+
* @return list<string>
72+
*/
73+
private function buildQueryConditions($tableName): array
74+
{
75+
$conditions = [];
76+
77+
if ($tableName !== null) {
78+
if (strpos($tableName, '.') !== false) {
79+
[$schemaName, $tableName] = explode('.', $tableName);
80+
$conditions[] = 'n.nspname = ' . $this->_platform->quoteStringLiteral($schemaName);
81+
} else {
82+
$conditions[] = 'n.nspname = ANY(current_schemas(false))';
83+
}
84+
85+
$identifier = new Identifier($tableName);
86+
$conditions[] = 'c.relname = ' . $this->_platform->quoteStringLiteral($identifier->getName());
87+
}
88+
89+
$conditions[] = "n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')";
90+
91+
return $conditions;
92+
}
93+
}

0 commit comments

Comments
 (0)