From 9e7ba356c31969b35c1442e7d012bab31e012831 Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Mon, 1 Apr 2024 03:59:49 +0330 Subject: [PATCH] [11.x] Use Default Schema Name on SQL Server (#50855) * get default schema name on sqlsrv * force re-run tests * add test * wip * wip * wip * wip * revert adding test * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * formatting --------- Co-authored-by: Taylor Otwell --- .../Schema/Grammars/SqlServerGrammar.php | 10 +++++ .../Database/Schema/SqlServerBuilder.php | 14 ++++++- .../Database/SchemaBuilderSchemaNameTest.php | 37 +++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Schema/Grammars/SqlServerGrammar.php b/src/Illuminate/Database/Schema/Grammars/SqlServerGrammar.php index a661094b2e84..d15a32f3cbe7 100755 --- a/src/Illuminate/Database/Schema/Grammars/SqlServerGrammar.php +++ b/src/Illuminate/Database/Schema/Grammars/SqlServerGrammar.php @@ -37,6 +37,16 @@ class SqlServerGrammar extends Grammar */ protected $fluentCommands = ['Default']; + /** + * Compile a query to determine the name of the default schema. + * + * @return string + */ + public function compileDefaultSchema() + { + return 'select schema_name()'; + } + /** * Compile a create database command. * diff --git a/src/Illuminate/Database/Schema/SqlServerBuilder.php b/src/Illuminate/Database/Schema/SqlServerBuilder.php index 876e8b39be46..2833b5098aba 100644 --- a/src/Illuminate/Database/Schema/SqlServerBuilder.php +++ b/src/Illuminate/Database/Schema/SqlServerBuilder.php @@ -42,6 +42,7 @@ public function hasTable($table) { [$schema, $table] = $this->parseSchemaAndTable($table); + $schema ??= $this->getDefaultSchema(); $table = $this->connection->getTablePrefix().$table; foreach ($this->getTables() as $value) { @@ -64,6 +65,7 @@ public function hasView($view) { [$schema, $view] = $this->parseSchemaAndTable($view); + $schema ??= $this->getDefaultSchema(); $view = $this->connection->getTablePrefix().$view; foreach ($this->getViews() as $value) { @@ -151,6 +153,16 @@ public function getForeignKeys($table) ); } + /** + * Get the default schema for the connection. + * + * @return string + */ + protected function getDefaultSchema() + { + return $this->connection->scalar($this->grammar->compileDefaultSchema()); + } + /** * Parse the database object reference and extract the schema and table. * @@ -159,7 +171,7 @@ public function getForeignKeys($table) */ protected function parseSchemaAndTable($reference) { - $parts = array_pad(explode('.', $reference, 2), -2, 'dbo'); + $parts = array_pad(explode('.', $reference, 2), -2, null); if (str_contains($parts[1], '.')) { $database = $parts[0]; diff --git a/tests/Integration/Database/SchemaBuilderSchemaNameTest.php b/tests/Integration/Database/SchemaBuilderSchemaNameTest.php index 2d6d9512ed87..f548422317db 100644 --- a/tests/Integration/Database/SchemaBuilderSchemaNameTest.php +++ b/tests/Integration/Database/SchemaBuilderSchemaNameTest.php @@ -425,6 +425,43 @@ public function testAutoIncrementStartingValue($connection) }); } + #[DataProvider('connectionProvider')] + public function testHasTable($connection) + { + if ($this->driver !== 'sqlsrv') { + $this->markTestSkipped('Test requires a SQL Server connection.'); + } + + $db = DB::connection($connection); + $schema = $db->getSchemaBuilder(); + + try { + $db->statement("create login my_user with password = 'Passw0rd'"); + $db->statement('create user my_user for login my_user'); + } catch(\Illuminate\Database\QueryException $e) { + // + } + + $db->statement('grant create table to my_user'); + $db->statement('grant alter on SCHEMA::my_schema to my_user'); + $db->statement("alter user my_user with default_schema = my_schema execute as user='my_user'"); + + config([ + 'database.connections.'.$connection.'.username' => 'my_user', + 'database.connections.'.$connection.'.password' => 'Passw0rd', + ]); + + $this->assertEquals('my_schema', $db->scalar('select schema_name()')); + + $schema->create('table', function (Blueprint $table) { + $table->id(); + }); + + $this->assertTrue($schema->hasTable('table')); + $this->assertTrue($schema->hasTable('my_schema.table')); + $this->assertFalse($schema->hasTable('dbo.table')); + } + public static function connectionProvider(): array { return [