Skip to content

Commit

Permalink
[11.x] SQLite Error: "General error: 1 no such table" after adding a …
Browse files Browse the repository at this point in the history
…foreign key when using a table prefix. (#52578)

* Added removal of the table prefix when defining a foreign key.

* Code style fixed.
  • Loading branch information
incrize authored Sep 3, 2024
1 parent 4153267 commit 85b7ca8
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/Illuminate/Database/Schema/BlueprintState.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public function __construct(Blueprint $blueprint, Connection $connection, Gramma

$this->foreignKeys = collect($schema->getForeignKeys($table))->map(fn ($foreignKey) => new ForeignKeyDefinition([
'columns' => $foreignKey['columns'],
'on' => $foreignKey['foreign_table'],
'on' => $this->withoutTablePrefix($foreignKey['foreign_table']),
'references' => $foreignKey['foreign_columns'],
'onUpdate' => $foreignKey['on_update'],
'onDelete' => $foreignKey['on_delete'],
Expand Down Expand Up @@ -251,4 +251,19 @@ public function update(Fluent $command)
break;
}
}

/**
* Remove the table prefix from a table name, if it exists.
*
* @param string $table
* @return string
*/
protected function withoutTablePrefix(string $table)
{
$prefix = $this->connection->getTablePrefix();

return str_starts_with($table, $prefix)
? substr($table, strlen($prefix))
: $table;
}
}
161 changes: 161 additions & 0 deletions tests/Database/DatabaseSQLiteSchemaGrammarTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Query\Processors\SQLiteProcessor;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\BlueprintState;
use Illuminate\Database\Schema\ColumnDefinition;
use Illuminate\Database\Schema\ForeignIdColumnDefinition;
use Illuminate\Database\Schema\ForeignKeyDefinition;
use Illuminate\Database\Schema\Grammars\SQLiteGrammar;
use Illuminate\Database\Schema\IndexDefinition;
use Illuminate\Database\Schema\SQLiteBuilder;
use Mockery as m;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -998,6 +1002,163 @@ public function testDroppingColumnsWorks()
$this->assertEquals(['alter table "users" drop column "name"'], $blueprint->toSql($this->getConnection(), $this->getGrammar()));
}

public function testBlueprintInitialState()
{
$db = new Manager;

$db->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => 'prefix_',
]);

$connection = $db->getConnection();
$grammar = new SQLiteGrammar();
$grammar->setConnection($connection);
$grammar->setTablePrefix($connection->getTablePrefix());

$schema = $connection->getSchemaBuilder();

$schema->create('users', function (Blueprint $table) {
$table->string('name');
$table->string('email');
});

$schema->create('posts', function (Blueprint $table) {
$table->increments('id');
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
$table->integer('parent_id')->nullable()->index('parent_id');
$table->string('status')->default('A');
$table->boolean('is_active')->virtualAs('"status" = \'A\'');
$table->boolean('has_parent')->storedAs('"parent_id" IS NOT NULL');
$table->string('title')->collation('RTRIM');
});

$blueprint = new Blueprint('posts', null, $connection->getTablePrefix());
$state = new BlueprintState($blueprint, $connection, $grammar);

$this->assertCount(7, $state->getColumns());
$this->assertCount(1, $state->getIndexes());
$this->assertCount(1, $state->getForeignKeys());
$this->assertSame(['id'], $state->getPrimaryKey()->get('columns'));
$this->assertSame(
[
[
'name' => 'id',
'type' => 'integer',
'full_type_definition' => 'integer',
'nullable' => false,
'default' => null,
'autoIncrement' => true,
'collation' => null,
'comment' => null,
'virtualAs' => null,
'storedAs' => null,
],
[
'name' => 'user_id',
'type' => 'integer',
'full_type_definition' => 'integer',
'nullable' => false,
'default' => null,
'autoIncrement' => false,
'collation' => null,
'comment' => null,
'virtualAs' => null,
'storedAs' => null,
],
[
'name' => 'parent_id',
'type' => 'integer',
'full_type_definition' => 'integer',
'nullable' => true,
'default' => null,
'autoIncrement' => false,
'collation' => null,
'comment' => null,
'virtualAs' => null,
'storedAs' => null,
],
[
'name' => 'status',
'type' => 'varchar',
'full_type_definition' => 'varchar',
'nullable' => false,
'default' => "'A'",
'autoIncrement' => false,
'collation' => null,
'comment' => null,
'virtualAs' => null,
'storedAs' => null,
],
[
'name' => 'is_active',
'type' => 'tinyint',
'full_type_definition' => 'tinyint(1)',
'nullable' => true,
'default' => null,
'autoIncrement' => false,
'collation' => null,
'comment' => null,
'virtualAs' => '"status" = \'A\'',
'storedAs' => null,
],
[
'name' => 'has_parent',
'type' => 'tinyint',
'full_type_definition' => 'tinyint(1)',
'nullable' => true,
'default' => null,
'autoIncrement' => false,
'collation' => null,
'comment' => null,
'virtualAs' => null,
'storedAs' => '"parent_id" IS NOT NULL',
],
[
'name' => 'title',
'type' => 'varchar',
'full_type_definition' => 'varchar',
'nullable' => false,
'default' => null,
'autoIncrement' => false,
'collation' => 'rtrim',
'comment' => null,
'virtualAs' => null,
'storedAs' => null,
],
],
array_map(
fn (ColumnDefinition $definition) => array_replace($definition->toArray(), [
'default' => $definition->value('default') ? $definition->value('default')->getValue($grammar) : $definition->value('default'),
]),
$state->getColumns()
)
);
$this->assertSame(
[
[
'name' => 'index',
'index' => 'parent_id',
'columns' => ['parent_id'],
],
],
array_map(fn (IndexDefinition $definition) => $definition->toArray(), $state->getIndexes())
);
$this->assertSame(
[
[
'columns' => ['user_id'],
'on' => 'users',
'references' => ['id'],
'onUpdate' => 'no action',
'onDelete' => 'cascade',
],
],
array_map(fn (ForeignKeyDefinition $definition) => $definition->toArray(), $state->getForeignKeys())
);
}

protected function getConnection()
{
$connection = m::mock(Connection::class);
Expand Down

0 comments on commit 85b7ca8

Please sign in to comment.