commit 3e0acb478d22a03ced2a21e355496066dbbb0cee Author: Maxime Rault Date: Wed Apr 22 14:41:53 2015 +0200 first commit diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..062f280 --- /dev/null +++ b/README.md @@ -0,0 +1,130 @@ +# laravel-db2 + +[![Latest Stable Version](https://poser.pugx.org/cooperl/laravel-db2/v/stable)](https://packagist.org/packages/cooperl/laravel-db2) +[![Total Downloads](https://poser.pugx.org/cooperl/laravel-db2/downloads)](https://packagist.org/packages/cooperl/laravel-db2) +[![Latest Unstable Version](https://poser.pugx.org/cooperl/laravel-db2/v/unstable)](https://packagist.org/packages/cooperl/laravel-db2) +[![License](https://poser.pugx.org/cooperl/laravel-db2/license)](https://packagist.org/packages/cooperl/laravel-db2) + +laravel-db2 is a simple DB2 service provider for Laravel. +It provides DB2 Connection by extending the Illuminate Database component of the laravel framework. + +--- + +- [Installation](#installation) +- [Registering the Package](#registering-the-package) +- [Configuration](#configuration) +- [Usage](#usage) + +## Installation + +Add laravel-db2 to your composer.json file: + +``` +"require": { + "cooperl/laravel-db2": "~1.0" +} +``` + +Use [composer](http://getcomposer.org) to install this package. + +``` +$ composer update +``` + +### Registering the Package + +Add the laravel-db2 Service Provider to your config in ``app/config/app.php``: + +```php +'providers' => [ + 'Cooperl\Database\DB2\DB2ServiceProvider' +], +``` + +### Configuration + +There are two ways to configure laravel-db2. You can choose the most convenient way for you. You can put your DB2 credentials into ``app/config/database.php`` (option 1) file or use package config file which you can be generated through command line by artisan (option 2). + +#### Option 1: Configure DB2 using ``app/config/database.php`` file + +Simply add this code at the end of your ``app/config/database.php`` file: + +```php + /* + |-------------------------------------------------------------------------- + | DB2 Databases + |-------------------------------------------------------------------------- + */ + + 'odbc' => [ + 'driver' => 'odbc', + 'host' => '', + 'database' => '', + 'username' => '', + 'password' => '', + 'charset' => 'utf8', + 'ccsid' => 1208, + 'prefix' => '', + 'schema' => '', + 'i5_libl' => '', + 'i5_lib' => '', + 'i5_commit' => 0, + 'i5_naming' => 0, + 'i5_date_fmt' => 5, + 'i5_date_sep' => 0, + 'i5_decimal_sep' => 0, + 'i5_time_fmt' => 0, + 'i5_time_sep' => 0, + 'options' => [ + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_EMULATE_PREPARES => false, + PDO::ATTR_PERSISTENT => false + ] + ], + + 'ibm' => [ + 'driver' => 'ibm', + 'host' => '', + 'database' => '', + 'username' => '', + 'password' => '', + 'charset' => 'utf8', + 'ccsid' => 1208, + 'prefix' => '', + 'schema' => '', + 'i5_libl' => '', + 'i5_lib' => '', + 'i5_commit' => 0, + 'i5_naming' => 0, + 'i5_date_fmt' => 5, + 'i5_date_sep' => 0, + 'i5_decimal_sep' => 0, + 'i5_time_fmt' => 0, + 'i5_time_sep' => 0, + 'options' => [ + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_EMULATE_PREPARES => false, + PDO::ATTR_PERSISTENT => false + ] + ], + +``` +driver setting is either 'odbc' for ODBC connection or 'ibm' for pdo_ibm connection +Then if driver is 'odbc', database must be set to ODBC connection name. +if driver is 'ibm', database must be set to IBMi database name (WRKRDBDIRE). + +#### Option 2: Configure DB2 using package config file + +Run on the command line from the root of your project: + +``` +$ php artisan config:publish cooperl/laravel-db2 +``` + +Set your laravel-db2 credentials in ``app/config/packages/cooperl/laravel-db2/config.php`` +the same way as above + + +## Usage + +Consult the [Laravel framework documentation](http://laravel.com/docs). diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..528c37a --- /dev/null +++ b/composer.json @@ -0,0 +1,29 @@ +{ + "name": "cooperl/laravel-db2", + "description": "laravel-db2 is a simple DB2 service provider for Laravel. It provides DB2 Connection by extending the Illuminate Database component of the laravel framework.", + "keywords": ["laravel", "DB2", "Database", "PDO", "ODBC"], + "license": "MIT", + "authors": [ + { + "name": "Maxime Rault", + "role": "Developer" + } + ], + "require": { + "php": ">=5.4.0", + "illuminate/support": "~4.2", + "illuminate/database": "~4.2" + }, + "require-dev": { + }, + "autoload": { + "psr-4": { + "Cooperl\\Database\\DB2\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/src/Connectors/IBMConnector.php b/src/Connectors/IBMConnector.php new file mode 100644 index 0000000..e24b5ed --- /dev/null +++ b/src/Connectors/IBMConnector.php @@ -0,0 +1,34 @@ +getDsn($config); + + $options = $this->getOptions($config); + + $connection = $this->createConnection($dsn, $config, $options); + + if (isset($config['schema'])) + { + $schema = $config['schema']; + + $connection->prepare("set schema $schema")->execute(); + } + + return $connection; + } + + protected function getDsn(array $config) { + extract($config); + $dsn = "ibm:$database"; + return $dsn; + } + +} diff --git a/src/Connectors/ODBCConnector.php b/src/Connectors/ODBCConnector.php new file mode 100644 index 0000000..8275a69 --- /dev/null +++ b/src/Connectors/ODBCConnector.php @@ -0,0 +1,46 @@ +getDsn($config); + + $options = $this->getOptions($config); + + $connection = $this->createConnection($dsn, $config, $options); + + if (isset($config['schema'])) + { + $schema = $config['schema']; + + $connection->prepare("set schema $schema")->execute(); + } + + return $connection; + } + + protected function getDsn(array $config) { + extract($config); + + $dsn = "odbc:DRIVER={iSeries Access ODBC Driver};" + . "SYSTEM=$database;" + . "NAM=$i5_naming;" + . "DATABASE=$i5_lib;" + . "DBQ=$i5_libl;" + . "DFT=$i5_date_fmt;" + . "DSP=$i5_date_sep;" + . "DEC=$i5_decimal_sep;" + . "TFT=$i5_time_fmt;" + . "TSP=$i5_time_sep;" + . "CCSID=$ccsid"; + + return $dsn; + } + +} diff --git a/src/DB2Connection.php b/src/DB2Connection.php new file mode 100644 index 0000000..5a6ea84 --- /dev/null +++ b/src/DB2Connection.php @@ -0,0 +1,100 @@ +currentSchema = $this->defaultSchema = strtoupper($config['schema']); + } + + /** + * Get the name of the default schema. + * + * @return string + */ + public function getDefaultSchema() + { + return $this->defaultSchema; + } + + /** + * Reset to default the current schema. + * + * @return string + */ + public function resetCurrentSchema() + { + $this->setCurrentSchema($this->getDefaultSchema()); + } + + /** + * Set the name of the current schema. + * + * @return string + */ + public function setCurrentSchema($schema) + { + //$this->currentSchema = $schema; + $this->statement('SET SCHEMA ?', [strtoupper($schema)]); + } + + /** + * Get a schema builder instance for the connection. + * + * @return \Illuminate\Database\Schema\MySqlBuilder + */ + public function getSchemaBuilder() + { + if (is_null($this->schemaGrammar)) { $this->useDefaultSchemaGrammar(); } + + return new Builder($this); + } + + /** + * @return Query\Grammars\Grammar + */ + protected function getDefaultQueryGrammar() + { + return $this->withTablePrefix(new QueryGrammar); + } + + /** + * Default grammar for specified Schema + * @return Schema\Grammars\Grammar + */ + protected function getDefaultSchemaGrammar() + { + + return $this->withTablePrefix(new SchemaGrammar); + } + + /** + * Get the default post processor instance. + * + * @return \Illuminate\Database\Query\Processors\PostgresProcessor + */ + protected function getDefaultPostProcessor() + { + return new DB2Processor; + } + +} diff --git a/src/DB2ServiceProvider.php b/src/DB2ServiceProvider.php new file mode 100644 index 0000000..e5e385f --- /dev/null +++ b/src/DB2ServiceProvider.php @@ -0,0 +1,84 @@ +app['config']['database.connections'] = array_merge($conns, $this->app['config']['database.connections']); + + //Extend the connections with pdo_odbc and pdo_ibm drivers + foreach(Config::get('database.connections') as $conn => $config) + { + + //Only use configurations that feature a "odbc" or "ibm" driver + if(!isset($config['driver']) || !in_array($config['driver'], ['odbc', 'ibm']) ) + { + continue; + } + + //Create a connector + $this->app['db']->extend($conn, function($config) + { + switch ($config['driver']) { + case 'odbc': + $connector = new ODBCConnector(); + break; + case 'ibm': + $connector = new IBMConnector(); + break; + default: + break; + } + $db2Connection = $connector->connect($config); + return new DB2Connection($db2Connection, $config["database"], $config["prefix"], $config); + }); + + } + + } + + /** + * Get the services provided by the provider. + * + * @return array + */ + public function provides() + { + return []; + } + +} diff --git a/src/Query/Grammars/DB2Grammar.php b/src/Query/Grammars/DB2Grammar.php new file mode 100644 index 0000000..9fcdc88 --- /dev/null +++ b/src/Query/Grammars/DB2Grammar.php @@ -0,0 +1,150 @@ +compileComponents($query); + + // If an offset is present on the query, we will need to wrap the query in + // a big "ANSI" offset syntax block. This is very nasty compared to the + // other database systems but is necessary for implementing features. + if ($query->offset > 0) + { + return $this->compileAnsiOffset($query, $components); + } + + return $this->concatenate($components); + } + + /** + * Create a full ANSI offset clause for the query. + * + * @param Illuminate\Database\Query\Builder $query + * @param array $components + * @return string + */ + protected function compileAnsiOffset(Builder $query, $components) + { + // An ORDER BY clause is required to make this offset query work, so if one does + // not exist we'll just create a dummy clause to trick the database and so it + // does not complain about the queries for not having an "order by" clause. + if ( ! isset($components['orders'])) + { + $components['orders'] = 'order by 1'; + } + + unset($components['limit']); + + // We need to add the row number to the query so we can compare it to the offset + // and limit values given for the statements. So we will add an expression to + // the "select" that will give back the row numbers on each of the records. + $orderings = $components['orders']; + + $columns = (!empty($components['columns']) ? $components['columns'] . ', ': 'select'); + + $components['columns'] = $this->compileOver($orderings, $columns); + + unset($components['orders']); + + // Next we need to calculate the constraints that should be placed on the query + // to get the right offset and limit from our query but if there is no limit + // set we will just handle the offset only since that is all that matters. + $start = $query->offset + 1; + + $constraint = $this->compileRowConstraint($query); + + $sql = $this->concatenate($components); + + // We are now ready to build the final SQL query so we'll create a common table + // expression from the query and get the records with row numbers within our + // given limit and offset value that we just put on as a query constraint. + return $this->compileTableExpression($sql, $constraint); + } + + /** + * Compile the over statement for a table expression. + * + * @param string $orderings + * @return string + */ + protected function compileOver($orderings, $columns) + { + return "{$columns} row_number() over ({$orderings}) as row_num"; + } + + protected function compileRowConstraint($query) + { + $start = $query->offset + 1; + + if ($query->limit > 0) + { + $finish = $query->offset + $query->limit; + + return "between {$start} and {$finish}"; + } + + return ">= {$start}"; + } + + /** + * Compile a common table expression for a query. + * + * @param string $sql + * @param string $constraint + * @return string + */ + protected function compileTableExpression($sql, $constraint) + { + return "select * from ({$sql}) as temp_table where row_num {$constraint}"; + } + + /** + * Compile the "offset" portions of the query. + * + * @param Illuminate\Database\Query\Builder $query + * @param int $offset + * @return string + */ + protected function compileOffset(Builder $query, $offset) + { + return ''; + } + +} diff --git a/src/Query/Processors/DB2Processor.php b/src/Query/Processors/DB2Processor.php new file mode 100644 index 0000000..2c6eebf --- /dev/null +++ b/src/Query/Processors/DB2Processor.php @@ -0,0 +1,43 @@ +columnize($sequence); + } + $sql = 'select ' . $sequenceStr . ' from new table (' . $sql; + $sql .= ')'; + $results = $query->getConnection()->select($sql, $values); + if (is_array($sequence)) + { + return array_values((array) $results[0]); + } + else + { + $result = (array) $results[0]; + $id = $result[$sequenceStr]; + return is_numeric($id) ? (int) $id : $id; + } + + } + +} diff --git a/src/Schema/Blueprint.php b/src/Schema/Blueprint.php new file mode 100644 index 0000000..b8aea3f --- /dev/null +++ b/src/Schema/Blueprint.php @@ -0,0 +1,96 @@ +systemName = $systemName; + } + + /** + * Specify a label for the table. + * + * @param string $label + * @return \Illuminate\Support\Fluent + */ + public function label($label) + { + return $this->addCommand('label', compact('label')); + } + + /** + * Add a new index command to the blueprint. + * + * @param string $type + * @param string|array $columns + * @param string $index + * @return \Illuminate\Support\Fluent + */ + protected function indexCommand($type, $columns, $index) + { + $columns = (array) $columns; + + switch ($type) { + case 'index': + $indexSystem = false; + if (!is_null($index)) + { + $indexSystem = $index; + } + $index = $this->createIndexName($type, $columns); + return $this->addCommand($type, compact('index', 'indexSystem', 'columns')); + break; + + default: + break; + } + + // If no name was specified for this index, we will create one using a basic + // convention of the table name, followed by the columns, followed by an + // index type, such as primary or index, which makes the index unique. + if (is_null($index)) + { + $index = $this->createIndexName($type, $columns); + } + + return $this->addCommand($type, compact('index', 'columns')); + } + + /** + * Create a new boolean column on the table. + * + * @param string $column + * @return \Illuminate\Support\Fluent + */ + public function boolean($column) + { + $prefix = $this->table; + // Aucune utilité d'avoir le nom du schéma dans le préfixe de la contrainte check pour le type booléen + $schemaTable = explode(".", $this->table); + if (count($schemaTable) > 1) + { + $prefix = $schemaTable[1]; + } + return $this->addColumn('boolean', $column, ['prefix' => $prefix]); + } + + /** + * Create a new numeric column on the table. + * + * @param string $column + * @param int $total + * @param int $places + * @return \Illuminate\Support\Fluent + */ + public function numeric($column, $total = 8, $places = 2) + { + return $this->addColumn('numeric', $column, compact('total', 'places')); + } + +} \ No newline at end of file diff --git a/src/Schema/Builder.php b/src/Schema/Builder.php new file mode 100644 index 0000000..cedc7e8 --- /dev/null +++ b/src/Schema/Builder.php @@ -0,0 +1,89 @@ +grammar->compileTableExists(); + + $schemaTable = explode(".", $table); + if (count($schemaTable) > 1) + { + $schema = $schemaTable[0]; + $table = $this->connection->getTablePrefix().$schemaTable[1]; + } + else + { + $schema = $this->connection->getDefaultSchema(); + $table = $this->connection->getTablePrefix().$table; + } + + return count($this->connection->select($sql, [$schema, $table])) > 0; + } + + /** + * Get the column listing for a given table. + * + * @param string $table + * @return array + */ + public function getColumnListing($table) + { + $sql = $this->grammar->compileColumnExists(); + + $database = $this->connection->getDatabaseName(); + + $table = $this->connection->getTablePrefix().$table; + + $results = $this->connection->select($sql, [$database, $table]); + + return $this->connection->getPostProcessor()->processColumnListing($results); + } + + /** + * Execute the blueprint to build / modify the table. + * + * @param \Cooperl\Database\DB2\Schema\Blueprint $blueprint + * @return void + */ + protected function build(Blueprint $blueprint) + { + $schemaTable = explode(".", $blueprint->getTable()); + if (count($schemaTable) > 1) + { + $this->connection->setCurrentSchema($schemaTable[0]); + } + + $blueprint->build($this->connection, $this->grammar); + + $this->connection->resetCurrentSchema(); + } + + /** + * Create a new command set with a Closure. + * + * @param string $table + * @param \Closure $callback + * @return \Cooperl\Database\DB2\Schema\Blueprint + */ + protected function createBlueprint($table, Closure $callback = null) + { + if (isset($this->resolver)) + { + return call_user_func($this->resolver, $table, $callback); + } + + return new \Cooperl\Database\DB2\Schema\Blueprint($table, $callback); + } + +} diff --git a/src/Schema/Grammars/DB2Grammar.php b/src/Schema/Grammars/DB2Grammar.php new file mode 100644 index 0000000..c110d58 --- /dev/null +++ b/src/Schema/Grammars/DB2Grammar.php @@ -0,0 +1,777 @@ +getColumns($blueprint)); + + $sql = 'create table '.$this->wrapTable($blueprint); + + if (isset($blueprint->systemName)) + { + $sql .= ' for system name '.$blueprint->systemName; + } + + $sql .= " ($columns)"; + + return $sql; + } + + /** + * Compile a label command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @param \Illuminate\Database\Connection $connection + * @return string + */ + public function compileLabel(Blueprint $blueprint, Fluent $command, Connection $connection) + { + return 'label on table '.$this->wrapTable($blueprint).' is \'' . $command->label . '\''; + } + + /** + * Compile the blueprint's column definitions. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @return array + */ + protected function getColumns(Blueprint $blueprint) + { + $columns = []; + + foreach ($blueprint->getColumns() 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); + $sql = $this->addPreModifiers($this->wrap($column), $blueprint, $column); + $sql .= ' '.$this->getType($column); + + $columns[] = $this->addModifiers($sql, $blueprint, $column); + } + + return $columns; + } + + /** + * 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 addPreModifiers($sql, Blueprint $blueprint, Fluent $column) + { + foreach ($this->preModifiers as $preModifier) + { + if (method_exists($this, $method = "modify{$preModifier}")) + { + $sql .= $this->{$method}($blueprint, $column); + } + } + + return $sql; + } + + /** + * Compile a create table command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileAdd(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint); + + $columns = $this->prefixArray('add', $this->getColumns($blueprint)); + + foreach ($columns as $column) + { + $statements[] = 'alter table '.$table.' '.$column; + } + + return $statements; + } + + /** + * Compile a primary key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compilePrimary(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint); + + $columns = $this->columnize($command->columns); + + // Aucune utilité d'avoir le nom du schéma dans le nom de la contrainte Primary + $schemaTable = explode(".", $table); + if (count($schemaTable) > 1) + { + $command->index = str_replace($schemaTable[0]."_", "", $command->index); + } + + return "alter table {$table} add constraint {$command->index} primary key ({$columns})"; + } + + /** + * 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) + { + $table = $this->wrapTable($blueprint); + + $on = $this->wrapTable($command->on); + + // 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. + $columns = $this->columnize($command->columns); + + $onColumns = $this->columnize((array) $command->references); + + // Aucune utilité d'avoir le nom du schéma dans le nom de la contrainte Foreign + $schemaTable = explode(".", $table); + if (count($schemaTable) > 1) + { + $command->index = str_replace($schemaTable[0]."_", "", $command->index); + } + + $sql = "alter table {$table} add constraint {$command->index} "; + + $sql .= "foreign key ({$columns}) references {$on} ({$onColumns})"; + + // 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 unique key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileUnique(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint); + + $columns = $this->columnize($command->columns); + + // Aucune utilité d'avoir le nom du schéma dans le nom de la contrainte Unique + $schemaTable = explode(".", $table); + if (count($schemaTable) > 1) + { + $command->index = str_replace($schemaTable[0]."_", "", $command->index); + } + + return "alter table {$table} add constraint {$command->index} unique({$columns})"; + } + + /** + * Compile a plain index key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileIndex(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint); + + $columns = $this->columnize($command->columns); + + // Aucune utilité d'avoir le nom du schéma dans le nom de la contrainte Index + $schemaTable = explode(".", $table); + if (count($schemaTable) > 1) + { + $command->index = str_replace($schemaTable[0]."_", "", $command->index); + } + + $sql = "create index {$command->index}"; + if ($command->indexSystem) + { + $sql .= " for system name {$command->indexSystem}"; + } + $sql .= " on {$table}($columns)"; + + //return "create index {$command->index} for system name on {$table}($columns)"; + return $sql; + } + + /** + * Compile a drop table command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDrop(Blueprint $blueprint, Fluent $command) + { + return 'drop table '.$this->wrapTable($blueprint); + } + + /** + * Compile a drop table (if exists) command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropIfExists(Blueprint $blueprint, Fluent $command) + { + return 'drop table if exists '.$this->wrapTable($blueprint); + } + + /** + * Compile a drop column command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropColumn(Blueprint $blueprint, Fluent $command) + { + $columns = $this->prefixArray('drop', $this->wrapArray($command->columns)); + + $table = $this->wrapTable($blueprint); + + return 'alter table '.$table.' '.implode(', ', $columns); + } + + /** + * Compile a drop primary key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropPrimary(Blueprint $blueprint, Fluent $command) + { + return 'alter table '.$this->wrapTable($blueprint).' drop primary key'; + } + + /** + * Compile a drop unique key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropUnique(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint); + + // Aucune utilité d'avoir le nom du schéma dans le nom de la contrainte Unique + $schemaTable = explode(".", $table); + if (count($schemaTable) > 1) + { + $command->index = str_replace($schemaTable[0]."_", "", $command->index); + } + + return "alter table {$table} drop index {$command->index}"; + } + + /** + * Compile a drop index command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropIndex(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint); + + // Aucune utilité d'avoir le nom du schéma dans le nom de la contrainte Index + $schemaTable = explode(".", $table); + if (count($schemaTable) > 1) + { + $command->index = str_replace($schemaTable[0]."_", "", $command->index); + } + + return "alter table {$table} drop index {$command->index}"; + } + + /** + * 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) + { + $table = $this->wrapTable($blueprint); + + // Aucune utilité d'avoir le nom du schéma dans le nom de la contrainte Foreign + $schemaTable = explode(".", $table); + if (count($schemaTable) > 1) + { + $command->index = str_replace($schemaTable[0]."_", "", $command->index); + } + + return "alter table {$table} drop foreign key {$command->index}"; + } + + /** + * Compile a rename table command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileRename(Blueprint $blueprint, Fluent $command) + { + $from = $this->wrapTable($blueprint); + + return "rename table {$from} to ".$this->wrapTable($command->to); + } + + /** + * Create the column definition for a char type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeChar(Fluent $column) + { + return "char({$column->length})"; + } + + /** + * Create the column definition for a string type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeString(Fluent $column) + { + return "varchar({$column->length})"; + } + + /** + * Create the column definition for a text type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeText(Fluent $column) + { + return 'text'; + } + + /** + * Create the column definition for a medium text type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeMediumText(Fluent $column) + { + return 'mediumtext'; + } + + /** + * Create the column definition for a long text type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeLongText(Fluent $column) + { + return 'longtext'; + } + + /** + * Create the column definition for a big integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeBigInteger(Fluent $column) + { + return 'bigint'; + } + + /** + * Create the column definition for a integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeInteger(Fluent $column) + { + return 'int'; + } + + /** + * Create the column definition for a small integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeSmallInteger(Fluent $column) + { + return 'smallint'; + } + + /** + * Create the column definition for a numeric type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeNumeric(Fluent $column) + { + return "numeric({$column->total}, {$column->places})"; + } + + /** + * Create the column definition for a float type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeFloat(Fluent $column) + { + return "float({$column->total}, {$column->places})"; + } + + /** + * Create the column definition for a double type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDouble(Fluent $column) + { + if ($column->total && $column->places) + { + return "double({$column->total}, {$column->places})"; + } + else + { + return 'double'; + } + } + + /** + * Create the column definition for a decimal type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDecimal(Fluent $column) + { + return "decimal({$column->total}, {$column->places})"; + } + + /** + * Create the column definition for a boolean type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeBoolean(Fluent $column) + { + return 'smallint constraint '.$column->type.'_'.$column->prefix.'_'.$column->name.' check('.$column->name.' in(0,1))'.(is_null($column->default) ? ' default 0' : ''); + } + + /** + * Create the column definition for an enum type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeEnum(Fluent $column) + { + return "enum('".implode("', '", $column->allowed)."')"; + } + + /** + * Create the column definition for a date type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDate(Fluent $column) + { + if ( ! $column->nullable) + return 'date default current_date'; + + return 'date'; + } + + /** + * Create the column definition for a date-time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDateTime(Fluent $column) + { + return 'datetime'; + } + + /** + * Create the column definition for a time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTime(Fluent $column) + { + if ( ! $column->nullable) + return 'time default current_time'; + + return 'time'; + } + + /** + * Create the column definition for a timestamp type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTimestamp(Fluent $column) + { + if ( ! $column->nullable) + return 'timestamp default current_timestamp'; + + return 'timestamp'; + } + + /** + * Create the column definition for a binary type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeBinary(Fluent $column) + { + return 'blob'; + } + + /** + * Get the SQL for a nullable column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyNullable(Blueprint $blueprint, Fluent $column) + { + return $column->nullable ? '' : ' not null'; + } + + /** + * Get the SQL for a default column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyDefault(Blueprint $blueprint, Fluent $column) + { + if ( ! is_null($column->default)) + { + return " default ".$this->getDefaultValue($column->default); + } + } + + /** + * Get the SQL for an auto-increment column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyIncrement(Blueprint $blueprint, Fluent $column) + { + if (in_array($column->type, $this->serials) && $column->autoIncrement) + { + return ' as identity'; + } + } + + + /** + * Get the SQL for an "before" column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyBefore(Blueprint $blueprint, Fluent $column) + { + if ( ! is_null($column->before)) + { + return ' before '.$this->wrap($column->before); + } + } + + /** + * Get the SQL for an "for column" column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyForColumn(Blueprint $blueprint, Fluent $column) + { + if ( ! is_null($column->forColumn)) + { + return ' for column '.$this->wrap($column->forColumn); + } + } + + /** + * Get the SQL for a "generated" column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyGenerated(Blueprint $blueprint, Fluent $column) + { + if ( ! is_null($column->generated)) + { + return ' generated '.($column->generated === true ? 'always' : $this->wrap($column->generated)); + } + } + + /** + * Get the SQL for a "startWith" column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyStartWith(Blueprint $blueprint, Fluent $column) + { + if ( ! is_null($column->startWith)) + { + return ' (start with '.$column->startWith.')'; + } + } + + /** + * Get the SQL for an "implicitly hidden" column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyImplicitlyHidden(Blueprint $blueprint, Fluent $column) + { + if ( ! is_null($column->implicitlyHidden)) + { + return ' implicitly hidden'; + } + } + + /** + * 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 + || is_bool($value) + || is_numeric($value)) return $value; + + return "'".strval($value)."'"; + } + +} diff --git a/src/config/config.php b/src/config/config.php new file mode 100644 index 0000000..36d55da --- /dev/null +++ b/src/config/config.php @@ -0,0 +1,118 @@ + [ + + 'odbc' => [ + 'driver' => 'odbc', + 'host' => '', + 'database' => '', + 'username' => '', + 'password' => '', + 'charset' => 'utf8', + 'ccsid' => 1208, + 'prefix' => '', + 'schema' => '', + 'i5_libl' => '', + 'i5_lib' => '', + 'i5_commit' => 0, + 'i5_naming' => 0, + 'i5_date_fmt' => 5, + 'i5_date_sep' => 0, + 'i5_decimal_sep' => 0, + 'i5_time_fmt' => 0, + 'i5_time_sep' => 0, + 'options' => [ + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_EMULATE_PREPARES => false, + PDO::ATTR_PERSISTENT => false + ] + ], + + 'ibm' => [ + 'driver' => 'ibm', + 'host' => '', + 'database' => '', + 'username' => '', + 'password' => '', + 'charset' => 'utf8', + 'ccsid' => 1208, + 'prefix' => '', + 'schema' => '', + 'i5_libl' => '', + 'i5_lib' => '', + 'i5_commit' => 0, + 'i5_naming' => 0, + 'i5_date_fmt' => 5, + 'i5_date_sep' => 0, + 'i5_decimal_sep' => 0, + 'i5_time_fmt' => 0, + 'i5_time_sep' => 0, + 'options' => [ + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_EMULATE_PREPARES => false, + PDO::ATTR_PERSISTENT => false + ] + ], + + ] + +];