First Commit

This commit is contained in:
marco
2026-09-01 10:46:29 -03:00
commit bf96b77e9c
10000 changed files with 3508600 additions and 0 deletions
+238
View File
@@ -0,0 +1,238 @@
<?php
namespace Illuminate\Database\Schema\Grammars;
use Doctrine\DBAL\Schema\AbstractSchemaManager as SchemaManager;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Type;
use Illuminate\Database\Connection;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Fluent;
use RuntimeException;
class ChangeColumn
{
/**
* Compile a change column command into a series of SQL statements.
*
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $command
* @param \Illuminate\Database\Connection $connection
* @return array
*
* @throws \RuntimeException
*/
public static function compile($grammar, Blueprint $blueprint, Fluent $command, Connection $connection)
{
if (! $connection->isDoctrineAvailable()) {
throw new RuntimeException(sprintf(
'Changing columns for table "%s" requires Doctrine DBAL. Please install the doctrine/dbal package.',
$blueprint->getTable()
));
}
$schema = $connection->getDoctrineSchemaManager();
$databasePlatform = $connection->getDoctrineConnection()->getDatabasePlatform();
$databasePlatform->registerDoctrineTypeMapping('enum', 'string');
$tableDiff = static::getChangedDiff(
$grammar, $blueprint, $schema
);
if (! $tableDiff->isEmpty()) {
return (array) $databasePlatform->getAlterTableSQL($tableDiff);
}
return [];
}
/**
* Get the Doctrine table difference for the given changes.
*
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Doctrine\DBAL\Schema\AbstractSchemaManager $schema
* @return \Doctrine\DBAL\Schema\TableDiff
*/
protected static function getChangedDiff($grammar, Blueprint $blueprint, SchemaManager $schema)
{
$current = $schema->introspectTable($grammar->getTablePrefix().$blueprint->getTable());
return $schema->createComparator()->compareTables(
$current, static::getTableWithColumnChanges($blueprint, $current)
);
}
/**
* Get a copy of the given Doctrine table after making the column changes.
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Doctrine\DBAL\Schema\Table $table
* @return \Doctrine\DBAL\Schema\Table
*/
protected static function getTableWithColumnChanges(Blueprint $blueprint, Table $table)
{
$table = clone $table;
foreach ($blueprint->getChangedColumns() as $fluent) {
$column = static::getDoctrineColumn($table, $fluent);
// Here we will spin through each fluent column definition and map it to the proper
// Doctrine column definitions - which is necessary because Laravel and Doctrine
// use some different terminology for various column attributes on the tables.
foreach ($fluent->getAttributes() as $key => $value) {
if (! is_null($option = static::mapFluentOptionToDoctrine($key))) {
if (method_exists($column, $method = 'set'.ucfirst($option))) {
$column->{$method}(static::mapFluentValueToDoctrine($option, $value));
continue;
}
$column->setPlatformOption($option, static::mapFluentValueToDoctrine($option, $value));
}
}
}
return $table;
}
/**
* Get the Doctrine column instance for a column change.
*
* @param \Doctrine\DBAL\Schema\Table $table
* @param \Illuminate\Support\Fluent $fluent
* @return \Doctrine\DBAL\Schema\Column
*/
protected static function getDoctrineColumn(Table $table, Fluent $fluent)
{
return $table->modifyColumn(
$fluent['name'], static::getDoctrineColumnChangeOptions($fluent)
)->getColumn($fluent['name']);
}
/**
* Get the Doctrine column change options.
*
* @param \Illuminate\Support\Fluent $fluent
* @return array
*/
protected static function getDoctrineColumnChangeOptions(Fluent $fluent)
{
$options = ['type' => static::getDoctrineColumnType($fluent['type'])];
if (! in_array($fluent['type'], ['smallint', 'integer', 'bigint'])) {
$options['autoincrement'] = false;
}
if (in_array($fluent['type'], ['tinyText', 'text', 'mediumText', 'longText'])) {
$options['length'] = static::calculateDoctrineTextLength($fluent['type']);
}
if ($fluent['type'] === 'char') {
$options['fixed'] = true;
}
if (static::doesntNeedCharacterOptions($fluent['type'])) {
$options['customSchemaOptions'] = [
'collation' => '',
'charset' => '',
];
}
return $options;
}
/**
* Get the doctrine column type.
*
* @param string $type
* @return \Doctrine\DBAL\Types\Type
*/
protected static function getDoctrineColumnType($type)
{
$type = strtolower($type);
return Type::getType(match ($type) {
'biginteger' => 'bigint',
'smallinteger' => 'smallint',
'tinytext', 'mediumtext', 'longtext' => 'text',
'binary' => 'blob',
'uuid' => 'guid',
'char' => 'string',
'double' => 'float',
default => $type,
});
}
/**
* Calculate the proper column length to force the Doctrine text type.
*
* @param string $type
* @return int
*/
protected static function calculateDoctrineTextLength($type)
{
return match ($type) {
'tinyText' => 1,
'mediumText' => 65535 + 1,
'longText' => 16777215 + 1,
default => 255 + 1,
};
}
/**
* Determine if the given type does not need character / collation options.
*
* @param string $type
* @return bool
*/
protected static function doesntNeedCharacterOptions($type)
{
return in_array($type, [
'bigInteger',
'binary',
'boolean',
'date',
'dateTime',
'decimal',
'double',
'float',
'integer',
'json',
'mediumInteger',
'smallInteger',
'time',
'timestamp',
'tinyInteger',
]);
}
/**
* Get the matching Doctrine option for a given Fluent attribute name.
*
* @param string $attribute
* @return string|null
*/
protected static function mapFluentOptionToDoctrine($attribute)
{
return match ($attribute) {
'type', 'name' => null,
'nullable' => 'notnull',
'total' => 'precision',
'places' => 'scale',
default => $attribute,
};
}
/**
* Get the matching Doctrine value for a given Fluent attribute.
*
* @param string $option
* @param mixed $value
* @return mixed
*/
protected static function mapFluentValueToDoctrine($option, $value)
{
return $option === 'notnull' ? ! $value : $value;
}
}
+357
View File
@@ -0,0 +1,357 @@
<?php
namespace Illuminate\Database\Schema\Grammars;
use BackedEnum;
use Doctrine\DBAL\Schema\AbstractSchemaManager as SchemaManager;
use Doctrine\DBAL\Schema\TableDiff;
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 RenameColumn::compile($this, $blueprint, $command, $connection);
}
/**
* 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)
{
return ChangeColumn::compile($this, $blueprint, $command, $connection);
}
/**
* 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 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) {
// 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);
$columns[] = $this->addModifiers($sql, $blueprint, $column);
}
return $columns;
}
/**
* 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.');
}
/**
* 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 primary key command 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;
});
}
/**
* 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
* @param bool $prefixAlias
* @return string
*/
public function wrap($value, $prefixAlias = false)
{
return parent::wrap(
$value instanceof Fluent ? $value->name : $value, $prefixAlias
);
}
/**
* 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."'";
}
/**
* Create an empty Doctrine DBAL TableDiff from the Blueprint.
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Doctrine\DBAL\Schema\AbstractSchemaManager $schema
* @return \Doctrine\DBAL\Schema\TableDiff
*/
public function getDoctrineTableDiff(Blueprint $blueprint, SchemaManager $schema)
{
$tableName = $this->getTablePrefix().$blueprint->getTable();
$table = $schema->introspectTable($tableName);
return new TableDiff(tableName: $tableName, fromTable: $table);
}
/**
* 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;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+84
View File
@@ -0,0 +1,84 @@
<?php
namespace Illuminate\Database\Schema\Grammars;
use Doctrine\DBAL\Schema\AbstractSchemaManager as SchemaManager;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\TableDiff;
use Illuminate\Database\Connection;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Fluent;
class RenameColumn
{
/**
* Compile a rename column command.
*
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $command
* @param \Illuminate\Database\Connection $connection
* @return array
*/
public static function compile(Grammar $grammar, Blueprint $blueprint, Fluent $command, Connection $connection)
{
$schema = $connection->getDoctrineSchemaManager();
$databasePlatform = $connection->getDoctrineConnection()->getDatabasePlatform();
$databasePlatform->registerDoctrineTypeMapping('enum', 'string');
$column = $connection->getDoctrineColumn(
$grammar->getTablePrefix().$blueprint->getTable(), $command->from
);
return (array) $databasePlatform->getAlterTableSQL(static::getRenamedDiff(
$grammar, $blueprint, $command, $column, $schema
));
}
/**
* Get a new column instance with the new column name.
*
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $command
* @param \Doctrine\DBAL\Schema\Column $column
* @param \Doctrine\DBAL\Schema\AbstractSchemaManager $schema
* @return \Doctrine\DBAL\Schema\TableDiff
*/
protected static function getRenamedDiff(Grammar $grammar, Blueprint $blueprint, Fluent $command, Column $column, SchemaManager $schema)
{
return static::setRenamedColumns(
$grammar->getDoctrineTableDiff($blueprint, $schema), $command, $column
);
}
/**
* Set the renamed columns on the table diff.
*
* @param \Doctrine\DBAL\Schema\TableDiff $tableDiff
* @param \Illuminate\Support\Fluent $command
* @param \Doctrine\DBAL\Schema\Column $column
* @return \Doctrine\DBAL\Schema\TableDiff
*/
protected static function setRenamedColumns(TableDiff $tableDiff, Fluent $command, Column $column)
{
$tableDiff->renamedColumns = [
$command->from => new Column($command->to, $column->getType(), self::getWritableColumnOptions($column)),
];
return $tableDiff;
}
/**
* Get the writable column options.
*
* @param \Doctrine\DBAL\Schema\Column $column
* @return array
*/
private static function getWritableColumnOptions(Column $column)
{
return array_filter($column->toArray(), function (string $name) use ($column) {
return method_exists($column, 'set'.$name);
}, ARRAY_FILTER_USE_KEY);
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff