add dropColumn schema migration feature

This commit is contained in:
Maxime Rault 2019-07-16 09:42:20 +02:00
parent c3cc4c2805
commit c5aa87d9a3
4 changed files with 171 additions and 20 deletions

View File

@ -2,15 +2,16 @@
namespace Cooperl\Database\DB2; namespace Cooperl\Database\DB2;
use Cooperl\Database\DB2\Query\Processors\DB2ZOSProcessor;
use PDO; use PDO;
use Illuminate\Database\Connection; use Illuminate\Database\Connection;
use Cooperl\Database\DB2\Schema\Builder; use Cooperl\Database\DB2\Schema\Builder;
use Cooperl\Database\DB2\Query\Processors\DB2Processor; use Cooperl\Database\DB2\Query\Processors\DB2Processor;
use Cooperl\Database\DB2\Query\Processors\DB2ZOSProcessor;
use Cooperl\Database\DB2\Query\Grammars\DB2Grammar as QueryGrammar; use Cooperl\Database\DB2\Query\Grammars\DB2Grammar as QueryGrammar;
use Cooperl\Database\DB2\Schema\Grammars\DB2Grammar as SchemaGrammar; use Cooperl\Database\DB2\Schema\Grammars\DB2Grammar as SchemaGrammar;
use Cooperl\Database\DB2\Schema\Grammars\DB2ExpressCGrammar;
/** /**
* Class DB2Connection * Class DB2Connection
@ -67,14 +68,25 @@ class DB2Connection extends Connection
*/ */
public function setCurrentSchema($schema) public function setCurrentSchema($schema)
{ {
//$this->currentSchema = $schema;
$this->statement('SET SCHEMA ?', [strtoupper($schema)]); $this->statement('SET SCHEMA ?', [strtoupper($schema)]);
} }
/**
* Execute a system command on IBMi.
*
* @param $command
*
* @return string
*/
public function executeCommand($command)
{
$this->statement('CALL QSYS2.QCMDEXC(?)', [$command]);
}
/** /**
* Get a schema builder instance for the connection. * Get a schema builder instance for the connection.
* *
* @return \Illuminate\Database\Schema\MySqlBuilder * @return \Cooperl\Database\DB2\Schema\Builder
*/ */
public function getSchemaBuilder() public function getSchemaBuilder()
{ {
@ -121,7 +133,7 @@ class DB2Connection extends Connection
/** /**
* Get the default post processor instance. * Get the default post processor instance.
* *
* @return \Illuminate\Database\Query\Processors\PostgresProcessor * @return \Cooperl\Database\DB2\Query\Processors\DB2Processor|\Cooperl\Database\DB2\Query\Processors\DB2ZOSProcessor
*/ */
protected function getDefaultPostProcessor() protected function getDefaultPostProcessor()
{ {

View File

@ -104,7 +104,7 @@ class DB2Grammar extends Grammar
} }
$components['columns'] = $this->compileOver($orderings, $columns); $components['columns'] = $this->compileOver($orderings, $columns);
// if there are bindings in the order, we need to move them to the select since we are moving the parameter // if there are bindings in the order, we need to move them to the select since we are moving the parameter
// markers there with the OVER statement // markers there with the OVER statement
if(isset($query->getRawBindings()['order'])){ if(isset($query->getRawBindings()['order'])){
@ -198,7 +198,7 @@ class DB2Grammar extends Grammar
$existsQuery->columns = []; $existsQuery->columns = [];
return $this->compileSelect($existsQuery->selectRaw('1')->limit(1)); return $this->compileSelect($existsQuery->selectRaw('1 exists')->limit(1));
} }
/** /**

View File

@ -2,6 +2,9 @@
namespace Cooperl\Database\DB2\Schema; namespace Cooperl\Database\DB2\Schema;
use Illuminate\Database\Connection;
use Illuminate\Database\Schema\Grammars\Grammar;
/** /**
* Class Blueprint * Class Blueprint
* *
@ -10,27 +13,62 @@ namespace Cooperl\Database\DB2\Schema;
class Blueprint extends \Illuminate\Database\Schema\Blueprint class Blueprint extends \Illuminate\Database\Schema\Blueprint
{ {
public function synchro($index, $masterizable = false) /**
* The sequence number of reply list entries.
*
* @var int
*/
private $replyListSequenceNumber;
/**
* Get the sequence number of reply list entries.
*
* @return int
*/
public function getReplyListSequenceNumber()
{ {
return $this->replyListSequenceNumber;
$this->string('id_sync', 20)
->index($index);
$this->string('hashcode', 32);
if (true === $masterizable) {
$this->boolean('data_master')
->default(true);
}
} }
/** /**
* @param string $index * Set the sequence number of reply list entries.
*
* @param int $replyListSequenceNumber
* @return void
*/ */
public function dropSynchro($index) public function setReplyListSequenceNumber(int $replyListSequenceNumber)
{ {
$this->dropColumn('id_sync', 'hashcode'); return $this->replyListSequenceNumber = $replyListSequenceNumber;
$this->dropIndex($index);
} }
/**
* Get the raw SQL statements for the blueprint.
*
* @param \Illuminate\Database\Connection $connection
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
* @return array
*/
public function toSql(Connection $connection, Grammar $grammar)
{
$this->addReplyListEntryCommands($connection);
return parent::toSql($connection, $grammar);
}
/**
* Add the commands that are necessary to DROP and Rename statements on IBMi.
*
* @param \Illuminate\Database\Connection $connection
* @return void
*/
protected function addReplyListEntryCommands(Connection $connection)
{
if ($this->commandsNamed(['dropColumn', 'renameColumn'])->count() > 0) {
array_unshift($this->commands, $this->createCommand('addReplyListEntry'), $this->createCommand('changeJob'));
array_push($this->commands, $this->createCommand('removeReplyListEntry'));
}
}
/** /**
* Specify a system name for the table. * Specify a system name for the table.
* *
@ -124,4 +162,26 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
{ {
return $this->addColumn('numeric', $column, compact('total', 'places')); return $this->addColumn('numeric', $column, compact('total', 'places'));
} }
public function synchro($index, $masterizable = false)
{
$this->string('id_sync', 20)
->index($index);
$this->string('hashcode', 32);
if (true === $masterizable) {
$this->boolean('data_master')
->default(true);
}
}
/**
* @param string $index
*/
public function dropSynchro($index)
{
$this->dropColumn('id_sync', 'hashcode');
$this->dropIndex($index);
}
} }

View File

@ -831,4 +831,83 @@ class DB2Grammar extends Grammar
return "'" . strval($value) . "'"; return "'" . strval($value) . "'";
} }
/**
* Compile a executeCommand command.
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $command
*
* @return string
*/
private function compileExecuteCommand(Blueprint $blueprint, Fluent $command)
{
return "CALL QSYS2.QCMDEXC('" . $command->command . "')";
}
/**
* Compile an addReplyListEntry command.
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $command
* @param \Illuminate\Database\Connection $connection
*
* @return string
*/
public function compileAddReplyListEntry(Blueprint $blueprint, Fluent $command, Connection $connection)
{
$sequenceNumberQuery = <<<EOT
with reply_list_info(sequence_number) as (
values(1)
union all
select sequence_number + 1
from reply_list_info
where sequence_number + 1 between 2 and 9999
)
select min(sequence_number) sequence_number
from reply_list_info
where not exists (
select 1
from qsys2.reply_list_info rli
where rli.sequence_number = reply_list_info.sequence_number
)
EOT;
$blueprint->setReplyListSequenceNumber($sequenceNumber = $connection->selectOne($sequenceNumberQuery)->sequence_number);
$command->command = "ADDRPYLE SEQNBR($sequenceNumber) MSGID(CPA32B2) RPY(''I'')";
return $this->compileExecuteCommand($blueprint, $command);
}
/**
* Compile a removeReplyListEntry command.
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $command
*
* @return string
*/
public function compileRemoveReplyListEntry(Blueprint $blueprint, Fluent $command)
{
$sequenceNumber = $blueprint->getReplyListSequenceNumber();
$command->command = "RMVRPYLE SEQNBR($sequenceNumber)";
return $this->compileExecuteCommand($blueprint, $command);
}
/**
* Compile a changeJob command.
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $command
*
* @return string
*/
public function compileChangeJob(Blueprint $blueprint, Fluent $command)
{
$command->command = 'CHGJOB INQMSGRPY(*SYSRPYL)';
return $this->compileExecuteCommand($blueprint, $command);
}
} }