init
This commit is contained in:
+1889
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,256 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Database\Schema\Grammars\Grammar;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Fluent;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class BlueprintState
|
||||
{
|
||||
/**
|
||||
* The blueprint instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Schema\Blueprint
|
||||
*/
|
||||
protected $blueprint;
|
||||
|
||||
/**
|
||||
* The connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The grammar instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Schema\Grammars\Grammar
|
||||
*/
|
||||
protected $grammar;
|
||||
|
||||
/**
|
||||
* The columns.
|
||||
*
|
||||
* @var \Illuminate\Database\Schema\ColumnDefinition[]
|
||||
*/
|
||||
private $columns;
|
||||
|
||||
/**
|
||||
* The primary key.
|
||||
*
|
||||
* @var \Illuminate\Database\Schema\IndexDefinition|null
|
||||
*/
|
||||
private $primaryKey;
|
||||
|
||||
/**
|
||||
* The indexes.
|
||||
*
|
||||
* @var \Illuminate\Database\Schema\IndexDefinition[]
|
||||
*/
|
||||
private $indexes;
|
||||
|
||||
/**
|
||||
* The foreign keys.
|
||||
*
|
||||
* @var \Illuminate\Database\Schema\ForeignKeyDefinition[]
|
||||
*/
|
||||
private $foreignKeys;
|
||||
|
||||
/**
|
||||
* Create a new blueprint state instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Blueprint $blueprint, Connection $connection, Grammar $grammar)
|
||||
{
|
||||
$this->blueprint = $blueprint;
|
||||
$this->connection = $connection;
|
||||
$this->grammar = $grammar;
|
||||
|
||||
$schema = $connection->getSchemaBuilder();
|
||||
$table = $blueprint->getTable();
|
||||
|
||||
$this->columns = (new Collection($schema->getColumns($table)))->map(fn ($column) => new ColumnDefinition([
|
||||
'name' => $column['name'],
|
||||
'type' => $column['type_name'],
|
||||
'full_type_definition' => $column['type'],
|
||||
'nullable' => $column['nullable'],
|
||||
'default' => is_null($column['default']) ? null : new Expression(Str::wrap($column['default'], '(', ')')),
|
||||
'autoIncrement' => $column['auto_increment'],
|
||||
'collation' => $column['collation'],
|
||||
'comment' => $column['comment'],
|
||||
'virtualAs' => ! is_null($column['generation']) && $column['generation']['type'] === 'virtual'
|
||||
? $column['generation']['expression'] : null,
|
||||
'storedAs' => ! is_null($column['generation']) && $column['generation']['type'] === 'stored'
|
||||
? $column['generation']['expression'] : null,
|
||||
]))->all();
|
||||
|
||||
[$primary, $indexes] = (new Collection($schema->getIndexes($table)))->map(fn ($index) => new IndexDefinition([
|
||||
'name' => match (true) {
|
||||
$index['primary'] => 'primary',
|
||||
$index['unique'] => 'unique',
|
||||
default => 'index',
|
||||
},
|
||||
'index' => $index['name'],
|
||||
'columns' => $index['columns'],
|
||||
]))->partition(fn ($index) => $index->name === 'primary');
|
||||
|
||||
$this->indexes = $indexes->all();
|
||||
$this->primaryKey = $primary->first();
|
||||
|
||||
$this->foreignKeys = (new Collection($schema->getForeignKeys($table)))->map(fn ($foreignKey) => new ForeignKeyDefinition([
|
||||
'columns' => $foreignKey['columns'],
|
||||
'on' => new Expression($foreignKey['foreign_table']),
|
||||
'references' => $foreignKey['foreign_columns'],
|
||||
'onUpdate' => $foreignKey['on_update'],
|
||||
'onDelete' => $foreignKey['on_delete'],
|
||||
]))->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the primary key.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\IndexDefinition|null
|
||||
*/
|
||||
public function getPrimaryKey()
|
||||
{
|
||||
return $this->primaryKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\ColumnDefinition[]
|
||||
*/
|
||||
public function getColumns()
|
||||
{
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indexes.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\IndexDefinition[]
|
||||
*/
|
||||
public function getIndexes()
|
||||
{
|
||||
return $this->indexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign keys.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\ForeignKeyDefinition[]
|
||||
*/
|
||||
public function getForeignKeys()
|
||||
{
|
||||
return $this->foreignKeys;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the blueprint's state.
|
||||
*
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @return void
|
||||
*/
|
||||
public function update(Fluent $command)
|
||||
{
|
||||
switch ($command->name) {
|
||||
case 'alter':
|
||||
// Already handled...
|
||||
break;
|
||||
|
||||
case 'add':
|
||||
$this->columns[] = $command->column;
|
||||
break;
|
||||
|
||||
case 'change':
|
||||
foreach ($this->columns as &$column) {
|
||||
if ($column->name === $command->column->name) {
|
||||
$column = $command->column;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'renameColumn':
|
||||
foreach ($this->columns as $column) {
|
||||
if ($column->name === $command->from) {
|
||||
$column->name = $command->to;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->primaryKey) {
|
||||
$this->primaryKey->columns = str_replace($command->from, $command->to, $this->primaryKey->columns);
|
||||
}
|
||||
|
||||
foreach ($this->indexes as $index) {
|
||||
$index->columns = str_replace($command->from, $command->to, $index->columns);
|
||||
}
|
||||
|
||||
foreach ($this->foreignKeys as $foreignKey) {
|
||||
$foreignKey->columns = str_replace($command->from, $command->to, $foreignKey->columns);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'dropColumn':
|
||||
$this->columns = array_values(
|
||||
array_filter($this->columns, fn ($column) => ! in_array($column->name, $command->columns))
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'primary':
|
||||
$this->primaryKey = $command;
|
||||
break;
|
||||
|
||||
case 'unique':
|
||||
case 'index':
|
||||
$this->indexes[] = $command;
|
||||
break;
|
||||
|
||||
case 'renameIndex':
|
||||
foreach ($this->indexes as $index) {
|
||||
if ($index->index === $command->from) {
|
||||
$index->index = $command->to;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'foreign':
|
||||
$this->foreignKeys[] = $command;
|
||||
break;
|
||||
|
||||
case 'dropPrimary':
|
||||
$this->primaryKey = null;
|
||||
break;
|
||||
|
||||
case 'dropIndex':
|
||||
case 'dropUnique':
|
||||
$this->indexes = array_values(
|
||||
array_filter($this->indexes, fn ($index) => $index->index !== $command->index)
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'dropForeign':
|
||||
$this->foreignKeys = array_values(
|
||||
array_filter($this->foreignKeys, fn ($fk) => $fk->columns !== $command->columns)
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
+620
@@ -0,0 +1,620 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
|
||||
class Builder
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* The database connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The schema grammar instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Schema\Grammars\Grammar
|
||||
*/
|
||||
protected $grammar;
|
||||
|
||||
/**
|
||||
* The Blueprint resolver callback.
|
||||
*
|
||||
* @var \Closure
|
||||
*/
|
||||
protected $resolver;
|
||||
|
||||
/**
|
||||
* The default string length for migrations.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
public static $defaultStringLength = 255;
|
||||
|
||||
/**
|
||||
* The default relationship morph key type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $defaultMorphKeyType = 'int';
|
||||
|
||||
/**
|
||||
* Create a new database Schema manager.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Connection $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->grammar = $connection->getSchemaGrammar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default string length for migrations.
|
||||
*
|
||||
* @param int $length
|
||||
* @return void
|
||||
*/
|
||||
public static function defaultStringLength($length)
|
||||
{
|
||||
static::$defaultStringLength = $length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default morph key type for migrations.
|
||||
*
|
||||
* @param string $type
|
||||
* @return void
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function defaultMorphKeyType(string $type)
|
||||
{
|
||||
if (! in_array($type, ['int', 'uuid', 'ulid'])) {
|
||||
throw new InvalidArgumentException("Morph key type must be 'int', 'uuid', or 'ulid'.");
|
||||
}
|
||||
|
||||
static::$defaultMorphKeyType = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default morph key type for migrations to UUIDs.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function morphUsingUuids()
|
||||
{
|
||||
static::defaultMorphKeyType('uuid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default morph key type for migrations to ULIDs.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function morphUsingUlids()
|
||||
{
|
||||
static::defaultMorphKeyType('ulid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a database in the schema.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function createDatabase($name)
|
||||
{
|
||||
throw new LogicException('This database driver does not support creating databases.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop a database from the schema if the database exists.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function dropDatabaseIfExists($name)
|
||||
{
|
||||
throw new LogicException('This database driver does not support dropping databases.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given table exists.
|
||||
*
|
||||
* @param string $table
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTable($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
foreach ($this->getTables() as $value) {
|
||||
if (strtolower($table) === strtolower($value['name'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given view exists.
|
||||
*
|
||||
* @param string $view
|
||||
* @return bool
|
||||
*/
|
||||
public function hasView($view)
|
||||
{
|
||||
$view = $this->connection->getTablePrefix().$view;
|
||||
|
||||
foreach ($this->getViews() as $value) {
|
||||
if (strtolower($view) === strtolower($value['name'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tables that belong to the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTables()
|
||||
{
|
||||
return $this->connection->getPostProcessor()->processTables(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileTables())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the names of the tables that belong to the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTableListing()
|
||||
{
|
||||
return array_column($this->getTables(), 'name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the views that belong to the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getViews()
|
||||
{
|
||||
return $this->connection->getPostProcessor()->processViews(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileViews())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user-defined types that belong to the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTypes()
|
||||
{
|
||||
throw new LogicException('This database driver does not support user-defined types.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given table has a given column.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $column
|
||||
* @return bool
|
||||
*/
|
||||
public function hasColumn($table, $column)
|
||||
{
|
||||
return in_array(
|
||||
strtolower($column), array_map('strtolower', $this->getColumnListing($table))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given table has given columns.
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
* @return bool
|
||||
*/
|
||||
public function hasColumns($table, array $columns)
|
||||
{
|
||||
$tableColumns = array_map('strtolower', $this->getColumnListing($table));
|
||||
|
||||
foreach ($columns as $column) {
|
||||
if (! in_array(strtolower($column), $tableColumns)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a table builder callback if the given table has a given column.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $column
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public function whenTableHasColumn(string $table, string $column, Closure $callback)
|
||||
{
|
||||
if ($this->hasColumn($table, $column)) {
|
||||
$this->table($table, fn (Blueprint $table) => $callback($table));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a table builder callback if the given table doesn't have a given column.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $column
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public function whenTableDoesntHaveColumn(string $table, string $column, Closure $callback)
|
||||
{
|
||||
if (! $this->hasColumn($table, $column)) {
|
||||
$this->table($table, fn (Blueprint $table) => $callback($table));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data type for the given column name.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $column
|
||||
* @param bool $fullDefinition
|
||||
* @return string
|
||||
*/
|
||||
public function getColumnType($table, $column, $fullDefinition = false)
|
||||
{
|
||||
$columns = $this->getColumns($table);
|
||||
|
||||
foreach ($columns as $value) {
|
||||
if (strtolower($value['name']) === strtolower($column)) {
|
||||
return $fullDefinition ? $value['type'] : $value['type_name'];
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("There is no column with name '$column' on table '$table'.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column listing for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnListing($table)
|
||||
{
|
||||
return array_column($this->getColumns($table), 'name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processColumns(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileColumns($table))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indexes for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexes($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processIndexes(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileIndexes($table))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the names of the indexes for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexListing($table)
|
||||
{
|
||||
return array_column($this->getIndexes($table), 'name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given table has a given index.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string|array $index
|
||||
* @param string|null $type
|
||||
* @return bool
|
||||
*/
|
||||
public function hasIndex($table, $index, $type = null)
|
||||
{
|
||||
$type = is_null($type) ? $type : strtolower($type);
|
||||
|
||||
foreach ($this->getIndexes($table) as $value) {
|
||||
$typeMatches = is_null($type)
|
||||
|| ($type === 'primary' && $value['primary'])
|
||||
|| ($type === 'unique' && $value['unique'])
|
||||
|| $type === $value['type'];
|
||||
|
||||
if (($value['name'] === $index || $value['columns'] === $index) && $typeMatches) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign keys for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getForeignKeys($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processForeignKeys(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileForeignKeys($table))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a table on the schema.
|
||||
*
|
||||
* @param string $table
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public function table($table, Closure $callback)
|
||||
{
|
||||
$this->build($this->createBlueprint($table, $callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new table on the schema.
|
||||
*
|
||||
* @param string $table
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public function create($table, Closure $callback)
|
||||
{
|
||||
$this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback) {
|
||||
$blueprint->create();
|
||||
|
||||
$callback($blueprint);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop a table from the schema.
|
||||
*
|
||||
* @param string $table
|
||||
* @return void
|
||||
*/
|
||||
public function drop($table)
|
||||
{
|
||||
$this->build(tap($this->createBlueprint($table), function ($blueprint) {
|
||||
$blueprint->drop();
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop a table from the schema if it exists.
|
||||
*
|
||||
* @param string $table
|
||||
* @return void
|
||||
*/
|
||||
public function dropIfExists($table)
|
||||
{
|
||||
$this->build(tap($this->createBlueprint($table), function ($blueprint) {
|
||||
$blueprint->dropIfExists();
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop columns from a table schema.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string|array $columns
|
||||
* @return void
|
||||
*/
|
||||
public function dropColumns($table, $columns)
|
||||
{
|
||||
$this->table($table, function (Blueprint $blueprint) use ($columns) {
|
||||
$blueprint->dropColumn($columns);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all tables from the database.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function dropAllTables()
|
||||
{
|
||||
throw new LogicException('This database driver does not support dropping all tables.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all views from the database.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function dropAllViews()
|
||||
{
|
||||
throw new LogicException('This database driver does not support dropping all views.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all types from the database.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function dropAllTypes()
|
||||
{
|
||||
throw new LogicException('This database driver does not support dropping all types.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename a table on the schema.
|
||||
*
|
||||
* @param string $from
|
||||
* @param string $to
|
||||
* @return void
|
||||
*/
|
||||
public function rename($from, $to)
|
||||
{
|
||||
$this->build(tap($this->createBlueprint($from), function ($blueprint) use ($to) {
|
||||
$blueprint->rename($to);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable foreign key constraints.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function enableForeignKeyConstraints()
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileEnableForeignKeyConstraints()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable foreign key constraints.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function disableForeignKeyConstraints()
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileDisableForeignKeyConstraints()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable foreign key constraints during the execution of a callback.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function withoutForeignKeyConstraints(Closure $callback)
|
||||
{
|
||||
$this->disableForeignKeyConstraints();
|
||||
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
$this->enableForeignKeyConstraints();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the blueprint to build / modify the table.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @return void
|
||||
*/
|
||||
protected function build(Blueprint $blueprint)
|
||||
{
|
||||
$blueprint->build($this->connection, $this->grammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new command set with a Closure.
|
||||
*
|
||||
* @param string $table
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Schema\Blueprint
|
||||
*/
|
||||
protected function createBlueprint($table, ?Closure $callback = null)
|
||||
{
|
||||
$prefix = $this->connection->getConfig('prefix_indexes')
|
||||
? $this->connection->getConfig('prefix')
|
||||
: '';
|
||||
|
||||
if (isset($this->resolver)) {
|
||||
return call_user_func($this->resolver, $table, $callback, $prefix);
|
||||
}
|
||||
|
||||
return Container::getInstance()->make(Blueprint::class, compact('table', 'callback', 'prefix'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database connection instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database connection instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return $this
|
||||
*/
|
||||
public function setConnection(Connection $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Schema Blueprint resolver callback.
|
||||
*
|
||||
* @param \Closure $resolver
|
||||
* @return void
|
||||
*/
|
||||
public function blueprintResolver(Closure $resolver)
|
||||
{
|
||||
$this->resolver = $resolver;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Support\Fluent;
|
||||
|
||||
/**
|
||||
* @method $this after(string $column) Place the column "after" another column (MySQL)
|
||||
* @method $this always(bool $value = true) Used as a modifier for generatedAs() (PostgreSQL)
|
||||
* @method $this autoIncrement() Set INTEGER columns as auto-increment (primary key)
|
||||
* @method $this change() Change the column
|
||||
* @method $this charset(string $charset) Specify a character set for the column (MySQL)
|
||||
* @method $this collation(string $collation) Specify a collation for the column
|
||||
* @method $this comment(string $comment) Add a comment to the column (MySQL/PostgreSQL)
|
||||
* @method $this default(mixed $value) Specify a "default" value for the column
|
||||
* @method $this first() Place the column "first" in the table (MySQL)
|
||||
* @method $this from(int $startingValue) Set the starting value of an auto-incrementing field (MySQL / PostgreSQL)
|
||||
* @method $this generatedAs(string|\Illuminate\Contracts\Database\Query\Expression $expression = null) Create a SQL compliant identity column (PostgreSQL)
|
||||
* @method $this index(bool|string $indexName = null) Add an index
|
||||
* @method $this invisible() Specify that the column should be invisible to "SELECT *" (MySQL)
|
||||
* @method $this nullable(bool $value = true) Allow NULL values to be inserted into the column
|
||||
* @method $this persisted() Mark the computed generated column as persistent (SQL Server)
|
||||
* @method $this primary(bool $value = true) Add a primary index
|
||||
* @method $this fulltext(bool|string $indexName = null) Add a fulltext index
|
||||
* @method $this spatialIndex(bool|string $indexName = null) Add a spatial index
|
||||
* @method $this startingValue(int $startingValue) Set the starting value of an auto-incrementing field (MySQL/PostgreSQL)
|
||||
* @method $this storedAs(string|\Illuminate\Contracts\Database\Query\Expression $expression) Create a stored generated column (MySQL/PostgreSQL/SQLite)
|
||||
* @method $this type(string $type) Specify a type for the column
|
||||
* @method $this unique(bool|string $indexName = null) Add a unique index
|
||||
* @method $this unsigned() Set the INTEGER column as UNSIGNED (MySQL)
|
||||
* @method $this useCurrent() Set the TIMESTAMP column to use CURRENT_TIMESTAMP as default value
|
||||
* @method $this useCurrentOnUpdate() Set the TIMESTAMP column to use CURRENT_TIMESTAMP when updating (MySQL)
|
||||
* @method $this virtualAs(string|\Illuminate\Contracts\Database\Query\Expression $expression) Create a virtual generated column (MySQL/PostgreSQL/SQLite)
|
||||
*/
|
||||
class ColumnDefinition extends Fluent
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Support\Stringable;
|
||||
|
||||
class ForeignIdColumnDefinition extends ColumnDefinition
|
||||
{
|
||||
/**
|
||||
* The schema builder blueprint instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Schema\Blueprint
|
||||
*/
|
||||
protected $blueprint;
|
||||
|
||||
/**
|
||||
* Create a new foreign ID column definition.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Blueprint $blueprint, $attributes = [])
|
||||
{
|
||||
parent::__construct($attributes);
|
||||
|
||||
$this->blueprint = $blueprint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a foreign key constraint on this column referencing the "id" column of the conventionally related table.
|
||||
*
|
||||
* @param string|null $table
|
||||
* @param string|null $column
|
||||
* @param string|null $indexName
|
||||
* @return \Illuminate\Database\Schema\ForeignKeyDefinition
|
||||
*/
|
||||
public function constrained($table = null, $column = null, $indexName = null)
|
||||
{
|
||||
$table ??= $this->table;
|
||||
$column ??= $this->referencesModelColumn ?? 'id';
|
||||
|
||||
return $this->references($column, $indexName)->on($table ?? (new Stringable($this->name))->beforeLast('_'.$column)->plural());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify which column this foreign ID references on another table.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $indexName
|
||||
* @return \Illuminate\Database\Schema\ForeignKeyDefinition
|
||||
*/
|
||||
public function references($column, $indexName = null)
|
||||
{
|
||||
return $this->blueprint->foreign($this->name, $indexName)->references($column);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Support\Fluent;
|
||||
|
||||
/**
|
||||
* @method ForeignKeyDefinition deferrable(bool $value = true) Set the foreign key as deferrable (PostgreSQL)
|
||||
* @method ForeignKeyDefinition initiallyImmediate(bool $value = true) Set the default time to check the constraint (PostgreSQL)
|
||||
* @method ForeignKeyDefinition on(string $table) Specify the referenced table
|
||||
* @method ForeignKeyDefinition onDelete(string $action) Add an ON DELETE action
|
||||
* @method ForeignKeyDefinition onUpdate(string $action) Add an ON UPDATE action
|
||||
* @method ForeignKeyDefinition references(string|array $columns) Specify the referenced column(s)
|
||||
*/
|
||||
class ForeignKeyDefinition extends Fluent
|
||||
{
|
||||
/**
|
||||
* Indicate that updates should cascade.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function cascadeOnUpdate()
|
||||
{
|
||||
return $this->onUpdate('cascade');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that updates should be restricted.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function restrictOnUpdate()
|
||||
{
|
||||
return $this->onUpdate('restrict');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that updates should set the foreign key value to null.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function nullOnUpdate()
|
||||
{
|
||||
return $this->onUpdate('set null');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that updates should have "no action".
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function noActionOnUpdate()
|
||||
{
|
||||
return $this->onUpdate('no action');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that deletes should cascade.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function cascadeOnDelete()
|
||||
{
|
||||
return $this->onDelete('cascade');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that deletes should be restricted.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function restrictOnDelete()
|
||||
{
|
||||
return $this->onDelete('restrict');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that deletes should set the foreign key value to null.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function nullOnDelete()
|
||||
{
|
||||
return $this->onDelete('set null');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that deletes should have "no action".
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function noActionOnDelete()
|
||||
{
|
||||
return $this->onDelete('no action');
|
||||
}
|
||||
}
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema\Grammars;
|
||||
|
||||
use BackedEnum;
|
||||
use Illuminate\Contracts\Database\Query\Expression;
|
||||
use Illuminate\Database\Concerns\CompilesJsonPaths;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\Grammar as BaseGrammar;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Fluent;
|
||||
use LogicException;
|
||||
use RuntimeException;
|
||||
|
||||
abstract class Grammar extends BaseGrammar
|
||||
{
|
||||
use CompilesJsonPaths;
|
||||
|
||||
/**
|
||||
* The possible column modifiers.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $modifiers = [];
|
||||
|
||||
/**
|
||||
* If this Grammar supports schema changes wrapped in a transaction.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $transactions = false;
|
||||
|
||||
/**
|
||||
* The commands to be executed outside of create or alter command.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fluentCommands = [];
|
||||
|
||||
/**
|
||||
* Compile a create database command.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function compileCreateDatabase($name, $connection)
|
||||
{
|
||||
throw new LogicException('This database driver does not support creating databases.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a drop database if exists command.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function compileDropDatabaseIfExists($name)
|
||||
{
|
||||
throw new LogicException('This database driver does not support dropping databases.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a rename column command.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return array|string
|
||||
*/
|
||||
public function compileRenameColumn(Blueprint $blueprint, Fluent $command, Connection $connection)
|
||||
{
|
||||
return sprintf('alter table %s rename column %s to %s',
|
||||
$this->wrapTable($blueprint),
|
||||
$this->wrap($command->from),
|
||||
$this->wrap($command->to)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a change column command into a series of SQL statements.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return array|string
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function compileChange(Blueprint $blueprint, Fluent $command, Connection $connection)
|
||||
{
|
||||
throw new LogicException('This database driver does not support modifying columns.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a fulltext index key command.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function compileFulltext(Blueprint $blueprint, Fluent $command)
|
||||
{
|
||||
throw new RuntimeException('This database driver does not support fulltext index creation.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a drop fulltext index command.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function compileDropFullText(Blueprint $blueprint, Fluent $command)
|
||||
{
|
||||
throw new RuntimeException('This database driver does not support fulltext index removal.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a foreign key command.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @return string
|
||||
*/
|
||||
public function compileForeign(Blueprint $blueprint, Fluent $command)
|
||||
{
|
||||
// We need to prepare several of the elements of the foreign key definition
|
||||
// before we can create the SQL, such as wrapping the tables and convert
|
||||
// an array of columns to comma-delimited strings for the SQL queries.
|
||||
$sql = sprintf('alter table %s add constraint %s ',
|
||||
$this->wrapTable($blueprint),
|
||||
$this->wrap($command->index)
|
||||
);
|
||||
|
||||
// Once we have the initial portion of the SQL statement we will add on the
|
||||
// key name, table name, and referenced columns. These will complete the
|
||||
// main portion of the SQL statement and this SQL will almost be done.
|
||||
$sql .= sprintf('foreign key (%s) references %s (%s)',
|
||||
$this->columnize($command->columns),
|
||||
$this->wrapTable($command->on),
|
||||
$this->columnize((array) $command->references)
|
||||
);
|
||||
|
||||
// Once we have the basic foreign key creation statement constructed we can
|
||||
// build out the syntax for what should happen on an update or delete of
|
||||
// the affected columns, which will get something like "cascade", etc.
|
||||
if (! is_null($command->onDelete)) {
|
||||
$sql .= " on delete {$command->onDelete}";
|
||||
}
|
||||
|
||||
if (! is_null($command->onUpdate)) {
|
||||
$sql .= " on update {$command->onUpdate}";
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a drop foreign key command.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @return string
|
||||
*/
|
||||
public function compileDropForeign(Blueprint $blueprint, Fluent $command)
|
||||
{
|
||||
throw new RuntimeException('This database driver does not support dropping foreign keys.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the blueprint's added column definitions.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @return array
|
||||
*/
|
||||
protected function getColumns(Blueprint $blueprint)
|
||||
{
|
||||
$columns = [];
|
||||
|
||||
foreach ($blueprint->getAddedColumns() as $column) {
|
||||
$columns[] = $this->getColumn($blueprint, $column);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the column definition.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Database\Schema\ColumnDefinition $column
|
||||
* @return string
|
||||
*/
|
||||
protected function getColumn(Blueprint $blueprint, $column)
|
||||
{
|
||||
// Each of the column types has their own compiler functions, which are tasked
|
||||
// with turning the column definition into its SQL format for this platform
|
||||
// used by the connection. The column's modifiers are compiled and added.
|
||||
$sql = $this->wrap($column).' '.$this->getType($column);
|
||||
|
||||
return $this->addModifiers($sql, $blueprint, $column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL for the column data type.
|
||||
*
|
||||
* @param \Illuminate\Support\Fluent $column
|
||||
* @return string
|
||||
*/
|
||||
protected function getType(Fluent $column)
|
||||
{
|
||||
return $this->{'type'.ucfirst($column->type)}($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the column definition for a generated, computed column type.
|
||||
*
|
||||
* @param \Illuminate\Support\Fluent $column
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function typeComputed(Fluent $column)
|
||||
{
|
||||
throw new RuntimeException('This database driver does not support the computed type.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the column definition for a vector type.
|
||||
*
|
||||
* @param \Illuminate\Support\Fluent $column
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function typeVector(Fluent $column)
|
||||
{
|
||||
throw new RuntimeException('This database driver does not support the vector type.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the column definition for a raw column type.
|
||||
*
|
||||
* @param \Illuminate\Support\Fluent $column
|
||||
* @return string
|
||||
*/
|
||||
protected function typeRaw(Fluent $column)
|
||||
{
|
||||
return $column->offsetGet('definition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the column modifiers to the definition.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $column
|
||||
* @return string
|
||||
*/
|
||||
protected function addModifiers($sql, Blueprint $blueprint, Fluent $column)
|
||||
{
|
||||
foreach ($this->modifiers as $modifier) {
|
||||
if (method_exists($this, $method = "modify{$modifier}")) {
|
||||
$sql .= $this->{$method}($blueprint, $column);
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command with a given name if it exists on the blueprint.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param string $name
|
||||
* @return \Illuminate\Support\Fluent|null
|
||||
*/
|
||||
protected function getCommandByName(Blueprint $blueprint, $name)
|
||||
{
|
||||
$commands = $this->getCommandsByName($blueprint, $name);
|
||||
|
||||
if (count($commands) > 0) {
|
||||
return reset($commands);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the commands with a given name.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function getCommandsByName(Blueprint $blueprint, $name)
|
||||
{
|
||||
return array_filter($blueprint->getCommands(), function ($value) use ($name) {
|
||||
return $value->name == $name;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if a command with a given name exists on the blueprint.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasCommand(Blueprint $blueprint, $name)
|
||||
{
|
||||
foreach ($blueprint->getCommands() as $command) {
|
||||
if ($command->name === $name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a prefix to an array of values.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function prefixArray($prefix, array $values)
|
||||
{
|
||||
return array_map(function ($value) use ($prefix) {
|
||||
return $prefix.' '.$value;
|
||||
}, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a table in keyword identifiers.
|
||||
*
|
||||
* @param mixed $table
|
||||
* @return string
|
||||
*/
|
||||
public function wrapTable($table)
|
||||
{
|
||||
return parent::wrapTable(
|
||||
$table instanceof Blueprint ? $table->getTable() : $table
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a value in keyword identifiers.
|
||||
*
|
||||
* @param \Illuminate\Support\Fluent|\Illuminate\Contracts\Database\Query\Expression|string $value
|
||||
* @return string
|
||||
*/
|
||||
public function wrap($value)
|
||||
{
|
||||
return parent::wrap(
|
||||
$value instanceof Fluent ? $value->name : $value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a value so that it can be used in "default" clauses.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function getDefaultValue($value)
|
||||
{
|
||||
if ($value instanceof Expression) {
|
||||
return $this->getValue($value);
|
||||
}
|
||||
|
||||
if ($value instanceof BackedEnum) {
|
||||
return "'{$value->value}'";
|
||||
}
|
||||
|
||||
return is_bool($value)
|
||||
? "'".(int) $value."'"
|
||||
: "'".(string) $value."'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fluent commands for the grammar.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFluentCommands()
|
||||
{
|
||||
return $this->fluentCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this Grammar supports schema changes wrapped in a transaction.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsSchemaTransactions()
|
||||
{
|
||||
return $this->transactions;
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema\Grammars;
|
||||
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Fluent;
|
||||
|
||||
class MariaDbGrammar extends MySqlGrammar
|
||||
{
|
||||
/**
|
||||
* Compile a rename column command.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return array|string
|
||||
*/
|
||||
public function compileRenameColumn(Blueprint $blueprint, Fluent $command, Connection $connection)
|
||||
{
|
||||
if (version_compare($connection->getServerVersion(), '10.5.2', '<')) {
|
||||
return $this->compileLegacyRenameColumn($blueprint, $command, $connection);
|
||||
}
|
||||
|
||||
return parent::compileRenameColumn($blueprint, $command, $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the column definition for a uuid type.
|
||||
*
|
||||
* @param \Illuminate\Support\Fluent $column
|
||||
* @return string
|
||||
*/
|
||||
protected function typeUuid(Fluent $column)
|
||||
{
|
||||
return 'uuid';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the column definition for a spatial Geometry type.
|
||||
*
|
||||
* @param \Illuminate\Support\Fluent $column
|
||||
* @return string
|
||||
*/
|
||||
protected function typeGeometry(Fluent $column)
|
||||
{
|
||||
$subtype = $column->subtype ? strtolower($column->subtype) : null;
|
||||
|
||||
if (! in_array($subtype, ['point', 'linestring', 'polygon', 'geometrycollection', 'multipoint', 'multilinestring', 'multipolygon'])) {
|
||||
$subtype = null;
|
||||
}
|
||||
|
||||
return sprintf('%s%s',
|
||||
$subtype ?? 'geometry',
|
||||
$column->srid ? ' ref_system_id='.$column->srid : ''
|
||||
);
|
||||
}
|
||||
}
|
||||
+1371
File diff suppressed because it is too large
Load Diff
+1235
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1072
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Support\Fluent;
|
||||
|
||||
/**
|
||||
* @method $this algorithm(string $algorithm) Specify an algorithm for the index (MySQL/PostgreSQL)
|
||||
* @method $this language(string $language) Specify a language for the full text index (PostgreSQL)
|
||||
* @method $this deferrable(bool $value = true) Specify that the unique index is deferrable (PostgreSQL)
|
||||
* @method $this initiallyImmediate(bool $value = true) Specify the default time to check the unique index constraint (PostgreSQL)
|
||||
*/
|
||||
class IndexDefinition extends Fluent
|
||||
{
|
||||
//
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
class MariaDbBuilder extends MySqlBuilder
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
class MariaDbSchemaState extends MySqlSchemaState
|
||||
{
|
||||
/**
|
||||
* Get the base dump command arguments for MariaDB as a string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function baseDumpCommand()
|
||||
{
|
||||
$command = 'mysqldump '.$this->connectionString().' --no-tablespaces --skip-add-locks --skip-comments --skip-set-charset --tz-utc --column-statistics=0';
|
||||
|
||||
return $command.' "${:LARAVEL_LOAD_DATABASE}"';
|
||||
}
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
class MySqlBuilder extends Builder
|
||||
{
|
||||
/**
|
||||
* Create a database in the schema.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function createDatabase($name)
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileCreateDatabase($name, $this->connection)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop a database from the schema if the database exists.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dropDatabaseIfExists($name)
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileDropDatabaseIfExists($name)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given table exists.
|
||||
*
|
||||
* @param string $table
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTable($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
$database = $this->connection->getDatabaseName();
|
||||
|
||||
return (bool) $this->connection->scalar(
|
||||
$this->grammar->compileTableExists($database, $table)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tables for the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTables()
|
||||
{
|
||||
return $this->connection->getPostProcessor()->processTables(
|
||||
$this->connection->selectFromWriteConnection(
|
||||
$this->grammar->compileTables($this->connection->getDatabaseName())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the views for the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getViews()
|
||||
{
|
||||
return $this->connection->getPostProcessor()->processViews(
|
||||
$this->connection->selectFromWriteConnection(
|
||||
$this->grammar->compileViews($this->connection->getDatabaseName())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
$results = $this->connection->selectFromWriteConnection(
|
||||
$this->grammar->compileColumns($this->connection->getDatabaseName(), $table)
|
||||
);
|
||||
|
||||
return $this->connection->getPostProcessor()->processColumns($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indexes for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexes($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processIndexes(
|
||||
$this->connection->selectFromWriteConnection(
|
||||
$this->grammar->compileIndexes($this->connection->getDatabaseName(), $table)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign keys for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getForeignKeys($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processForeignKeys(
|
||||
$this->connection->selectFromWriteConnection(
|
||||
$this->grammar->compileForeignKeys($this->connection->getDatabaseName(), $table)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all tables from the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dropAllTables()
|
||||
{
|
||||
$tables = array_column($this->getTables(), 'name');
|
||||
|
||||
if (empty($tables)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->disableForeignKeyConstraints();
|
||||
|
||||
$this->connection->statement(
|
||||
$this->grammar->compileDropAllTables($tables)
|
||||
);
|
||||
|
||||
$this->enableForeignKeyConstraints();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all views from the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dropAllViews()
|
||||
{
|
||||
$views = array_column($this->getViews(), 'name');
|
||||
|
||||
if (empty($views)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->connection->statement(
|
||||
$this->grammar->compileDropAllViews($views)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class MySqlSchemaState extends SchemaState
|
||||
{
|
||||
/**
|
||||
* Dump the database's schema into a file.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function dump(Connection $connection, $path)
|
||||
{
|
||||
$this->executeDumpProcess($this->makeProcess(
|
||||
$this->baseDumpCommand().' --routines --result-file="${:LARAVEL_LOAD_PATH}" --no-data'
|
||||
), $this->output, array_merge($this->baseVariables($this->connection->getConfig()), [
|
||||
'LARAVEL_LOAD_PATH' => $path,
|
||||
]));
|
||||
|
||||
$this->removeAutoIncrementingState($path);
|
||||
|
||||
if ($this->hasMigrationTable()) {
|
||||
$this->appendMigrationData($path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the auto-incrementing state from the given schema dump.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
protected function removeAutoIncrementingState(string $path)
|
||||
{
|
||||
$this->files->put($path, preg_replace(
|
||||
'/\s+AUTO_INCREMENT=[0-9]+/iu',
|
||||
'',
|
||||
$this->files->get($path)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the migration data to the schema dump.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
protected function appendMigrationData(string $path)
|
||||
{
|
||||
$process = $this->executeDumpProcess($this->makeProcess(
|
||||
$this->baseDumpCommand().' '.$this->getMigrationTable().' --no-create-info --skip-extended-insert --skip-routines --compact --complete-insert'
|
||||
), null, array_merge($this->baseVariables($this->connection->getConfig()), [
|
||||
//
|
||||
]));
|
||||
|
||||
$this->files->append($path, $process->getOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given schema file into the database.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function load($path)
|
||||
{
|
||||
$command = 'mysql '.$this->connectionString().' --database="${:LARAVEL_LOAD_DATABASE}" < "${:LARAVEL_LOAD_PATH}"';
|
||||
|
||||
$process = $this->makeProcess($command)->setTimeout(null);
|
||||
|
||||
$process->mustRun(null, array_merge($this->baseVariables($this->connection->getConfig()), [
|
||||
'LARAVEL_LOAD_PATH' => $path,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base dump command arguments for MySQL as a string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function baseDumpCommand()
|
||||
{
|
||||
$command = 'mysqldump '.$this->connectionString().' --no-tablespaces --skip-add-locks --skip-comments --skip-set-charset --tz-utc --column-statistics=0';
|
||||
|
||||
if (! $this->connection->isMaria()) {
|
||||
$command .= ' --set-gtid-purged=OFF';
|
||||
}
|
||||
|
||||
return $command.' "${:LARAVEL_LOAD_DATABASE}"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a basic connection string (--socket, --host, --port, --user, --password) for the database.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function connectionString()
|
||||
{
|
||||
$value = ' --user="${:LARAVEL_LOAD_USER}" --password="${:LARAVEL_LOAD_PASSWORD}"';
|
||||
|
||||
$config = $this->connection->getConfig();
|
||||
|
||||
$value .= $config['unix_socket'] ?? false
|
||||
? ' --socket="${:LARAVEL_LOAD_SOCKET}"'
|
||||
: ' --host="${:LARAVEL_LOAD_HOST}" --port="${:LARAVEL_LOAD_PORT}"';
|
||||
|
||||
if (isset($config['options'][\PDO::MYSQL_ATTR_SSL_CA])) {
|
||||
$value .= ' --ssl-ca="${:LARAVEL_LOAD_SSL_CA}"';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base variables for a dump / load command.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function baseVariables(array $config)
|
||||
{
|
||||
$config['host'] ??= '';
|
||||
|
||||
return [
|
||||
'LARAVEL_LOAD_SOCKET' => $config['unix_socket'] ?? '',
|
||||
'LARAVEL_LOAD_HOST' => is_array($config['host']) ? $config['host'][0] : $config['host'],
|
||||
'LARAVEL_LOAD_PORT' => $config['port'] ?? '',
|
||||
'LARAVEL_LOAD_USER' => $config['username'],
|
||||
'LARAVEL_LOAD_PASSWORD' => $config['password'] ?? '',
|
||||
'LARAVEL_LOAD_DATABASE' => $config['database'],
|
||||
'LARAVEL_LOAD_SSL_CA' => $config['options'][\PDO::MYSQL_ATTR_SSL_CA] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given dump process.
|
||||
*
|
||||
* @param \Symfony\Component\Process\Process $process
|
||||
* @param callable $output
|
||||
* @param array $variables
|
||||
* @param int $depth
|
||||
* @return \Symfony\Component\Process\Process
|
||||
*/
|
||||
protected function executeDumpProcess(Process $process, $output, array $variables, int $depth = 0)
|
||||
{
|
||||
if ($depth > 30) {
|
||||
throw new Exception('Dump execution exceeded maximum depth of 30.');
|
||||
}
|
||||
|
||||
try {
|
||||
$process->setTimeout(null)->mustRun($output, $variables);
|
||||
} catch (Exception $e) {
|
||||
if (Str::contains($e->getMessage(), ['column-statistics', 'column_statistics'])) {
|
||||
return $this->executeDumpProcess(Process::fromShellCommandLine(
|
||||
str_replace(' --column-statistics=0', '', $process->getCommandLine())
|
||||
), $output, $variables, $depth + 1);
|
||||
}
|
||||
|
||||
if (str_contains($e->getMessage(), 'set-gtid-purged')) {
|
||||
return $this->executeDumpProcess(Process::fromShellCommandLine(
|
||||
str_replace(' --set-gtid-purged=OFF', '', $process->getCommandLine())
|
||||
), $output, $variables, $depth + 1);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $process;
|
||||
}
|
||||
}
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Database\Concerns\ParsesSearchPath;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class PostgresBuilder extends Builder
|
||||
{
|
||||
use ParsesSearchPath {
|
||||
parseSearchPath as baseParseSearchPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a database in the schema.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function createDatabase($name)
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileCreateDatabase($name, $this->connection)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop a database from the schema if the database exists.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dropDatabaseIfExists($name)
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileDropDatabaseIfExists($name)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given table exists.
|
||||
*
|
||||
* @param string $table
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTable($table)
|
||||
{
|
||||
[$schema, $table] = $this->parseSchemaAndTable($table);
|
||||
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return (bool) $this->connection->scalar(
|
||||
$this->grammar->compileTableExists($schema, $table)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given view exists.
|
||||
*
|
||||
* @param string $view
|
||||
* @return bool
|
||||
*/
|
||||
public function hasView($view)
|
||||
{
|
||||
[$schema, $view] = $this->parseSchemaAndTable($view);
|
||||
|
||||
$view = $this->connection->getTablePrefix().$view;
|
||||
|
||||
foreach ($this->getViews() as $value) {
|
||||
if (strtolower($view) === strtolower($value['name'])
|
||||
&& strtolower($schema) === strtolower($value['schema'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user-defined types that belong to the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTypes()
|
||||
{
|
||||
return $this->connection->getPostProcessor()->processTypes(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileTypes())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all tables from the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dropAllTables()
|
||||
{
|
||||
$tables = [];
|
||||
|
||||
$excludedTables = $this->connection->getConfig('dont_drop') ?? ['spatial_ref_sys'];
|
||||
|
||||
$schemas = $this->getSchemas();
|
||||
|
||||
foreach ($this->getTables() as $table) {
|
||||
$qualifiedName = $table['schema'].'.'.$table['name'];
|
||||
|
||||
if (in_array($table['schema'], $schemas) &&
|
||||
empty(array_intersect([$table['name'], $qualifiedName], $excludedTables))) {
|
||||
$tables[] = $qualifiedName;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($tables)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->connection->statement(
|
||||
$this->grammar->compileDropAllTables($tables)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all views from the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dropAllViews()
|
||||
{
|
||||
$views = [];
|
||||
|
||||
$schemas = $this->getSchemas();
|
||||
|
||||
foreach ($this->getViews() as $view) {
|
||||
if (in_array($view['schema'], $schemas)) {
|
||||
$views[] = $view['schema'].'.'.$view['name'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($views)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->connection->statement(
|
||||
$this->grammar->compileDropAllViews($views)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all types from the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dropAllTypes()
|
||||
{
|
||||
$types = [];
|
||||
$domains = [];
|
||||
|
||||
$schemas = $this->getSchemas();
|
||||
|
||||
foreach ($this->getTypes() as $type) {
|
||||
if (! $type['implicit'] && in_array($type['schema'], $schemas)) {
|
||||
if ($type['type'] === 'domain') {
|
||||
$domains[] = $type['schema'].'.'.$type['name'];
|
||||
} else {
|
||||
$types[] = $type['schema'].'.'.$type['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($types)) {
|
||||
$this->connection->statement($this->grammar->compileDropAllTypes($types));
|
||||
}
|
||||
|
||||
if (! empty($domains)) {
|
||||
$this->connection->statement($this->grammar->compileDropAllDomains($domains));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($table)
|
||||
{
|
||||
[$schema, $table] = $this->parseSchemaAndTable($table);
|
||||
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
$results = $this->connection->selectFromWriteConnection(
|
||||
$this->grammar->compileColumns($schema, $table)
|
||||
);
|
||||
|
||||
return $this->connection->getPostProcessor()->processColumns($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indexes for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexes($table)
|
||||
{
|
||||
[$schema, $table] = $this->parseSchemaAndTable($table);
|
||||
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processIndexes(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileIndexes($schema, $table))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign keys for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getForeignKeys($table)
|
||||
{
|
||||
[$schema, $table] = $this->parseSchemaAndTable($table);
|
||||
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processForeignKeys(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileForeignKeys($schema, $table))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the schemas for the connection.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSchemas()
|
||||
{
|
||||
return $this->parseSearchPath(
|
||||
$this->connection->getConfig('search_path') ?: $this->connection->getConfig('schema') ?: 'public'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the database object reference and extract the schema and table.
|
||||
*
|
||||
* @param string $reference
|
||||
* @return array
|
||||
*/
|
||||
public function parseSchemaAndTable($reference)
|
||||
{
|
||||
$parts = explode('.', $reference);
|
||||
|
||||
if (count($parts) > 2) {
|
||||
$database = $parts[0];
|
||||
|
||||
throw new InvalidArgumentException("Using three-part reference is not supported, you may use `Schema::connection('$database')` instead.");
|
||||
}
|
||||
|
||||
// We will use the default schema unless the schema has been specified in the
|
||||
// query. If the schema has been specified in the query then we can use it
|
||||
// instead of a default schema configured in the connection search path.
|
||||
$schema = $this->getSchemas()[0];
|
||||
|
||||
if (count($parts) === 2) {
|
||||
$schema = $parts[0];
|
||||
array_shift($parts);
|
||||
}
|
||||
|
||||
return [$schema, $parts[0]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the "search_path" configuration value into an array.
|
||||
*
|
||||
* @param string|array|null $searchPath
|
||||
* @return array
|
||||
*/
|
||||
protected function parseSearchPath($searchPath)
|
||||
{
|
||||
return array_map(function ($schema) {
|
||||
return $schema === '$user'
|
||||
? $this->connection->getConfig('username')
|
||||
: $schema;
|
||||
}, $this->baseParseSearchPath($searchPath));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class PostgresSchemaState extends SchemaState
|
||||
{
|
||||
/**
|
||||
* Dump the database's schema into a file.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function dump(Connection $connection, $path)
|
||||
{
|
||||
$commands = new Collection([
|
||||
$this->baseDumpCommand().' --schema-only > '.$path,
|
||||
]);
|
||||
|
||||
if ($this->hasMigrationTable()) {
|
||||
$commands->push($this->baseDumpCommand().' -t '.$this->getMigrationTable().' --data-only >> '.$path);
|
||||
}
|
||||
|
||||
$commands->map(function ($command, $path) {
|
||||
$this->makeProcess($command)->mustRun($this->output, array_merge($this->baseVariables($this->connection->getConfig()), [
|
||||
'LARAVEL_LOAD_PATH' => $path,
|
||||
]));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given schema file into the database.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function load($path)
|
||||
{
|
||||
$command = 'pg_restore --no-owner --no-acl --clean --if-exists --host="${:LARAVEL_LOAD_HOST}" --port="${:LARAVEL_LOAD_PORT}" --username="${:LARAVEL_LOAD_USER}" --dbname="${:LARAVEL_LOAD_DATABASE}" "${:LARAVEL_LOAD_PATH}"';
|
||||
|
||||
if (str_ends_with($path, '.sql')) {
|
||||
$command = 'psql --file="${:LARAVEL_LOAD_PATH}" --host="${:LARAVEL_LOAD_HOST}" --port="${:LARAVEL_LOAD_PORT}" --username="${:LARAVEL_LOAD_USER}" --dbname="${:LARAVEL_LOAD_DATABASE}"';
|
||||
}
|
||||
|
||||
$process = $this->makeProcess($command);
|
||||
|
||||
$process->mustRun(null, array_merge($this->baseVariables($this->connection->getConfig()), [
|
||||
'LARAVEL_LOAD_PATH' => $path,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the application's migration table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getMigrationTable(): string
|
||||
{
|
||||
[$schema, $table] = $this->connection->getSchemaBuilder()->parseSchemaAndTable($this->migrationTable);
|
||||
|
||||
return $schema.'.'.$this->connection->getTablePrefix().$table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base dump command arguments for PostgreSQL as a string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function baseDumpCommand()
|
||||
{
|
||||
return 'pg_dump --no-owner --no-acl --host="${:LARAVEL_LOAD_HOST}" --port="${:LARAVEL_LOAD_PORT}" --username="${:LARAVEL_LOAD_USER}" --dbname="${:LARAVEL_LOAD_DATABASE}"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base variables for a dump / load command.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function baseVariables(array $config)
|
||||
{
|
||||
$config['host'] ??= '';
|
||||
|
||||
return [
|
||||
'LARAVEL_LOAD_HOST' => is_array($config['host']) ? $config['host'][0] : $config['host'],
|
||||
'LARAVEL_LOAD_PORT' => $config['port'] ?? '',
|
||||
'LARAVEL_LOAD_USER' => $config['username'],
|
||||
'PGPASSWORD' => $config['password'],
|
||||
'LARAVEL_LOAD_DATABASE' => $config['database'],
|
||||
];
|
||||
}
|
||||
}
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class SQLiteBuilder extends Builder
|
||||
{
|
||||
/**
|
||||
* Create a database in the schema.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function createDatabase($name)
|
||||
{
|
||||
return File::put($name, '') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop a database from the schema if the database exists.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dropDatabaseIfExists($name)
|
||||
{
|
||||
return File::exists($name)
|
||||
? File::delete($name)
|
||||
: true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given table exists.
|
||||
*
|
||||
* @param string $table
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTable($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return (bool) $this->connection->scalar(
|
||||
$this->grammar->compileTableExists($table)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tables for the database.
|
||||
*
|
||||
* @param bool $withSize
|
||||
* @return array
|
||||
*/
|
||||
public function getTables($withSize = true)
|
||||
{
|
||||
if ($withSize) {
|
||||
try {
|
||||
$withSize = $this->connection->scalar($this->grammar->compileDbstatExists());
|
||||
} catch (QueryException $e) {
|
||||
$withSize = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->connection->getPostProcessor()->processTables(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileTables($withSize))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($table)
|
||||
{
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processColumns(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileColumns($table)),
|
||||
$this->connection->scalar($this->grammar->compileSqlCreateStatement($table))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all tables from the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dropAllTables()
|
||||
{
|
||||
$database = $this->connection->getDatabaseName();
|
||||
|
||||
if ($database !== ':memory:' &&
|
||||
! str_contains($database, '?mode=memory') &&
|
||||
! str_contains($database, '&mode=memory')
|
||||
) {
|
||||
return $this->refreshDatabaseFile();
|
||||
}
|
||||
|
||||
$this->connection->select($this->grammar->compileEnableWriteableSchema());
|
||||
|
||||
$this->connection->select($this->grammar->compileDropAllTables());
|
||||
|
||||
$this->connection->select($this->grammar->compileDisableWriteableSchema());
|
||||
|
||||
$this->connection->select($this->grammar->compileRebuild());
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all views from the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dropAllViews()
|
||||
{
|
||||
$this->connection->select($this->grammar->compileEnableWriteableSchema());
|
||||
|
||||
$this->connection->select($this->grammar->compileDropAllViews());
|
||||
|
||||
$this->connection->select($this->grammar->compileDisableWriteableSchema());
|
||||
|
||||
$this->connection->select($this->grammar->compileRebuild());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the busy timeout.
|
||||
*
|
||||
* @param int $milliseconds
|
||||
* @return bool
|
||||
*/
|
||||
public function setBusyTimeout($milliseconds)
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileSetBusyTimeout($milliseconds)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the journal mode.
|
||||
*
|
||||
* @param string $mode
|
||||
* @return bool
|
||||
*/
|
||||
public function setJournalMode($mode)
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileSetJournalMode($mode)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the synchronous mode.
|
||||
*
|
||||
* @param int $mode
|
||||
* @return bool
|
||||
*/
|
||||
public function setSynchronous($mode)
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileSetSynchronous($mode)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the database file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function refreshDatabaseFile()
|
||||
{
|
||||
file_put_contents($this->connection->getDatabaseName(), '');
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
abstract class SchemaState
|
||||
{
|
||||
/**
|
||||
* The connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The filesystem instance.
|
||||
*
|
||||
* @var \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* The name of the application's migration table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $migrationTable = 'migrations';
|
||||
|
||||
/**
|
||||
* The process factory callback.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
protected $processFactory;
|
||||
|
||||
/**
|
||||
* The output callable instance.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* Create a new dumper instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param \Illuminate\Filesystem\Filesystem|null $files
|
||||
* @param callable|null $processFactory
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Connection $connection, ?Filesystem $files = null, ?callable $processFactory = null)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
|
||||
$this->files = $files ?: new Filesystem;
|
||||
|
||||
$this->processFactory = $processFactory ?: function (...$arguments) {
|
||||
return Process::fromShellCommandline(...$arguments)->setTimeout(null);
|
||||
};
|
||||
|
||||
$this->handleOutputUsing(function () {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the database's schema into a file.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
abstract public function dump(Connection $connection, $path);
|
||||
|
||||
/**
|
||||
* Load the given schema file into the database.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
abstract public function load($path);
|
||||
|
||||
/**
|
||||
* Create a new process instance.
|
||||
*
|
||||
* @param mixed ...$arguments
|
||||
* @return \Symfony\Component\Process\Process
|
||||
*/
|
||||
public function makeProcess(...$arguments)
|
||||
{
|
||||
return call_user_func($this->processFactory, ...$arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the current connection has a migration table.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasMigrationTable(): bool
|
||||
{
|
||||
return $this->connection->getSchemaBuilder()->hasTable($this->migrationTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the application's migration table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getMigrationTable(): string
|
||||
{
|
||||
return $this->connection->getTablePrefix().$this->migrationTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the name of the application's migration table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return $this
|
||||
*/
|
||||
public function withMigrationTable(string $table)
|
||||
{
|
||||
$this->migrationTable = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the callback that should be used to handle process output.
|
||||
*
|
||||
* @param callable $output
|
||||
* @return $this
|
||||
*/
|
||||
public function handleOutputUsing(callable $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class SqlServerBuilder extends Builder
|
||||
{
|
||||
/**
|
||||
* Create a database in the schema.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function createDatabase($name)
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileCreateDatabase($name, $this->connection)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop a database from the schema if the database exists.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dropDatabaseIfExists($name)
|
||||
{
|
||||
return $this->connection->statement(
|
||||
$this->grammar->compileDropDatabaseIfExists($name)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given table exists.
|
||||
*
|
||||
* @param string $table
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTable($table)
|
||||
{
|
||||
[$schema, $table] = $this->parseSchemaAndTable($table);
|
||||
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return (bool) $this->connection->scalar(
|
||||
$this->grammar->compileTableExists($schema, $table)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given view exists.
|
||||
*
|
||||
* @param string $view
|
||||
* @return bool
|
||||
*/
|
||||
public function hasView($view)
|
||||
{
|
||||
[$schema, $view] = $this->parseSchemaAndTable($view);
|
||||
|
||||
$schema ??= $this->getDefaultSchema();
|
||||
$view = $this->connection->getTablePrefix().$view;
|
||||
|
||||
foreach ($this->getViews() as $value) {
|
||||
if (strtolower($view) === strtolower($value['name'])
|
||||
&& strtolower($schema) === strtolower($value['schema'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all tables from the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dropAllTables()
|
||||
{
|
||||
$this->connection->statement($this->grammar->compileDropAllForeignKeys());
|
||||
|
||||
$this->connection->statement($this->grammar->compileDropAllTables());
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all views from the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dropAllViews()
|
||||
{
|
||||
$this->connection->statement($this->grammar->compileDropAllViews());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($table)
|
||||
{
|
||||
[$schema, $table] = $this->parseSchemaAndTable($table);
|
||||
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
$results = $this->connection->selectFromWriteConnection(
|
||||
$this->grammar->compileColumns($schema, $table)
|
||||
);
|
||||
|
||||
return $this->connection->getPostProcessor()->processColumns($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indexes for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexes($table)
|
||||
{
|
||||
[$schema, $table] = $this->parseSchemaAndTable($table);
|
||||
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processIndexes(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileIndexes($schema, $table))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign keys for a given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getForeignKeys($table)
|
||||
{
|
||||
[$schema, $table] = $this->parseSchemaAndTable($table);
|
||||
|
||||
$table = $this->connection->getTablePrefix().$table;
|
||||
|
||||
return $this->connection->getPostProcessor()->processForeignKeys(
|
||||
$this->connection->selectFromWriteConnection($this->grammar->compileForeignKeys($schema, $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.
|
||||
*
|
||||
* @param string $reference
|
||||
* @return array
|
||||
*/
|
||||
protected function parseSchemaAndTable($reference)
|
||||
{
|
||||
$parts = array_pad(explode('.', $reference, 2), -2, null);
|
||||
|
||||
if (str_contains($parts[1], '.')) {
|
||||
$database = $parts[0];
|
||||
|
||||
throw new InvalidArgumentException("Using three-part reference is not supported, you may use `Schema::connection('$database')` instead.");
|
||||
}
|
||||
|
||||
return $parts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class SqliteSchemaState extends SchemaState
|
||||
{
|
||||
/**
|
||||
* Dump the database's schema into a file.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function dump(Connection $connection, $path)
|
||||
{
|
||||
with($process = $this->makeProcess(
|
||||
$this->baseCommand().' ".schema --indent"'
|
||||
))->setTimeout(null)->mustRun(null, array_merge($this->baseVariables($this->connection->getConfig()), [
|
||||
//
|
||||
]));
|
||||
|
||||
$migrations = preg_replace('/CREATE TABLE sqlite_.+?\);[\r\n]+/is', '', $process->getOutput());
|
||||
|
||||
$this->files->put($path, $migrations.PHP_EOL);
|
||||
|
||||
if ($this->hasMigrationTable()) {
|
||||
$this->appendMigrationData($path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the migration data to the schema dump.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
protected function appendMigrationData(string $path)
|
||||
{
|
||||
with($process = $this->makeProcess(
|
||||
$this->baseCommand().' ".dump \''.$this->getMigrationTable().'\'"'
|
||||
))->mustRun(null, array_merge($this->baseVariables($this->connection->getConfig()), [
|
||||
//
|
||||
]));
|
||||
|
||||
$migrations = (new Collection(preg_split("/\r\n|\n|\r/", $process->getOutput())))
|
||||
->filter(fn ($line) => preg_match('/^\s*(--|INSERT\s)/iu', $line) === 1 && strlen($line) > 0)
|
||||
->all();
|
||||
|
||||
$this->files->append($path, implode(PHP_EOL, $migrations).PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given schema file into the database.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function load($path)
|
||||
{
|
||||
$database = $this->connection->getDatabaseName();
|
||||
|
||||
if ($database === ':memory:' ||
|
||||
str_contains($database, '?mode=memory') ||
|
||||
str_contains($database, '&mode=memory')
|
||||
) {
|
||||
$this->connection->getPdo()->exec($this->files->get($path));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$process = $this->makeProcess($this->baseCommand().' < "${:LARAVEL_LOAD_PATH}"');
|
||||
|
||||
$process->mustRun(null, array_merge($this->baseVariables($this->connection->getConfig()), [
|
||||
'LARAVEL_LOAD_PATH' => $path,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base sqlite command arguments as a string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function baseCommand()
|
||||
{
|
||||
return 'sqlite3 "${:LARAVEL_LOAD_DATABASE}"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base variables for a dump / load command.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function baseVariables(array $config)
|
||||
{
|
||||
return [
|
||||
'LARAVEL_LOAD_DATABASE' => $config['database'],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user