287 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			287 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace Illuminate\Database\Schema\Grammars;
 | 
						|
 | 
						|
use Doctrine\DBAL\Schema\AbstractSchemaManager as SchemaManager;
 | 
						|
use Doctrine\DBAL\Schema\TableDiff;
 | 
						|
use Illuminate\Database\Connection;
 | 
						|
use Illuminate\Database\Grammar as BaseGrammar;
 | 
						|
use Illuminate\Database\Query\Expression;
 | 
						|
use Illuminate\Database\Schema\Blueprint;
 | 
						|
use Illuminate\Support\Fluent;
 | 
						|
use RuntimeException;
 | 
						|
 | 
						|
abstract class Grammar extends BaseGrammar
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * 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 rename column command.
 | 
						|
     *
 | 
						|
     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
 | 
						|
     * @param  \Illuminate\Support\Fluent  $command
 | 
						|
     * @param  \Illuminate\Database\Connection  $connection
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    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
 | 
						|
     *
 | 
						|
     * @throws \RuntimeException
 | 
						|
     */
 | 
						|
    public function compileChange(Blueprint $blueprint, Fluent $command, Connection $connection)
 | 
						|
    {
 | 
						|
        return ChangeColumn::compile($this, $blueprint, $command, $connection);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 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 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 have 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\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 $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)
 | 
						|
    {
 | 
						|
        $table = $this->getTablePrefix().$blueprint->getTable();
 | 
						|
 | 
						|
        return tap(new TableDiff($table), function ($tableDiff) use ($schema, $table) {
 | 
						|
            $tableDiff->fromTable = $schema->listTableDetails($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;
 | 
						|
    }
 | 
						|
}
 |