diff --git a/CHANGELOG.md b/CHANGELOG.md index a5d9e84..1ebbf19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,9 @@ All notable changes to this project will be documented in this file. This projec ## [unreleased] Unreleased -## [1.1.2] 2022-11-22 +* Feature - Added `Table::has_foreign_key()` method. + +## [1.1.2] 2022-11-2 * Tweak - Set the composer's `config.platform.php` to `7.0`. diff --git a/docs/schemas-field.md b/docs/schemas-field.md index 95b9f6c..a866ade 100644 --- a/docs/schemas-field.md +++ b/docs/schemas-field.md @@ -147,17 +147,35 @@ public function after_update() { $table_name = static::table_name( true ); $updated = false; - if ( $this->exists() && $this->has_index( 'boom' ) ) { - $udpated = $wpdb->query( "ALTER TABLE `{$table_name}` ADD UNIQUE( `name` )" ); - } + // Add a UNIQUE constraint on the name column. + if ( $this->exists() && ! $this->has_index( 'boom' ) ) { + $updated = $wpdb->query( "ALTER TABLE `{$table_name}` ADD UNIQUE( `name` )" ); + + if ( $updated ) { + $message = "Added UNIQUE constraint to the {$table_name} table on name."; + } else { + $message = "Failed to add a unique constraint on the {$table_name} table."; + } - if ( $updated ) { - $message = "Added UNIQUE constraint to the {$table_name} table on name."; - } else { - $message = "Failed to add a unique constraint on the {$table_name} table."; + $results[ $table_name . '.name' ] = $message; } - $results[ $table_name . '.name' ] = $message; + // Add a FOREIGN KEY constraint on the reseller_id column. + if ( $this->exists() && ! $this->has_foreign_key( 'reseller_id' ) ) { + $referenced_table = $wpdb->prefix . 'resellers'; + $updated = $wpdb->query( "ALTER TABLE `{$table_name}` + ADD FOREIGN KEY ( `reseller_id` ) + REFERENCES `$referenced_table` ( `id` )" + ); + + if ( $updated ) { + $message = "Added FOREIGN KEY constraint to the {$table_name} table on reseller_id."; + } else { + $message = "Failed to add a FOREIGN KEY constraint on the {$table_name} table."; + } + + $results[ $table_name . '.reseller_id' ] = $message; + } return $results; } diff --git a/docs/schemas-table.md b/docs/schemas-table.md index 9187211..52de692 100644 --- a/docs/schemas-table.md +++ b/docs/schemas-table.md @@ -162,17 +162,35 @@ public function after_update() { $table_name = static::table_name( true ); $updated = false; - if ( $this->exists() && $this->has_index( 'boom' ) ) { - $udpated = $wpdb->query( "ALTER TABLE `{$table_name}` ADD UNIQUE( `name` )" ); - } + // Add a UNIQUE constraint on the name column. + if ( $this->exists() && ! $this->has_index( 'boom' ) ) { + $updated = $wpdb->query( "ALTER TABLE `{$table_name}` ADD UNIQUE( `name` )" ); + + if ( $updated ) { + $message = "Added UNIQUE constraint to the {$table_name} table on name."; + } else { + $message = "Failed to add a unique constraint on the {$table_name} table."; + } - if ( $updated ) { - $message = "Added UNIQUE constraint to the {$table_name} table on name."; - } else { - $message = "Failed to add a unique constraint on the {$table_name} table."; + $results[ $table_name . '.name' ] = $message; } - $results[ $table_name . '.name' ] = $message; + // Add a FOREIGN KEY constraint on the reseller_id column. + if ( $this->exists() && ! $this->has_foreign_key( 'reseller_id' ) ) { + $referenced_table = $wpdb->prefix . 'resellers'; + $updated = $wpdb->query( "ALTER TABLE `{$table_name}` + ADD FOREIGN KEY ( `reseller_id` ) + REFERENCES `$referenced_table` ( `id` )" + ); + + if ( $updated ) { + $message = "Added FOREIGN KEY constraint to the {$table_name} table on reseller_id."; + } else { + $message = "Failed to add a FOREIGN KEY constraint on the {$table_name} table."; + } + + $results[ $table_name . '.reseller_id' ] = $message; + } return $results; } diff --git a/src/Schema/Tables/Contracts/Table.php b/src/Schema/Tables/Contracts/Table.php index 5b3c4c9..1ce8fb2 100644 --- a/src/Schema/Tables/Contracts/Table.php +++ b/src/Schema/Tables/Contracts/Table.php @@ -531,4 +531,26 @@ public function update() { return $results; } + + /** + * Checks if a foreign key exists on a table. + * + * @since TBD + * + * @param string $foreign_key The foreign key to check for. + * @param string|null $table_name The table name to check. Defaults to the current table. + * + * @return bool Whether the foreign key exists on the table. + */ + public function has_foreign_key( string $foreign_key, string $table_name = null ): bool { + $table_name = $table_name ?: static::table_name(); + + $count = $this->db::table( $this->db::raw( 'information_schema.statistics' ) ) + ->whereRaw( 'WHERE TABLE_SCHEMA = DATABASE()' ) + ->where( 'TABLE_NAME', $table_name ) + ->where( 'INDEX_NAME', $foreign_key ) + ->count(); + + return $count >= 1; + } } diff --git a/tests/_support/Traits/Table_Fixtures.php b/tests/_support/Traits/Table_Fixtures.php index eb302a0..06faf18 100644 --- a/tests/_support/Traits/Table_Fixtures.php +++ b/tests/_support/Traits/Table_Fixtures.php @@ -163,4 +163,50 @@ protected function get_definition() { return $field; } + + public function get_foreign_key_table() { + $table = new class extends Table { + const SCHEMA_VERSION = '1.0.0'; + + protected static $base_table_name = 'foreignkey'; + protected static $group = 'bork'; + protected static $schema_slug = 'bork-with-foreignkey'; + protected static $uid_column = 'id'; + + protected function get_definition() { + global $wpdb; + $table_name = self::table_name( true ); + $charset_collate = $wpdb->get_charset_collate(); + + return " + CREATE TABLE `{$table_name}` ( + `id` int(11) UNSIGNED NOT NULL, + `name` varchar(25) NOT NULL, + `simple_id` int(11) UNSIGNED NOT NULL + ) {$charset_collate}; + "; + } + + protected function after_update( array $results ) { + if ( $this->has_foreign_key( 'simple_id' ) ) { + return $results; + } + + global $wpdb; + $table_name = $this->table_name(); + $simple_table = $wpdb->prefix . 'simple'; + $updated = $wpdb->query( "ALTER TABLE $table_name ADD FOREIGN KEY (simple_id) REFERENCES $simple_table(id)" ); + + $result = $updated ? + 'FOREIGN KEY added to ' . $table_name . ' on column simple_id to table ' . $simple_table . ' on column id' : + 'Failed to add FOREIGN KEY NOT to ' . $table_name . ' on column simple_id to table ' . $simple_table . ' on column id'; + + $results[] = $result; + + return $results; + } + }; + + return $table; + } } diff --git a/tests/wpunit/Tables/TableTest.php b/tests/wpunit/Tables/TableTest.php index 96dd227..d15d736 100644 --- a/tests/wpunit/Tables/TableTest.php +++ b/tests/wpunit/Tables/TableTest.php @@ -9,13 +9,21 @@ class TableTest extends SchemaTestCase { use Table_Fixtures; + /** + * @before + */ + public function drop_tables() { + $this->get_simple_table()->drop(); + $this->get_foreign_key_table()->drop(); + } + /** * Should have index. * * @test */ public function should_have_index() { - $table = $this->get_simple_table(); + $table = $this->get_simple_table(); Register::table( $table ); @@ -28,11 +36,45 @@ public function should_have_index() { * @test */ public function should_have_fake_index() { - $table = $this->get_simple_table(); + $table = $this->get_simple_table(); Register::table( $table ); $this->assertFalse( $table->has_index( 'bork' ) ); } + + /** + * It should not have foreign key + * + * @test + */ + public function should_not_have_foreign_key() { + $simple_table = $this->get_simple_table(); + $foreign_key_table = $this->get_foreign_key_table(); + + Register::table( $simple_table ); + Register::table( $foreign_key_table ); + + $this->assertFalse( $simple_table->has_foreign_key( 'simple_id' ) ); + $this->assertFalse( $foreign_key_table->has_foreign_key( 'not_really' ) ); + } + + /** + * It should have foreign key + * + * @test + */ + public function should_have_foreign_key() { + $simple_table = $this->get_simple_table(); + $foreign_key_table = $this->get_foreign_key_table(); + + Register::table( $simple_table ); + Register::table( $foreign_key_table ); + + $this->assertFalse( $simple_table->has_foreign_key( 'simple_id' ) ); + $this->assertFalse( $foreign_key_table->has_foreign_key( 'not_really' ) ); + + $this->assertTrue( $foreign_key_table->has_foreign_key( 'simple_id' ) ); + } }