From b74c2cf64f6187db62e3207458d6064d079520ca Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 1 Apr 2024 13:34:33 +0900 Subject: [PATCH] feat: add TableName class --- system/Database/TableName.php | 174 ++++++++++++++++++++++++ tests/system/Database/TableNameTest.php | 151 ++++++++++++++++++++ 2 files changed, 325 insertions(+) create mode 100644 system/Database/TableName.php create mode 100644 tests/system/Database/TableNameTest.php diff --git a/system/Database/TableName.php b/system/Database/TableName.php new file mode 100644 index 000000000000..d8d0316929dc --- /dev/null +++ b/system/Database/TableName.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Database; + +/** + * Represents a table name in SQL. + * + * @see \CodeIgniter\Database\TableNameTest + */ +class TableName +{ + /** + * @param string $dbPrefix DB prefix + * @param string $table Table name (w/o DB prefix) + * @param string $escapedTableName Escaped table name (w/z DB prefix) + * @param string $escapedAliasName Escaped alias name + * @param string $schema Schema name + * @param string $database Database name + * @param string $alias Alias name + */ + protected function __construct( + private string $dbPrefix, + private string $table, + private string $escapedTableName, + private string $escapedAliasName, + private string $schema = '', + private string $database = '', + private string $alias = '' + ) { + } + + /** + * Creates a new instance. + * + * @param string $table Table name (w/o DB prefix) + * @param string $alias Alias name + */ + public static function create(BaseConnection $db, string $table, string $alias = ''): self + { + $escapedTableName = $db->escapeIdentifier($db->DBPrefix . $table); + $escapedAliasName = $db->escapeIdentifier($alias); + + return new self( + $db->DBPrefix, + $table, + $escapedTableName, + $escapedAliasName, + '', + '', + $alias + ); + } + + /** + * Creates a new instance from an actual table name. + * + * @param string $table Actual table name with DB prefix + * @param string $alias Alias name + */ + public static function fromActualName(BaseConnection $db, string $table, string $alias = ''): self + { + $escapedTableName = $db->escapeIdentifier($table); + $escapedAliasName = $db->escapeIdentifier($alias); + + return new self( + '', + $table, + $escapedTableName, + $escapedAliasName, + '', + '', + $alias + ); + } + + /** + * Creates a new instance from full name. + * + * @param string $table Table name (w/o DB prefix) + * @param string $schema Schema name + * @param string $database Database name + * @param string $alias Alias name + */ + public static function fromFullName( + BaseConnection $db, + string $table, + string $schema = '', + string $database = '', + string $alias = '' + ): self { + $escapedTableName = ''; + if ($database !== '') { + $escapedTableName .= $db->escapeIdentifier($database) . '.'; + } + if ($schema !== '') { + $escapedTableName .= $db->escapeIdentifier($schema) . '.'; + } + $escapedTableName .= $db->escapeIdentifier($db->DBPrefix . $table); + + $escapedAliasName = $db->escapeIdentifier($alias); + + return new self( + $db->DBPrefix, + $table, + $escapedTableName, + $escapedAliasName, + $schema, + $database, + $alias + ); + } + + /** + * Returns the single segment table name w/o DB prefix. + */ + public function getTableName(): string + { + return $this->table; + } + + /** + * Returns the actual single segment table name w/z DB prefix. + */ + public function getActualTableName(): string + { + return $this->dbPrefix . $this->table; + } + + public function getAlias(): string + { + return $this->alias; + } + + public function getSchema(): string + { + return $this->schema; + } + + public function getDatabase(): string + { + return $this->database; + } + + /** + * Returns the escaped table name. + */ + public function getEscapedTableName(): string + { + return $this->escapedTableName; + } + + /** + * Returns the escaped table name with alias. + */ + public function getEscapedTableNameWithAlias(): string + { + if ($this->escapedAliasName === '') { + return $this->escapedTableName; + } + + return $this->escapedTableName . ' ' . $this->escapedAliasName; + } +} diff --git a/tests/system/Database/TableNameTest.php b/tests/system/Database/TableNameTest.php new file mode 100644 index 000000000000..7fc4841ffa32 --- /dev/null +++ b/tests/system/Database/TableNameTest.php @@ -0,0 +1,151 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Database; + +use CodeIgniter\Test\CIUnitTestCase; +use CodeIgniter\Test\Mock\MockConnection; + +/** + * @internal + * + * @group Others + */ +final class TableNameTest extends CIUnitTestCase +{ + protected function setUp(): void + { + parent::setUp(); + + $this->db = new MockConnection([ + 'database' => 'test', + 'DBPrefix' => 'db_', + 'schema' => 'dbo', + ]); + } + + public function testInstantiate(): void + { + $table = 'table'; + + $tableName = TableName::create($this->db, $table); + + $this->assertInstanceOf(TableName::class, $tableName); + } + + public function testCreateAndTableName(): void + { + $table = 'table'; + + $tableName = TableName::create($this->db, $table); + + $this->assertSame($table, $tableName->getTableName()); + $this->assertSame('db_table', $tableName->getActualTableName()); + } + + public function testFromActualNameAndTableName(): void + { + $table = 'table'; + + $tableName = TableName::fromActualName($this->db, $table); + + $this->assertSame($table, $tableName->getTableName()); + $this->assertSame($table, $tableName->getActualTableName()); + } + + public function testGetAlias(): void + { + $table = 'table'; + $alias = 't'; + + $tableName = TableName::create($this->db, $table, $alias); + + $this->assertSame($alias, $tableName->getAlias()); + } + + public function testGetSchema(): void + { + $table = 'table'; + $schema = 'dbo'; + $database = 'test'; + + $tableName = TableName::fromFullName($this->db, $table, $schema, $database); + + $this->assertSame($schema, $tableName->getSchema()); + } + + public function testGetDatabase(): void + { + $table = 'table'; + $schema = 'dbo'; + $database = 'test'; + + $tableName = TableName::fromFullName($this->db, $table, $schema, $database); + + $this->assertSame($database, $tableName->getDatabase()); + } + + public function testGetEscapedTableName(): void + { + $table = 'table'; + + $tableName = TableName::create($this->db, $table); + + $this->assertSame('"db_table"', $tableName->getEscapedTableName()); + } + + public function testGetEscapedTableNameFullName(): void + { + $table = 'table'; + $schema = 'dbo'; + $database = 'test'; + + $tableName = TableName::fromFullName($this->db, $table, $schema, $database); + + $this->assertSame('"test"."dbo"."db_table"', $tableName->getEscapedTableName()); + } + + public function testGetEscapedTableNameWithAlias(): void + { + $table = 'table'; + $alias = 't'; + + $tableName = TableName::create($this->db, $table, $alias); + + $this->assertSame('"db_table" "t"', $tableName->getEscapedTableNameWithAlias()); + } + + public function testGetEscapedTableNameWithAliasWithoutAlias(): void + { + $table = 'table'; + + $tableName = TableName::create($this->db, $table); + + $this->assertSame('"db_table"', $tableName->getEscapedTableNameWithAlias()); + } + + public function testGetEscapedTableNameWithAliasFullName(): void + { + $table = 'table'; + $schema = 'dbo'; + $database = 'test'; + $alias = 't'; + + $tableName = TableName::fromFullName($this->db, $table, $schema, $database, $alias); + + $this->assertSame( + '"test"."dbo"."db_table" "t"', + $tableName->getEscapedTableNameWithAlias() + ); + } +}