Skip to content

Commit 79fb5c0

Browse files
committed
feat(Table) add has_foreign_key method
1 parent 35d4054 commit 79fb5c0

File tree

6 files changed

+167
-19
lines changed

6 files changed

+167
-19
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ All notable changes to this project will be documented in this file. This projec
44

55
## [unreleased] Unreleased
66

7-
## [1.1.2] 2022-11-22
7+
* Feature - Added `Table::has_foreign_key()` method.
8+
9+
## [1.1.2] 2022-11-2
810

911
* Tweak - Set the composer's `config.platform.php` to `7.0`.
1012

docs/schemas-field.md

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,35 @@ public function after_update() {
147147
$table_name = static::table_name( true );
148148
$updated = false;
149149

150-
if ( $this->exists() && $this->has_index( 'boom' ) ) {
151-
$udpated = $wpdb->query( "ALTER TABLE `{$table_name}` ADD UNIQUE( `name` )" );
152-
}
150+
// Add a UNIQUE constraint on the name column.
151+
if ( $this->exists() && ! $this->has_index( 'boom' ) ) {
152+
$updated = $wpdb->query( "ALTER TABLE `{$table_name}` ADD UNIQUE( `name` )" );
153+
154+
if ( $updated ) {
155+
$message = "Added UNIQUE constraint to the {$table_name} table on name.";
156+
} else {
157+
$message = "Failed to add a unique constraint on the {$table_name} table.";
158+
}
153159

154-
if ( $updated ) {
155-
$message = "Added UNIQUE constraint to the {$table_name} table on name.";
156-
} else {
157-
$message = "Failed to add a unique constraint on the {$table_name} table.";
160+
$results[ $table_name . '.name' ] = $message;
158161
}
159162

160-
$results[ $table_name . '.name' ] = $message;
163+
// Add a FOREIGN KEY constraint on the reseller_id column.
164+
if ( $this->exists() && ! $this->has_foreign_key( 'reseller_id' ) ) {
165+
$referenced_table = $wpdb->prefix . 'resellers';
166+
$updated = $wpdb->query( "ALTER TABLE `{$table_name}`
167+
ADD FOREIGN KEY ( `reseller_id` )
168+
REFERENCES `$referenced_table` ( `id` )"
169+
);
170+
171+
if ( $updated ) {
172+
$message = "Added FOREIGN KEY constraint to the {$table_name} table on reseller_id.";
173+
} else {
174+
$message = "Failed to add a FOREIGN KEY constraint on the {$table_name} table.";
175+
}
176+
177+
$results[ $table_name . '.reseller_id' ] = $message;
178+
}
161179

162180
return $results;
163181
}

docs/schemas-table.md

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,17 +162,35 @@ public function after_update() {
162162
$table_name = static::table_name( true );
163163
$updated = false;
164164

165-
if ( $this->exists() && $this->has_index( 'boom' ) ) {
166-
$udpated = $wpdb->query( "ALTER TABLE `{$table_name}` ADD UNIQUE( `name` )" );
167-
}
165+
// Add a UNIQUE constraint on the name column.
166+
if ( $this->exists() && ! $this->has_index( 'boom' ) ) {
167+
$updated = $wpdb->query( "ALTER TABLE `{$table_name}` ADD UNIQUE( `name` )" );
168+
169+
if ( $updated ) {
170+
$message = "Added UNIQUE constraint to the {$table_name} table on name.";
171+
} else {
172+
$message = "Failed to add a unique constraint on the {$table_name} table.";
173+
}
168174

169-
if ( $updated ) {
170-
$message = "Added UNIQUE constraint to the {$table_name} table on name.";
171-
} else {
172-
$message = "Failed to add a unique constraint on the {$table_name} table.";
175+
$results[ $table_name . '.name' ] = $message;
173176
}
174177

175-
$results[ $table_name . '.name' ] = $message;
178+
// Add a FOREIGN KEY constraint on the reseller_id column.
179+
if ( $this->exists() && ! $this->has_foreign_key( 'reseller_id' ) ) {
180+
$referenced_table = $wpdb->prefix . 'resellers';
181+
$updated = $wpdb->query( "ALTER TABLE `{$table_name}`
182+
ADD FOREIGN KEY ( `reseller_id` )
183+
REFERENCES `$referenced_table` ( `id` )"
184+
);
185+
186+
if ( $updated ) {
187+
$message = "Added FOREIGN KEY constraint to the {$table_name} table on reseller_id.";
188+
} else {
189+
$message = "Failed to add a FOREIGN KEY constraint on the {$table_name} table.";
190+
}
191+
192+
$results[ $table_name . '.reseller_id' ] = $message;
193+
}
176194

177195
return $results;
178196
}

src/Schema/Tables/Contracts/Table.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,4 +531,26 @@ public function update() {
531531

532532
return $results;
533533
}
534+
535+
/**
536+
* Checks if a foreign key exists on a table.
537+
*
538+
* @since TBD
539+
*
540+
* @param string $foreign_key The foreign key to check for.
541+
* @param string|null $table_name The table name to check. Defaults to the current table.
542+
*
543+
* @return bool Whether the foreign key exists on the table.
544+
*/
545+
public function has_foreign_key( string $foreign_key, string $table_name = null ): bool {
546+
$table_name = $table_name ?: static::table_name();
547+
548+
$count = $this->db::table( $this->db::raw( 'information_schema.statistics' ) )
549+
->whereRaw( 'WHERE TABLE_SCHEMA = DATABASE()' )
550+
->where( 'TABLE_NAME', $table_name )
551+
->where( 'INDEX_NAME', $foreign_key )
552+
->count();
553+
554+
return $count >= 1;
555+
}
534556
}

tests/_support/Traits/Table_Fixtures.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,50 @@ protected function get_definition() {
163163

164164
return $field;
165165
}
166+
167+
public function get_foreign_key_table() {
168+
$table = new class extends Table {
169+
const SCHEMA_VERSION = '1.0.0';
170+
171+
protected static $base_table_name = 'foreignkey';
172+
protected static $group = 'bork';
173+
protected static $schema_slug = 'bork-with-foreignkey';
174+
protected static $uid_column = 'id';
175+
176+
protected function get_definition() {
177+
global $wpdb;
178+
$table_name = self::table_name( true );
179+
$charset_collate = $wpdb->get_charset_collate();
180+
181+
return "
182+
CREATE TABLE `{$table_name}` (
183+
`id` int(11) UNSIGNED NOT NULL,
184+
`name` varchar(25) NOT NULL,
185+
`simple_id` int(11) UNSIGNED NOT NULL
186+
) {$charset_collate};
187+
";
188+
}
189+
190+
protected function after_update( array $results ) {
191+
if ( $this->has_foreign_key( 'simple_id' ) ) {
192+
return $results;
193+
}
194+
195+
global $wpdb;
196+
$table_name = $this->table_name();
197+
$simple_table = $wpdb->prefix . 'simple';
198+
$updated = $wpdb->query( "ALTER TABLE $table_name ADD FOREIGN KEY (simple_id) REFERENCES $simple_table(id)" );
199+
200+
$result = $updated ?
201+
'FOREIGN KEY added to ' . $table_name . ' on column simple_id to table ' . $simple_table . ' on column id' :
202+
'Failed to add FOREIGN KEY NOT to ' . $table_name . ' on column simple_id to table ' . $simple_table . ' on column id';
203+
204+
$results[] = $result;
205+
206+
return $results;
207+
}
208+
};
209+
210+
return $table;
211+
}
166212
}

tests/wpunit/Tables/TableTest.php

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,21 @@
99
class TableTest extends SchemaTestCase {
1010
use Table_Fixtures;
1111

12+
/**
13+
* @before
14+
*/
15+
public function drop_tables() {
16+
$this->get_simple_table()->drop();
17+
$this->get_foreign_key_table()->drop();
18+
}
19+
1220
/**
1321
* Should have index.
1422
*
1523
* @test
1624
*/
1725
public function should_have_index() {
18-
$table = $this->get_simple_table();
26+
$table = $this->get_simple_table();
1927

2028
Register::table( $table );
2129

@@ -28,11 +36,45 @@ public function should_have_index() {
2836
* @test
2937
*/
3038
public function should_have_fake_index() {
31-
$table = $this->get_simple_table();
39+
$table = $this->get_simple_table();
3240

3341
Register::table( $table );
3442

3543
$this->assertFalse( $table->has_index( 'bork' ) );
3644
}
45+
46+
/**
47+
* It should not have foreign key
48+
*
49+
* @test
50+
*/
51+
public function should_not_have_foreign_key() {
52+
$simple_table = $this->get_simple_table();
53+
$foreign_key_table = $this->get_foreign_key_table();
54+
55+
Register::table( $simple_table );
56+
Register::table( $foreign_key_table );
57+
58+
$this->assertFalse( $simple_table->has_foreign_key( 'simple_id' ) );
59+
$this->assertFalse( $foreign_key_table->has_foreign_key( 'not_really' ) );
60+
}
61+
62+
/**
63+
* It should have foreign key
64+
*
65+
* @test
66+
*/
67+
public function should_have_foreign_key() {
68+
$simple_table = $this->get_simple_table();
69+
$foreign_key_table = $this->get_foreign_key_table();
70+
71+
Register::table( $simple_table );
72+
Register::table( $foreign_key_table );
73+
74+
$this->assertFalse( $simple_table->has_foreign_key( 'simple_id' ) );
75+
$this->assertFalse( $foreign_key_table->has_foreign_key( 'not_really' ) );
76+
77+
$this->assertTrue( $foreign_key_table->has_foreign_key( 'simple_id' ) );
78+
}
3779
}
3880

0 commit comments

Comments
 (0)