Skip to content

Commit

Permalink
Merge pull request #5504 from Laravel-Backpack/load-on-demand-and-fix…
Browse files Browse the repository at this point in the history
…-index-query

DB schema was loading ALL tables when not necessary
  • Loading branch information
pxpm committed May 6, 2024
2 parents 785f8f8 + 57b8c6e commit 1fe921d
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 60 deletions.
88 changes: 47 additions & 41 deletions src/app/Library/Database/DatabaseSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Backpack\CRUD\app\Library\Database;

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\LazyCollection;

Expand All @@ -12,28 +13,39 @@ final class DatabaseSchema
/**
* Return the schema for the table.
*/
public static function getForTable(string $connection, string $table)
public static function getForTable(string $table, string $connection)
{
$connection = $connection ?: config('database.default');

self::generateDatabaseSchema($connection);
self::generateDatabaseSchema($connection, $table);

return self::$schema[$connection][$table] ?? null;
}

public static function getTables(string $connection = null): array
{
$connection = $connection ?: config('database.default');
self::generateDatabaseSchema($connection);

return self::$schema[$connection] ?? [];
self::$schema[$connection] = LazyCollection::make(self::getCreateSchema($connection)->getTables())->mapWithKeys(function ($table, $key) use ($connection) {
$tableName = is_array($table) ? $table['name'] : $table->getName();

if ($existingTable = self::$schema[$connection][$tableName] ?? false) {
return [$tableName => $existingTable];
}

$table = self::mapTable($connection, $tableName);

return [$tableName => $table];
})->toArray();

return self::$schema[$connection];
}

public function listTableColumnsNames(string $connection, string $table)
{
$table = self::getForTable($connection, $table);
$table = self::getForTable($table, $connection);

return array_keys($table->getColumns());
return $table ? array_keys($table->getColumns()) : [];
}

public function listTableIndexes(string $connection, string $table)
Expand All @@ -51,59 +63,53 @@ public function getManager(string $connection = null)
/**
* Generates and store the database schema.
*/
private static function generateDatabaseSchema(string $connection)
private static function generateDatabaseSchema(string $connection, string $table)
{
if (! isset(self::$schema[$connection])) {
self::$schema[$connection] = self::mapTables($connection);
if (! isset(self::$schema[$connection][$table])) {
self::$schema[$connection][$table] = self::mapTable($connection, $table);
}
}

/**
* Map the tables from raw db values into an usable array.
*
* @param string $connection
* @return array
*/
private static function mapTables(string $connection)
private static function mapTable(string $connection, string $tableName)
{
return LazyCollection::make(self::getCreateSchema($connection)->getTables())->mapWithKeys(function ($table, $key) use ($connection) {
$tableName = is_array($table) ? $table['name'] : $table->getName();

if (self::$schema[$connection][$tableName] ?? false) {
return [$tableName => self::$schema[$connection][$tableName]];
}

if (is_array($table)) {
$table = new Table($tableName, self::mapTableColumns($connection, $tableName));
}
try {
$table = method_exists(self::getCreateSchema($connection), 'getTable') ?
self::getCreateSchema($connection)->getTable($tableName) :
self::getCreateSchema($connection)->getColumns($tableName);
} catch (\Exception $e) {
return new Table($tableName, []);
}

return [$tableName => $table];
})->toArray();
}
if (! is_array($table) || empty($table)) {
return $table;
}

private static function getIndexColumnNames(string $connection, string $table)
{
$schemaManager = self::getSchemaManager($connection);
$indexes = method_exists($schemaManager, 'listTableIndexes') ? $schemaManager->listTableIndexes($table) : $schemaManager->getIndexes($table);
$indexes = $schemaManager->getIndexes($tableName);

$indexes = array_map(function ($index) {
return is_array($index) ? $index['columns'] : $index->getColumns();
return $index['columns'];
}, $indexes);

$indexes = \Illuminate\Support\Arr::flatten($indexes);
$table = new Table($tableName, $table);

return array_unique($indexes);
$indexes = Arr::flatten($indexes);
$table->setIndexes(array_unique($indexes));

return $table;
}

private static function mapTableColumns(string $connection, string $table)
private static function getIndexColumnNames(string $connection, string $table)
{
$indexedColumns = self::getIndexColumnNames($connection, $table);
self::generateDatabaseSchema($connection, $table);

return LazyCollection::make(self::getSchemaManager($connection)->getColumns($table))->mapWithKeys(function ($column, $key) use ($indexedColumns) {
$column['index'] = array_key_exists($column['name'], $indexedColumns) ? true : false;
$indexes = self::$schema[$connection][$table]->getIndexes();

return [$column['name'] => $column];
})->toArray();
$indexes = \Illuminate\Support\Arr::flatten(array_map(function ($index) {
return is_string($index) ? $index : $index->getColumns();
}, $indexes));

return array_unique($indexes);
}

private static function getCreateSchema(string $connection)
Expand Down
11 changes: 11 additions & 0 deletions src/app/Library/Database/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ final class Table
{
private string $name;
private array $columns = [];
private array $indexes = [];

public function __construct(string $name, array $columns = [])
{
Expand Down Expand Up @@ -74,4 +75,14 @@ public function getColumn(string $columnName)
{
return $this->columns[$columnName];
}

public function getIndexes()
{
return $this->indexes;
}

public function setIndexes(array $indexes)
{
$this->indexes = $indexes;
}
}
23 changes: 4 additions & 19 deletions src/app/Library/Database/TableSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class TableSchema

public function __construct(string $connection, string $table)
{
$this->schema = app('DatabaseSchema')->getForTable($connection, $table);
$this->schema = app('DatabaseSchema')->getForTable($table, $connection);
}

/**
Expand Down Expand Up @@ -66,7 +66,7 @@ public function hasColumn($columnName)
*/
public function columnIsNullable($columnName)
{
if (! $this->columnExists($columnName)) {
if (! $this->hasColumn($columnName)) {
return true;
}

Expand All @@ -83,7 +83,7 @@ public function columnIsNullable($columnName)
*/
public function columnHasDefault($columnName)
{
if (! $this->columnExists($columnName)) {
if (! $this->hasColumn($columnName)) {
return false;
}

Expand All @@ -100,7 +100,7 @@ public function columnHasDefault($columnName)
*/
public function getColumnDefault($columnName)
{
if (! $this->columnExists($columnName)) {
if (! $this->hasColumn($columnName)) {
return false;
}

Expand All @@ -123,21 +123,6 @@ public function getColumns()
return $this->schema->getColumns();
}

/**
* Make sure column exists or throw an exception.
*
* @param string $columnName
* @return bool
*/
private function columnExists($columnName)
{
if (! $this->schemaExists()) {
return false;
}

return $this->schema->hasColumn($columnName);
}

/**
* Make sure the schema for the connection is initialized.
*
Expand Down

0 comments on commit 1fe921d

Please sign in to comment.