Skip to content

Commit 16b7b08

Browse files
committed
fix!: spark db:table causes errors w/z table name including speciali chars
1 parent af24e62 commit 16b7b08

File tree

10 files changed

+98
-31
lines changed

10 files changed

+98
-31
lines changed

phpstan-baseline.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,11 +2536,6 @@
25362536
'count' => 1,
25372537
'path' => __DIR__ . '/system/Database/BaseConnection.php',
25382538
];
2539-
$ignoreErrors[] = [
2540-
'message' => '#^Property CodeIgniter\\\\Database\\\\BaseConnection\\:\\:\\$aliasedTables type has no value type specified in iterable type array\\.$#',
2541-
'count' => 1,
2542-
'path' => __DIR__ . '/system/Database/BaseConnection.php',
2543-
];
25442539
$ignoreErrors[] = [
25452540
'message' => '#^Property CodeIgniter\\\\Database\\\\BaseConnection\\:\\:\\$dataCache type has no value type specified in iterable type array\\.$#',
25462541
'count' => 1,

system/Commands/Database/ShowTableInfo.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use CodeIgniter\CLI\BaseCommand;
1717
use CodeIgniter\CLI\CLI;
1818
use CodeIgniter\Database\BaseConnection;
19+
use CodeIgniter\Database\TableName;
1920
use Config\Database;
2021
use InvalidArgumentException;
2122

@@ -194,7 +195,7 @@ private function showDataOfTable(string $tableName, int $limitRows, int $limitFi
194195
CLI::newLine();
195196

196197
$this->removeDBPrefix();
197-
$thead = $this->db->getFieldNames($tableName);
198+
$thead = $this->db->getFieldNames(TableName::fromActualName($this->db, $tableName));
198199
$this->restoreDBPrefix();
199200

200201
// If there is a field named `id`, sort by it.
@@ -253,7 +254,7 @@ private function makeTableRows(
253254
$this->tbody = [];
254255

255256
$this->removeDBPrefix();
256-
$builder = $this->db->table($tableName);
257+
$builder = $this->db->table(TableName::fromActualName($this->db, $tableName));
257258
$builder->limit($limitRows);
258259
if ($sortField !== null) {
259260
$builder->orderBy($sortField, $this->sortDesc ? 'DESC' : 'ASC');

system/Database/BaseBuilder.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ class BaseBuilder
298298
/**
299299
* Constructor
300300
*
301-
* @param array|string $tableName tablename or tablenames with or without aliases
301+
* @param array|string|TableName $tableName tablename or tablenames with or without aliases
302302
*
303303
* Examples of $tableName: `mytable`, `jobs j`, `jobs j, users u`, `['jobs j','users u']`
304304
*
@@ -315,15 +315,20 @@ public function __construct($tableName, ConnectionInterface $db, ?array $options
315315
*/
316316
$this->db = $db;
317317

318+
if ($tableName instanceof TableName) {
319+
$this->tableName = $tableName->getTableName();
320+
$this->QBFrom[] = $tableName->getEscapedTableName();
321+
$this->db->addTableAlias($tableName->getAlias());
322+
}
318323
// If it contains `,`, it has multiple tables
319-
if (is_string($tableName) && strpos($tableName, ',') === false) {
324+
elseif (is_string($tableName) && strpos($tableName, ',') === false) {
320325
$this->tableName = $tableName; // @TODO remove alias if exists
326+
$this->from($tableName);
321327
} else {
322328
$this->tableName = '';
329+
$this->from($tableName);
323330
}
324331

325-
$this->from($tableName);
326-
327332
if ($options !== null && $options !== []) {
328333
foreach ($options as $key => $value) {
329334
if (property_exists($this, $key)) {

system/Database/BaseConnection.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,7 @@ abstract protected function _transRollback(): bool;
898898
/**
899899
* Returns a non-shared new instance of the query builder for this connection.
900900
*
901-
* @param array|string $tableName
901+
* @param array|string|TableName $tableName
902902
*
903903
* @return BaseBuilder
904904
*
@@ -1311,6 +1311,10 @@ public function escape($str)
13111311
return array_map([&$this, 'escape'], $str);
13121312
}
13131313

1314+
if ($str instanceof TableName) {
1315+
return $str->getEscapedTableName();
1316+
}
1317+
13141318
/** @psalm-suppress NoValue I don't know why ERROR. */
13151319
if (is_string($str) || (is_object($str) && method_exists($str, '__toString'))) {
13161320
if ($str instanceof RawSql) {
@@ -1511,12 +1515,16 @@ public function tableExists(string $tableName, bool $cached = true): bool
15111515
/**
15121516
* Fetch Field Names
15131517
*
1518+
* @param string|TableName $tableName
1519+
*
15141520
* @return array|false
15151521
*
15161522
* @throws DatabaseException
15171523
*/
1518-
public function getFieldNames(string $table)
1524+
public function getFieldNames($tableName)
15191525
{
1526+
$table = $tableName->getTableName();
1527+
15201528
// Is there a cached result?
15211529
if (isset($this->dataCache['field_names'][$table])) {
15221530
return $this->dataCache['field_names'][$table];
@@ -1526,7 +1534,7 @@ public function getFieldNames(string $table)
15261534
$this->initialize();
15271535
}
15281536

1529-
if (false === ($sql = $this->_listColumns($table))) {
1537+
if (false === ($sql = $this->_listColumns($tableName))) {
15301538
if ($this->DBDebug) {
15311539
throw new DatabaseException('This feature is not available for the database you are using.');
15321540
}
@@ -1740,9 +1748,11 @@ abstract protected function _listTables(bool $constrainByPrefix = false, ?string
17401748
/**
17411749
* Generates a platform-specific query string so that the column names can be fetched.
17421750
*
1751+
* @param string|TableName $table
1752+
*
17431753
* @return false|string
17441754
*/
1745-
abstract protected function _listColumns(string $table = '');
1755+
abstract protected function _listColumns($table = '');
17461756

17471757
/**
17481758
* Platform-specific field data information.

system/Database/MySQLi/Connection.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use CodeIgniter\Database\BaseConnection;
1717
use CodeIgniter\Database\Exceptions\DatabaseException;
18+
use CodeIgniter\Database\TableName;
1819
use LogicException;
1920
use mysqli;
2021
use mysqli_result;
@@ -404,10 +405,23 @@ protected function _listTables(bool $prefixLimit = false, ?string $tableName = n
404405

405406
/**
406407
* Generates a platform-specific query string so that the column names can be fetched.
408+
*
409+
* @param string|TableName $table
407410
*/
408-
protected function _listColumns(string $table = ''): string
411+
protected function _listColumns($table = ''): string
409412
{
410-
return 'SHOW COLUMNS FROM ' . $this->protectIdentifiers($table, true, null, false);
413+
if ($table instanceof TableName) {
414+
$tableName = $table->getEscapedTableName();
415+
} else {
416+
$tableName = $this->protectIdentifiers(
417+
$table,
418+
true,
419+
null,
420+
false
421+
);
422+
}
423+
424+
return 'SHOW COLUMNS FROM ' . $tableName;
411425
}
412426

413427
/**

system/Database/OCI8/Connection.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use CodeIgniter\Database\BaseConnection;
1717
use CodeIgniter\Database\Exceptions\DatabaseException;
1818
use CodeIgniter\Database\Query;
19+
use CodeIgniter\Database\TableName;
1920
use ErrorException;
2021
use stdClass;
2122

@@ -266,18 +267,25 @@ protected function _listTables(bool $prefixLimit = false, ?string $tableName = n
266267

267268
/**
268269
* Generates a platform-specific query string so that the column names can be fetched.
270+
*
271+
* @param string|TableName $table
269272
*/
270-
protected function _listColumns(string $table = ''): string
273+
protected function _listColumns($table = ''): string
271274
{
272-
if (strpos($table, '.') !== false) {
273-
sscanf($table, '%[^.].%s', $owner, $table);
275+
if ($table instanceof TableName) {
276+
$tableName = $table->getEscapedTableName();
277+
$owner = $this->username;
278+
} elseif (strpos($table, '.') !== false) {
279+
sscanf($table, '%[^.].%s', $owner, $tableName);
280+
$tableName = $this->escape(strtoupper($this->DBPrefix . $tableName));
274281
} else {
275-
$owner = $this->username;
282+
$owner = $this->username;
283+
$tableName = $this->escape(strtoupper($this->DBPrefix . $table));
276284
}
277285

278286
return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
279287
WHERE UPPER(OWNER) = ' . $this->escape(strtoupper($owner)) . '
280-
AND UPPER(TABLE_NAME) = ' . $this->escape(strtoupper($this->DBPrefix . $table));
288+
AND UPPER(TABLE_NAME) = ' . $tableName;
281289
}
282290

283291
/**

system/Database/Postgre/Connection.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use CodeIgniter\Database\BaseConnection;
1717
use CodeIgniter\Database\Exceptions\DatabaseException;
1818
use CodeIgniter\Database\RawSql;
19+
use CodeIgniter\Database\TableName;
1920
use ErrorException;
2021
use PgSql\Connection as PgSqlConnection;
2122
use PgSql\Result as PgSqlResult;
@@ -286,13 +287,21 @@ protected function _listTables(bool $prefixLimit = false, ?string $tableName = n
286287

287288
/**
288289
* Generates a platform-specific query string so that the column names can be fetched.
290+
*
291+
* @param string|TableName $table
289292
*/
290-
protected function _listColumns(string $table = ''): string
293+
protected function _listColumns($table = ''): string
291294
{
295+
if ($table instanceof TableName) {
296+
$tableName = $table->getEscapedTableName();
297+
} else {
298+
$tableName = $this->escape($this->DBPrefix . strtolower($table));
299+
}
300+
292301
return 'SELECT "column_name"
293302
FROM "information_schema"."columns"
294303
WHERE LOWER("table_name") = '
295-
. $this->escape($this->DBPrefix . strtolower($table))
304+
. $tableName
296305
. ' ORDER BY "ordinal_position"';
297306
}
298307

system/Database/SQLSRV/Connection.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use CodeIgniter\Database\BaseConnection;
1717
use CodeIgniter\Database\Exceptions\DatabaseException;
18+
use CodeIgniter\Database\TableName;
1819
use stdClass;
1920

2021
/**
@@ -221,12 +222,20 @@ protected function _listTables(bool $prefixLimit = false, ?string $tableName = n
221222

222223
/**
223224
* Generates a platform-specific query string so that the column names can be fetched.
225+
*
226+
* @param string|TableName $table
224227
*/
225-
protected function _listColumns(string $table = ''): string
228+
protected function _listColumns($table = ''): string
226229
{
230+
if ($table instanceof TableName) {
231+
$tableName = $table->getEscapedTableName();
232+
} else {
233+
$tableName = $this->escape($this->DBPrefix . $table);
234+
}
235+
227236
return 'SELECT [COLUMN_NAME] '
228237
. ' FROM [INFORMATION_SCHEMA].[COLUMNS]'
229-
. ' WHERE [TABLE_NAME] = ' . $this->escape($this->DBPrefix . $table)
238+
. ' WHERE [TABLE_NAME] = ' . $tableName
230239
. ' AND [TABLE_SCHEMA] = ' . $this->escape($this->schema);
231240
}
232241

system/Database/SQLite3/Connection.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use CodeIgniter\Database\BaseConnection;
1717
use CodeIgniter\Database\Exceptions\DatabaseException;
18+
use CodeIgniter\Database\TableName;
1819
use Exception;
1920
use SQLite3;
2021
use SQLite3Result;
@@ -202,19 +203,31 @@ protected function _listTables(bool $prefixLimit = false, ?string $tableName = n
202203

203204
/**
204205
* Generates a platform-specific query string so that the column names can be fetched.
206+
*
207+
* @param string|TableName $table
205208
*/
206-
protected function _listColumns(string $table = ''): string
209+
protected function _listColumns($table = ''): string
207210
{
208-
return 'PRAGMA TABLE_INFO(' . $this->protectIdentifiers($table, true, null, false) . ')';
211+
if ($table instanceof TableName) {
212+
$tableName = $table->getEscaped();
213+
} else {
214+
$tableName = $this->protectIdentifiers($table, true, null, false);
215+
}
216+
217+
return 'PRAGMA TABLE_INFO(' . $tableName . ')';
209218
}
210219

211220
/**
221+
* @param string|TableName $tableName
222+
*
212223
* @return array|false
213224
*
214225
* @throws DatabaseException
215226
*/
216-
public function getFieldNames(string $table)
227+
public function getFieldNames($tableName)
217228
{
229+
$table = $tableName->getTableName();
230+
218231
// Is there a cached result?
219232
if (isset($this->dataCache['field_names'][$table])) {
220233
return $this->dataCache['field_names'][$table];
@@ -224,7 +237,7 @@ public function getFieldNames(string $table)
224237
$this->initialize();
225238
}
226239

227-
$sql = $this->_listColumns($table);
240+
$sql = $this->_listColumns($tableName);
228241

229242
$query = $this->query($sql);
230243
$this->dataCache['field_names'][$table] = [];

system/Test/Mock/MockConnection.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use CodeIgniter\Database\BaseConnection;
1818
use CodeIgniter\Database\BaseResult;
1919
use CodeIgniter\Database\Query;
20+
use CodeIgniter\Database\TableName;
2021

2122
/**
2223
* @extends BaseConnection<object|resource, object|resource>
@@ -197,8 +198,10 @@ protected function _listTables(bool $constrainByPrefix = false, ?string $tableNa
197198

198199
/**
199200
* Generates a platform-specific query string so that the column names can be fetched.
201+
*
202+
* @param string|TableName $table
200203
*/
201-
protected function _listColumns(string $table = ''): string
204+
protected function _listColumns($table = ''): string
202205
{
203206
return '';
204207
}

0 commit comments

Comments
 (0)