Skip to content

Commit c09b48d

Browse files
authored
Merge branch 'master' into feature/non-parent-interleave
2 parents bac4b62 + 07f066c commit c09b48d

File tree

9 files changed

+262
-90
lines changed

9 files changed

+262
-90
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ RUN pecl_mt_install() { \
3434
&& apk add --no-cache bash gmp libxml2 libstdc++ \
3535
&& apk add --no-cache --virtual=.build-deps autoconf curl-dev gcc gmp-dev g++ libxml2-dev linux-headers make pcre-dev tzdata \
3636
&& docker-php-ext-install -j$(nproc) bcmath gmp \
37-
&& pecl_mt_install protobuf \
37+
&& pecl_mt_install protobuf-4.30.2 \
3838
&& pecl_mt_install grpc \
3939
&& pecl_mt_install pcov \
4040
&& docker-php-ext-enable grpc opcache protobuf \

compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ services:
88
depends_on:
99
- emulator
1010
emulator:
11-
image: "gcr.io/cloud-spanner-emulator/emulator:1.5.28"
11+
image: "gcr.io/cloud-spanner-emulator/emulator:1.5.30"

phpstan.neon

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,14 @@ parameters:
66
- message: "#^Call to an undefined method Illuminate\\\\Database\\\\ConnectionInterface\\:\\:recordsHaveBeenModified\\(\\)\\.$#"
77
count: 1
88
path: src/Query/Processor.php
9+
-
10+
message: '#^Closure invoked with 2 parameters, 3 required\.$#'
11+
identifier: arguments.count
12+
count: 1
13+
path: src/Schema/Builder.php
14+
15+
-
16+
message: '#^Parameter \#2 of closure expects Closure, Closure\|null given\.$#'
17+
identifier: argument.type
18+
count: 1
19+
path: src/Schema/Builder.php

src/Query/Grammar.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public function compileInsertGetId(Builder $query, $values, $sequence)
6565
*/
6666
protected function compileLock(Builder $query, $value)
6767
{
68-
return '';
68+
return $value === true ? 'for update' : '';
6969
}
7070

7171
/**

src/Query/Processor.php

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -100,58 +100,86 @@ protected function processColumn(mixed $value): mixed
100100
}
101101

102102
/**
103-
* Process the results of a columns query.
104-
*
105-
* {@inheritDoc}
106-
* @param array<array-key, array<array-key, mixed>> $results
107-
* @return array<array-key, array{
108-
* name: string,
109-
* type_name: string,
110-
* type: string,
111-
* collation: null,
112-
* nullable: bool,
113-
* default: scalar,
114-
* auto_increment: false,
115-
* comment: null
116-
* }>
103+
* @inheritDoc
104+
*/
105+
public function processTables($results)
106+
{
107+
return array_map(function ($result) {
108+
$result = (object) $result;
109+
110+
return [
111+
'name' => $result->name,
112+
'schema' => $result->schema !== '' ? $result->schema : null,
113+
'schema_qualified_name' => $result->schema !== ''
114+
? $result->schema . '.' . $result->name
115+
: $result->name,
116+
'parent' => $result->parent,
117+
'size' => null,
118+
'comment' => null,
119+
'collation' => null,
120+
'engine' => null,
121+
];
122+
}, $results);
123+
}
124+
125+
/**
126+
* @inheritDoc
117127
*/
118128
public function processColumns($results)
119129
{
120130
return array_map(static function (array $result) {
131+
$result = (object) $result;
132+
121133
return [
122-
'name' => $result['COLUMN_NAME'],
123-
'type_name' => preg_replace("/\([^)]+\)/", "", $result['SPANNER_TYPE']),
124-
'type' => $result['SPANNER_TYPE'],
134+
'name' => $result->name,
135+
'type_name' => (string) preg_replace("/\([^)]+\)/", "", $result->type),
136+
'type' => $result->type,
125137
'collation' => null,
126-
'nullable' => $result['IS_NULLABLE'] !== 'NO',
127-
'default' => $result['COLUMN_DEFAULT'],
138+
'nullable' => $result->nullable === 'YES',
139+
'default' => $result->default,
140+
// TODO check IS_IDENTITY and set auto_increment accordingly
128141
'auto_increment' => false,
129142
'comment' => null,
143+
'generation' => null,
130144
];
131145
}, $results);
132146
}
133147

134148
/**
135-
* {@inheritDoc}
136-
* @param array{ index_name: string }&array<string, mixed> $results
137-
* @return array<array-key, string>
149+
* @inheritDoc
138150
*/
139151
public function processIndexes($results)
140152
{
141153
return array_map(function ($result) {
142-
return ((object) $result)->index_name;
154+
$result = (object) $result;
155+
156+
return [
157+
'name' => $name = $result->name,
158+
'columns' => $result->columns ? explode(',', $result->columns) : [],
159+
'type' => strtolower($result->type),
160+
'unique' => (bool) $result->unique,
161+
'primary' => $name === 'PRIMARY_KEY',
162+
];
143163
}, $results);
144164
}
145165

146166
/**
147-
* {@inheritDoc}
148-
* @param array{key_name: string}&array<string, mixed> $results
149-
* @return array<array-key, string>
167+
* @inheritDoc
150168
*/
151169
public function processForeignKeys($results)
152170
{
153171
return array_map(function ($result) {
154-
return ((object) $result)->key_name;
172+
$result = (object) $result;
173+
174+
return [
175+
'name' => $result->name,
176+
'columns' => explode(',', $result->columns),
177+
'foreign_schema' => $result->foreign_schema,
178+
'foreign_table' => $result->foreign_table,
179+
'foreign_columns' => explode(',', $result->foreign_columns),
180+
'on_update' => strtolower($result->on_update),
181+
'on_delete' => strtolower($result->on_delete),
182+
];
155183
}, $results);
156184
}
157185
}

src/Schema/Builder.php

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,6 @@ class Builder extends BaseBuilder
4040
*/
4141
public static $defaultMorphKeyType = 'uuid';
4242

43-
/**
44-
* @param null $schema
45-
* @inheritDoc Adds a parent key, for tracking interleaving
46-
*
47-
* @return list<array{ name: string, type: string, parent: string }>
48-
*/
49-
public function getTables($schema = null)
50-
{
51-
/** @var list<array{ name: string, type: string, parent: string }> */
52-
return $this->connection->select(
53-
$this->grammar->compileTables(null),
54-
);
55-
}
56-
5743
/**
5844
* @param string $table
5945
* @param string $name
@@ -73,7 +59,7 @@ public function dropIndex($table, $name)
7359
*/
7460
public function dropIndexIfExist($table, $name)
7561
{
76-
if (in_array($name, $this->getIndexes($table), true)) {
62+
if (in_array($name, $this->getIndexListing($table), true)) {
7763
$blueprint = $this->createBlueprint($table);
7864
$blueprint->dropIndex($name);
7965
$this->build($blueprint);
@@ -85,7 +71,6 @@ public function dropIndexIfExist($table, $name)
8571
*/
8672
protected function createBlueprint($table, ?Closure $callback = null)
8773
{
88-
/** @phpstan-ignore isset.property */
8974
return isset($this->resolver)
9075
? ($this->resolver)($table, $callback)
9176
: new Blueprint($this->connection, $table, $callback);
@@ -97,6 +82,17 @@ protected function createBlueprint($table, ?Closure $callback = null)
9782
public function dropAllTables()
9883
{
9984
$connection = $this->connection;
85+
/** @var list<array{
86+
* name: string,
87+
* schema: string|null,
88+
* schema_qualified_name: string,
89+
* size: int|null,
90+
* comment: string|null,
91+
* collation: string|null,
92+
* engine: string|null,
93+
* parent: string|null
94+
* }> $tables
95+
*/
10096
$tables = $this->getTables();
10197

10298
if (count($tables) === 0) {
@@ -134,7 +130,7 @@ public function dropAllTables()
134130
$foreigns = $this->getForeignKeys($tableName);
135131
$blueprint = $this->createBlueprint($tableName);
136132
foreach ($foreigns as $foreign) {
137-
$blueprint->dropForeign($foreign);
133+
$blueprint->dropForeign($foreign['name']);
138134
}
139135
array_push($queries, ...$blueprint->toSql());
140136
}
@@ -145,7 +141,7 @@ public function dropAllTables()
145141
$queries = [];
146142
foreach ($sortedTables as $tableData) {
147143
$tableName = $tableData['name'];
148-
$indexes = $this->getIndexes($tableName);
144+
$indexes = $this->getIndexListing($tableName);
149145
$blueprint = $this->createBlueprint($tableName);
150146
foreach ($indexes as $index) {
151147
if ($index === 'PRIMARY_KEY') {

src/Schema/Grammar.php

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,52 +47,92 @@ class Grammar extends BaseGrammar
4747
*/
4848
public function compileTables($schema)
4949
{
50-
return 'select `table_name` as name, `table_type` as type, `parent_table_name` as parent from information_schema.tables where table_schema = \'\' and table_type = \'BASE TABLE\'';
50+
return implode(' ', [
51+
'select',
52+
implode(', ', [
53+
'table_name as name',
54+
'table_schema as `schema`',
55+
'parent_table_name as parent',
56+
]),
57+
'from information_schema.tables',
58+
'where table_type = \'BASE TABLE\'',
59+
'and table_schema = \'\'',
60+
]);
5161
}
5262

5363
/**
54-
* Compile the query to determine the list of indexes.
64+
* Compile the query to determine the columns.
5565
*
56-
* @param string|null $schema
57-
* @param $table
66+
* @param string $table
5867
* @return string
5968
*/
60-
public function compileIndexes($schema, $table)
69+
public function compileColumns($schema, $table)
6170
{
62-
return sprintf(
63-
'select index_name as `index_name` from information_schema.indexes where table_schema = \'\' and table_name = %s',
64-
$this->quoteString($table),
65-
);
71+
return implode(' ', [
72+
'select',
73+
implode(', ', [
74+
'column_name as `name`',
75+
'spanner_type as `type`',
76+
'is_nullable as `nullable`',
77+
'column_default as `default`',
78+
]),
79+
'from information_schema.columns',
80+
'where table_name = ' . $this->quoteString($table),
81+
]);
6682
}
6783

6884
/**
69-
* Compile the query to determine the list of foreign keys.
85+
* Compile the query to determine the list of indexes.
7086
*
7187
* @param string|null $schema
7288
* @param $table
7389
* @return string
7490
*/
75-
public function compileForeignKeys($schema, $table)
91+
public function compileIndexes($schema, $table)
7692
{
77-
return sprintf(
78-
'select constraint_name as `key_name` from information_schema.table_constraints where constraint_type = "FOREIGN KEY" and table_schema = \'\' and table_name = %s',
79-
$this->quoteString($table),
80-
);
93+
return implode(' ', [
94+
'select',
95+
implode(', ', [
96+
'i.index_name as `name`',
97+
'string_agg(c.column_name, \',\') as `columns`',
98+
'i.index_type as `type`',
99+
'i.is_unique as `unique`',
100+
]),
101+
'from information_schema.indexes as i',
102+
'join information_schema.index_columns as c on i.table_schema = c.table_schema and i.table_name = c.table_name and i.index_name = c.index_name',
103+
'where i.table_schema = ' . $this->quoteString(''),
104+
'and i.table_name = ' . $this->quoteString($table),
105+
'group by i.index_name, i.index_type, i.is_unique',
106+
]);
81107
}
82108

83109
/**
84-
* Compile the query to determine the columns.
110+
* Compile the query to determine the list of foreign keys.
85111
*
86112
* @param string|null $schema
87113
* @param $table
88114
* @return string
89115
*/
90-
public function compileColumns($schema, $table)
116+
public function compileForeignKeys($schema, $table)
91117
{
92-
return sprintf(
93-
'select * from information_schema.columns where table_schema = \'\' and table_name = %s',
94-
$this->quoteString($table),
95-
);
118+
return implode(' ', [
119+
'select',
120+
implode(', ', [
121+
'kc.constraint_name as `name`',
122+
'string_agg(kc.column_name) as `columns`',
123+
'cc.table_schema as `foreign_schema`',
124+
'cc.table_name as `foreign_table`',
125+
'string_agg(cc.column_name) as `foreign_columns`',
126+
'rc.update_rule as `on_update`',
127+
'rc.delete_rule as `on_delete`',
128+
]),
129+
'from information_schema.key_column_usage kc',
130+
'join information_schema.referential_constraints rc on kc.constraint_name = rc.constraint_name',
131+
'join information_schema.constraint_column_usage cc on kc.constraint_name = cc.constraint_name',
132+
'where kc.table_schema = ""',
133+
'and kc.table_name = ' . $this->quoteString($table),
134+
'group by kc.constraint_name, cc.table_schema, cc.table_name, rc.update_rule, rc.delete_rule'
135+
]);
96136
}
97137

98138
/**

tests/Query/BuilderTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -994,15 +994,15 @@ public function test_lock(): void
994994
$conn = $this->getDefaultConnection();
995995
$qb = $conn->table(self::TABLE_NAME_USER);
996996
$sql = $qb->lock()->toRawSql();
997-
$this->assertSame('select * from `User`', $sql);
997+
$this->assertSame('select * from `User` for update', $sql);
998998
}
999999

10001000
public function test_lockForUpdate(): void
10011001
{
10021002
$conn = $this->getDefaultConnection();
10031003
$qb = $conn->table(self::TABLE_NAME_USER);
10041004
$sql = $qb->lockForUpdate()->toRawSql();
1005-
$this->assertSame('select * from `User`', $sql);
1005+
$this->assertSame('select * from `User` for update', $sql);
10061006
}
10071007

10081008
public function test_sharedLock(): void

0 commit comments

Comments
 (0)