diff --git a/.gitignore b/.gitignore index fa2b677..477fa56 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .DS_Store .*.sw? .idea +/nbproject \ No newline at end of file diff --git a/README.md b/README.md index cbb08db..35128b7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# laravel-firebird +laravel-firebird +================ To use this package: @@ -11,27 +12,30 @@ Mariuz's Blog has a very good step by step on this: http://mapopa.blogspot.com/2009/04/php5-and-firebird-pdo-on-ubuntu-hardy.html Install using composer: -```json -composer require jacquestvanzuydam/laravel-firebird -``` -**For Laravel 5.1.* support, please look at the [5.1-support](https://github.com/jacquestvanzuydam/laravel-firebird/tree/5.1-support) branch.** - -**For Laravel 5.2.* support, please look at the [5.2-sup](https://github.com/jacquestvanzuydam/laravel-firebird/tree/5.2-sup) branch.** - -**For Laravel 5.3.* support, pleast look at the [5.3-support](https://github.com/jacquestvanzuydam/laravel-firebird/tree/5.3-support) branch.** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ json +composer require sim1984/laravel-firebird +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Update the `app/config/app.php`, add the service provider: -```json + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ json 'Firebird\FirebirdServiceProvider'. -``` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can remove the original DatabaseServiceProvider, as the original connection factory has also been extended. +For Laravel 5.7 and later: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ php +Firebird\FirebirdServiceProvider::class, +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can remove the original DatabaseServiceProvider, as the original connection +factory has also been extended. Declare your connection in the database config, using 'firebird' as the -connecion type. -Other keys that are needed: -```php +connecion type. Other keys that are needed: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ php 'firebird' => [ 'driver' => 'firebird', 'host' => env('DB_HOST', 'localhost'), @@ -39,17 +43,112 @@ Other keys that are needed: 'username' => env('DB_USERNAME', 'sysdba'), 'password' => env('DB_PASSWORD', 'masterkey'), 'charset' => env('DB_CHARSET', 'UTF8'), + 'role' => 'RDB$ADMIN', + 'engine_version' => '3.0.4', ], -``` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ And add to your .env -``` + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DB_CHARSET=UTF8 -``` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If necessary, change the UTF8 to any other charset -This package is still in it's infancy and I wouldn't yet recommend using -it for large projects, or without backing up your database regularly. +This package is a branch jacquestvanzuydam/laravel-firebird package and extends +its functionality. Tested on Laravel-5.7. + +Added the following features: + +- Added support for direct control sequences in + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ php + // CREATE SEQUENCE "seq_users_id" + Schema::createSequence('seq_users_id'); + + // ALTER SEQUENCE "seq_users_id" RESTART WITH 10 INCREMENT BY 5 + Schema::sequence('seq_users_id', function (SequenceBlueprint $sequence) { + $sequence->increment(5); + $sequence->restart(10); + }); + + // DROP SEQUENCE "seq_users_id" + Schema::dropSequence('seq_users_id'); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- The implementation of auto-increment columns in two ways: + +- through the automatic generation of sequences and before insert trigger + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ php + // CREATE TABLE "users" ( + // "id" INTEGER NOT NULL PRIMARY KEY, + // "name" VARCHAR(255) NOT NULL, + // "email" VARCHAR(255) NOT NULL, + // "password" VARCHAR(255) NOT NULL, + // "remember_token" VARCHAR(100), + // "created_at" TIMESTAMP, + // "updated_at" TIMESTAMP + // ); + // ALTER TABLE "users" ADD PRIMARY KEY ("id"); + // ALTER TABLE "users" ADD CONSTRAINT "users_email_unique" UNIQUE ("email"); + // CREATE SEQUENCE "seq_users"; + // CREATE OR ALTER TRIGGER "tr_users_bi" FOR "users" + // ACTIVE BEFORE INSERT + // AS + // BEGIN + // IF (NEW."id" IS NULL) THEN + // NEW."id" = NEXT VALUE FOR "seq_users"; + // END + Schema::create('users', function (Blueprint $table) { + $table->increments('id'); + $table->string('name'); + $table->string('email')->unique(); + $table->string('password'); + $table->rememberToken(); + $table->timestamps(); + }); + + // DROP TABLE "users"; + // DROP SEQUENCE "seq_users"; + Schema::drop('users'); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- using identity fields (only in Firebird 3.0). + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ php + // CREATE TABLE "users" ( + // "id" INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + // "name" VARCHAR(255) NOT NULL, + // "email" VARCHAR(255) NOT NULL, + // "password" VARCHAR(255) NOT NULL, + // "remember_token" VARCHAR(100), + // "created_at" TIMESTAMP, + // "updated_at" TIMESTAMP + // ); + // ALTER TABLE "users" ADD CONSTRAINT "users_email_unique" UNIQUE ("email"); + Schema::create('users', function (Blueprint $table) { + $table->useIdentity(); // only Firebird 3.0 + $table->increments('id'); + $table->string('name'); + $table->string('email')->unique(); + $table->string('password'); + $table->rememberToken(); + $table->timestamps(); + }); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- The implementation of InsertGetId method is similar to the postgres, ie + using RETURNING proposal. + +- Create your own base model class in which insertAndSetId method is + implemented through the prior receipt by the sequence identifier. + +- Added additional methods for the execution of stored procedures and stored + functions. + +- Added Providing the connection parameters: the name of the role and Firebird + version (to use the correct grammar). -Any comments or contributions are welcome. +  diff --git a/composer.json b/composer.json index 4d3ecb8..3403a9a 100644 --- a/composer.json +++ b/composer.json @@ -1,25 +1,32 @@ { - "name": "jacquestvanzuydam/laravel-firebird", + "name": "sim_1984/laravel-firebird", "description": "A Firebird database package for the Laravel Framework", "license": "MIT", - "version": "1.0.0.0", + "version": "1.0.3", "authors": [ { "name": "Jacques van Zuydam", "email": "jtvanzuydam@gmail.com" + }, + { + "name": "Simonov Denis", + "email": "sim-mail@list.ru" } ], + "prefer-stable": true, "minimum-stability": "dev", "require": { - "php": ">=5.4.0", - "illuminate/support": "5.0.*", - "illuminate/container": "5.0.*", - "illuminate/database": "5.0.*", - "illuminate/events": "5.0.*" + "php": "^7.1.3", + "ext-pdo": "*", + "illuminate/support": "5.7.*", + "illuminate/container": "5.7.*", + "illuminate/database": "5.7.*", + "illuminate/events": "5.7.*", + "doctrine/instantiator": "~1.0.3" }, "autoload":{ - "psr-0": { - "Firebird\\": "src/" - } + "psr-0": { + "Firebird\\": "src/" + } } } diff --git a/composer.lock b/composer.lock index 31e628e..2a3fb28 100644 --- a/composer.lock +++ b/composer.lock @@ -1,40 +1,41 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "hash": "9f383b8b485f58599282e7a1acf882f0", + "content-hash": "513926db4b72298af795a474af1a673e", "packages": [ { - "name": "danielstjules/stringy", - "version": "1.9.0", + "name": "doctrine/inflector", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/danielstjules/Stringy.git", - "reference": "3cf18e9e424a6dedc38b7eb7ef580edb0929461b" + "url": "https://github.com/doctrine/inflector.git", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/danielstjules/Stringy/zipball/3cf18e9e424a6dedc38b7eb7ef580edb0929461b", - "reference": "3cf18e9e424a6dedc38b7eb7ef580edb0929461b", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=5.3.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^6.2" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, "autoload": { "psr-4": { - "Stringy\\": "src/" - }, - "files": [ - "src/Create.php" - ] + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -42,45 +43,59 @@ ], "authors": [ { - "name": "Daniel St. Jules", - "email": "danielst.jules@gmail.com", - "homepage": "http://www.danielstjules.com" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "A string manipulation library with multibyte support", - "homepage": "https://github.com/danielstjules/Stringy", + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "UTF", - "helpers", - "manipulation", - "methods", - "multibyte", - "string", - "utf-8", - "utility", - "utils" - ], - "time": "2015-02-10 06:19:18" + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2018-01-09T20:05:19+00:00" }, { - "name": "doctrine/inflector", - "version": "dev-master", + "name": "doctrine/instantiator", + "version": "1.0.5", "source": { "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "e5eaf8c7ded0877195b5d2848491e17b1c0a6c4d" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/e5eaf8c7ded0877195b5d2848491e17b1c0a6c4d", - "reference": "e5eaf8c7ded0877195b5d2848491e17b1c0a6c4d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.3,<8.0-DEV" }, "require-dev": { - "phpunit/phpunit": "4.*" + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", "extra": { @@ -89,8 +104,8 @@ } }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Inflector\\": "lib/" + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -99,58 +114,43 @@ ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" } ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", "keywords": [ - "inflection", - "pluralize", - "singularize", - "string" + "constructor", + "instantiate" ], - "time": "2015-01-01 18:34:57" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "illuminate/container", - "version": "5.0.x-dev", + "version": "v5.7.28", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", - "reference": "a11c01c1d8b6941bd7ef2f104749ada5e34f146e" + "reference": "8c3a75e464d59509ae88db152cab61a3f115b9ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/a11c01c1d8b6941bd7ef2f104749ada5e34f146e", - "reference": "a11c01c1d8b6941bd7ef2f104749ada5e34f146e", + "url": "https://api.github.com/repos/illuminate/container/zipball/8c3a75e464d59509ae88db152cab61a3f115b9ec", + "reference": "8c3a75e464d59509ae88db152cab61a3f115b9ec", "shasum": "" }, "require": { - "illuminate/contracts": "5.0.*", - "php": ">=5.4.0" + "illuminate/contracts": "5.7.*", + "illuminate/support": "5.7.*", + "php": "^7.1.3", + "psr/container": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.7-dev" } }, "autoload": { @@ -165,34 +165,36 @@ "authors": [ { "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com" + "email": "taylor@laravel.com" } ], "description": "The Illuminate Container package.", - "homepage": "http://laravel.com", - "time": "2015-03-25 17:06:14" + "homepage": "https://laravel.com", + "time": "2019-02-11T13:48:57+00:00" }, { "name": "illuminate/contracts", - "version": "5.0.x-dev", + "version": "v5.7.28", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", - "reference": "5cda7e58df704a224828491b90f6d86bb49c6b97" + "reference": "b63324d349a8ae2156fbc2697c1ccc85879b3803" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/5cda7e58df704a224828491b90f6d86bb49c6b97", - "reference": "5cda7e58df704a224828491b90f6d86bb49c6b97", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/b63324d349a8ae2156fbc2697c1ccc85879b3803", + "reference": "b63324d349a8ae2156fbc2697c1ccc85879b3803", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "^7.1.3", + "psr/container": "^1.0", + "psr/simple-cache": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.7-dev" } }, "autoload": { @@ -207,44 +209,45 @@ "authors": [ { "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com" + "email": "taylor@laravel.com" } ], "description": "The Illuminate Contracts package.", - "homepage": "http://laravel.com", - "time": "2015-03-24 23:11:34" + "homepage": "https://laravel.com", + "time": "2019-02-12T07:46:48+00:00" }, { "name": "illuminate/database", - "version": "5.0.x-dev", + "version": "v5.7.28", "source": { "type": "git", "url": "https://github.com/illuminate/database.git", - "reference": "c0cf0be377b7a8e19f8942c9fb0992003562429b" + "reference": "c0702cb8c665cab8d080a81de5a44ac672b26d62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/database/zipball/c0cf0be377b7a8e19f8942c9fb0992003562429b", - "reference": "c0cf0be377b7a8e19f8942c9fb0992003562429b", + "url": "https://api.github.com/repos/illuminate/database/zipball/c0702cb8c665cab8d080a81de5a44ac672b26d62", + "reference": "c0702cb8c665cab8d080a81de5a44ac672b26d62", "shasum": "" }, "require": { - "illuminate/container": "5.0.*", - "illuminate/contracts": "5.0.*", - "illuminate/support": "5.0.*", - "nesbot/carbon": "~1.0", - "php": ">=5.4.0" + "illuminate/container": "5.7.*", + "illuminate/contracts": "5.7.*", + "illuminate/support": "5.7.*", + "php": "^7.1.3" }, "suggest": { - "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).", - "illuminate/console": "Required to use the database commands (5.0.*).", - "illuminate/events": "Required to use the observers with Eloquent (5.0.*).", - "illuminate/filesystem": "Required to use the migrations (5.0.*)." + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).", + "fzaninotto/faker": "Required to use the eloquent factory builder (^1.4).", + "illuminate/console": "Required to use the database commands (5.7.*).", + "illuminate/events": "Required to use the observers with Eloquent (5.7.*).", + "illuminate/filesystem": "Required to use the migrations (5.7.*).", + "illuminate/pagination": "Required to paginate the result set (5.7.*)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.7-dev" } }, "autoload": { @@ -259,43 +262,43 @@ "authors": [ { "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com" + "email": "taylor@laravel.com" } ], "description": "The Illuminate Database package.", - "homepage": "http://laravel.com", + "homepage": "https://laravel.com", "keywords": [ "database", "laravel", "orm", "sql" ], - "time": "2015-04-08 01:42:10" + "time": "2019-02-20T03:55:15+00:00" }, { "name": "illuminate/events", - "version": "5.0.x-dev", + "version": "v5.7.28", "source": { "type": "git", "url": "https://github.com/illuminate/events.git", - "reference": "bf2f28157a5acba4df20980e8511850a6572f1f2" + "reference": "e48888062a9962f30c431524357b9a815b093609" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/events/zipball/bf2f28157a5acba4df20980e8511850a6572f1f2", - "reference": "bf2f28157a5acba4df20980e8511850a6572f1f2", + "url": "https://api.github.com/repos/illuminate/events/zipball/e48888062a9962f30c431524357b9a815b093609", + "reference": "e48888062a9962f30c431524357b9a815b093609", "shasum": "" }, "require": { - "illuminate/container": "5.0.*", - "illuminate/contracts": "5.0.*", - "illuminate/support": "5.0.*", - "php": ">=5.4.0" + "illuminate/container": "5.7.*", + "illuminate/contracts": "5.7.*", + "illuminate/support": "5.7.*", + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.7-dev" } }, "autoload": { @@ -310,41 +313,48 @@ "authors": [ { "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com" + "email": "taylor@laravel.com" } ], "description": "The Illuminate Events package.", - "homepage": "http://laravel.com", - "time": "2015-03-26 16:16:33" + "homepage": "https://laravel.com", + "time": "2019-02-11T13:48:57+00:00" }, { "name": "illuminate/support", - "version": "5.0.x-dev", + "version": "v5.7.28", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "0e069a45cdcb1a8a7d85f010f462f622f5b3c669" + "reference": "3e2810145f37eb89fa11759781ee88ee1c1a5262" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/0e069a45cdcb1a8a7d85f010f462f622f5b3c669", - "reference": "0e069a45cdcb1a8a7d85f010f462f622f5b3c669", + "url": "https://api.github.com/repos/illuminate/support/zipball/3e2810145f37eb89fa11759781ee88ee1c1a5262", + "reference": "3e2810145f37eb89fa11759781ee88ee1c1a5262", "shasum": "" }, "require": { - "danielstjules/stringy": "~1.8", - "doctrine/inflector": "~1.0", + "doctrine/inflector": "^1.1", "ext-mbstring": "*", - "illuminate/contracts": "5.0.*", - "php": ">=5.4.0" + "illuminate/contracts": "5.7.*", + "nesbot/carbon": "^1.26.3", + "php": "^7.1.3" + }, + "conflict": { + "tightenco/collect": "<5.5.33" }, "suggest": { - "jeremeamia/superclosure": "Required to be able to serialize closures (~2.0)." + "illuminate/filesystem": "Required to use the composer class (5.7.*).", + "moontoast/math": "Required to use ordered UUIDs (^1.1).", + "ramsey/uuid": "Required to use Str::uuid() (^3.7).", + "symfony/process": "Required to use the composer class (^4.1).", + "symfony/var-dumper": "Required to use the dd function (^4.1)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.7-dev" } }, "autoload": { @@ -362,38 +372,97 @@ "authors": [ { "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com" + "email": "taylor@laravel.com" } ], "description": "The Illuminate Support package.", - "homepage": "http://laravel.com", - "time": "2015-04-07 16:02:55" + "homepage": "https://laravel.com", + "time": "2019-02-12T07:57:07+00:00" + }, + { + "name": "kylekatarnls/update-helper", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/kylekatarnls/update-helper.git", + "reference": "b34a46d7f5ec1795b4a15ac9d46b884377262df9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kylekatarnls/update-helper/zipball/b34a46d7f5ec1795b4a15ac9d46b884377262df9", + "reference": "b34a46d7f5ec1795b4a15ac9d46b884377262df9", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1.0", + "php": ">=5.3.0" + }, + "require-dev": { + "codeclimate/php-test-reporter": "dev-master", + "composer/composer": "^2.0.x-dev", + "phpunit/phpunit": ">=4.8.35 <6.0" + }, + "type": "composer-plugin", + "extra": { + "class": "UpdateHelper\\ComposerPlugin" + }, + "autoload": { + "psr-0": { + "UpdateHelper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Update helper", + "time": "2019-06-05T08:34:23+00:00" }, { "name": "nesbot/carbon", - "version": "1.18.0", + "version": "1.39.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "99e2f69f7bdc2cc4334b2d00f1e0ba450623ea36" + "reference": "dd62a58af4e0775a45ea5f99d0363d81b7d9a1e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/99e2f69f7bdc2cc4334b2d00f1e0ba450623ea36", - "reference": "99e2f69f7bdc2cc4334b2d00f1e0ba450623ea36", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/dd62a58af4e0775a45ea5f99d0363d81b7d9a1e0", + "reference": "dd62a58af4e0775a45ea5f99d0363d81b7d9a1e0", "shasum": "" }, "require": { - "php": ">=5.3.0", - "symfony/translation": "2.6.*" + "kylekatarnls/update-helper": "^1.1", + "php": ">=5.3.9", + "symfony/translation": "~2.6 || ~3.0 || ~4.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "composer/composer": "^1.2", + "friendsofphp/php-cs-fixer": "~2", + "phpunit/phpunit": "^4.8.35 || ^5.7" }, + "bin": [ + "bin/upgrade-carbon" + ], "type": "library", + "extra": { + "update-helper": "Carbon\\Upgrade", + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + } + }, "autoload": { - "psr-0": { - "Carbon": "src" + "psr-4": { + "": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -414,76 +483,307 @@ "datetime", "time" ], - "time": "2015-03-26 03:05:57" + "time": "2019-06-11T09:07:59+00:00" }, { - "name": "symfony/translation", - "version": "2.6.x-dev", - "target-dir": "Symfony/Component/Translation", + "name": "psr/container", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/Translation.git", - "reference": "bd939f05cdaca128f4ddbae1b447d6f0203b60af" + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Translation/zipball/bd939f05cdaca128f4ddbae1b447d6f0203b60af", - "reference": "bd939f05cdaca128f4ddbae1b447d6f0203b60af", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.11-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2019-02-06T07:57:58+00:00" + }, + { + "name": "symfony/translation", + "version": "v4.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "934ab1d18545149e012aa898cf02e9f23790f7a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/934ab1d18545149e012aa898cf02e9f23790f7a0", + "reference": "934ab1d18545149e012aa898cf02e9f23790f7a0", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^1.1.2" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" + }, + "provide": { + "symfony/translation-implementation": "1.0" + }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.3,>=2.3.12", - "symfony/intl": "~2.3", - "symfony/phpunit-bridge": "~2.7", - "symfony/yaml": "~2.2" + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/intl": "~3.4|~4.0", + "symfony/service-contracts": "^1.1.2", + "symfony/var-dumper": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" }, "suggest": { - "psr/log": "To use logging capability in translator", + "psr/log-implementation": "To use logging capability in translator", "symfony/config": "", "symfony/yaml": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "4.3-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Translation Component", - "homepage": "http://symfony.com", - "time": "2015-03-30 15:54:10" + "homepage": "https://symfony.com", + "time": "2019-06-13T11:03:18+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v1.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "cb4b18ad7b92a26e83b65dde940fab78339e6f3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/cb4b18ad7b92a26e83b65dde940fab78339e6f3c", + "reference": "cb4b18ad7b92a26e83b65dde940fab78339e6f3c", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-06-13T11:15:36+00:00" } ], "packages-dev": [], "aliases": [], "minimum-stability": "dev", "stability-flags": [], - "prefer-stable": false, + "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=5.4.0" + "php": "^7.1.3", + "ext-pdo": "*" }, "platform-dev": [] } diff --git a/src/Firebird/Connection.php b/src/Firebird/Connection.php index 7940cdf..b636414 100644 --- a/src/Firebird/Connection.php +++ b/src/Firebird/Connection.php @@ -1,156 +1,203 @@ -engine_version) { + $this->engine_version = isset($this->config['engine_version']) ? $this->config['engine_version'] : null; + } + if (!$this->engine_version) { + $sql = "SELECT RDB\$GET_CONTEXT(?, ?) FROM RDB\$DATABASE"; + $sth = $this->getPdo()->prepare($sql); + $sth->execute(['SYSTEM', 'ENGINE_VERSION']); + $this->engine_version = $sth->fetchColumn(); + $sth->closeCursor(); + } + return $this->engine_version; + } + + /** + * Get major engine version + * It allows you to determine the features of the engine. + * + * @return int + */ + protected function getMajorEngineVersion() + { + $version = $this->getEngineVersion(); + $parts = explode('.', $version); + return (int)$parts[0]; + } + + /** + * Get the default query grammar instance + * + * @return QueryGrammar10|QueryGrammar20|QueryGrammar30 + */ + protected function getDefaultQueryGrammar() + { + switch ($this->getMajorEngineVersion()){ + case 1: + return new QueryGrammar10; + break; + case 3: + return new QueryGrammar30; + break; + default: + return new QueryGrammar20; + break; + } + } + + /** + * Get the default post processor instance. + * + * @return \Firebird\Query\Processors\FirebirdProcessor + */ + protected function getDefaultPostProcessor() + { + return new Processor; + } + + /** + * Get a schema builder instance for this connection. + * + * @return \Firebird\Schema\Builder + */ + public function getSchemaBuilder() + { + if (is_null($this->schemaGrammar)) { + $this->useDefaultSchemaGrammar(); + } + + return new SchemaBuilder($this); + } + + /** + * Get the default schema grammar instance. + * + * @return \Illuminate\Database\Grammar + */ + protected function getDefaultSchemaGrammar() + { + return $this->withTablePrefix(new SchemaGrammar); + } + + /** + * Get query builder + * + * @return \Firebird\Query\Builder + */ + protected function getQueryBuilder() + { + $processor = $this->getPostProcessor(); + $grammar = $this->getQueryGrammar(); -class Connection extends \Illuminate\Database\Connection { - - /** - * The Firebird database handler. - * - * @var Firebird - */ - protected $db; - - /** - * The Firebird connection handler. - * - * @var PDO - */ - protected $connection; - - /** - * Create a new database connection instance. - * - * @param array $config - */ - public function __construct(PDO $pdo, $database = '', $tablePrefix = '', array $config = array()) - { - $this->pdo = $pdo; - - $this->config = $config; - - // First we will setup the default properties. We keep track of the DB - // name we are connected to since it is needed when some reflective - // type commands are run such as checking whether a table exists. - $this->database = $database; - - $this->tablePrefix = $tablePrefix; - - $this->config = $config; - - // The connection string - $dsn = $this->getDsn($config); - - // Create the connection - $this->connection = $this->createConnection($dsn, $config); - - // Set the database - $this->db = $this->connection; - - // We need to initialize a query grammar and the query post processors - // which are both very important parts of the database abstractions - // so we initialize these to their default values while starting. - $this->useDefaultQueryGrammar(); - - $this->useDefaultPostProcessor(); - } - /** - * Return the DSN string from configuration - * - * @param array $config - * @return string - */ - protected function getDsn(array $config) - { - // Check that the host and database are not empty - if( ! empty($config['host']) && ! empty ($config['database']) ) + return new QueryBuilder($this, $grammar, $processor); + } + + /** + * Get a new query builder instance. + * + * @return \Firebird\Query\Builder + */ + public function query() { - return 'firebird:dbname='.$config['host'].':'.$config['database'].';charset='.$config['charset']; + return $this->getQueryBuilder(); } - else + + /** + * Execute stored function + * + * @param string $function + * @param array $values + * @return mixed + */ + public function executeFunction($function, array $values = null) { - trigger_error( 'Cannot connect to Firebird Database, no host or path supplied' ); + $query = $this->getQueryBuilder(); + + return $query->executeFunction($function, $values); + } + + /** + * Execute stored procedure + * + * @param string $procedure + * @param array $values + */ + public function executeProcedure($procedure, array $values = null) + { + $query = $this->getQueryBuilder(); + + $query->executeProcedure($procedure, $values); } - } - - /** - * Create the Firebird Connection - * - * @param string $dsn - * @param array $config - * @return PDO - */ - public function createConnection($dsn, array $config) - { - //Check the username and password - if (!empty($config['username']) && !empty($config['password'])) - { - try { - return new PDO($dsn, $config['username'], $config['password']); - } catch (PDOException $e) { - trigger_error($e->getMessage()); - } - } - else - { - trigger_error('Cannot connect to Firebird Database, no username or password supplied'); - } - return null; - } - - /** - * Get the default query grammar instance - * - * @return Query\Grammars\FirebirdGrammar - */ - protected function getDefaultQueryGrammar() - { - return new Query\Grammars\FirebirdGrammar; - } - - /** - * Get the default post processor instance. - * - * @return Query\Processors\FirebirdProcessor - */ - protected function getDefaultPostProcessor() - { - return new Query\Processors\FirebirdProcessor; - } - - /** - * Get a schema builder instance for this connection. - * @return Schema\Builder - */ - public function getSchemaBuilder() - { - if (is_null($this->schemaGrammar)) { $this->useDefaultSchemaGrammar(); } - - return new Schema\Builder($this); - } - - /** - * Get the default schema grammar instance. - * - * @return SchemaGrammar; - */ - protected function getDefaultSchemaGrammar() { - return $this->withTablePrefix(new SchemaGrammar); - } - - /** - * Begin a fluent query against a database table. - * - * @param string $table - * @return Firebird\Query\Builder - */ - public function table($table) - { - $processor = $this->getPostProcessor(); - - $query = new Query\Builder($this, $this->getQueryGrammar(), $processor); - - return $query->from($table); - } + + /** + * Start a new database transaction. + * + * @return void + * @throws \Exception + */ + public function beginTransaction() + { + if ($this->transactions == 0 && $this->pdo->getAttribute(PDO::ATTR_AUTOCOMMIT) == 1) { + $this->pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0); + } + parent::beginTransaction(); + } + + /** + * Commit the active database transaction. + * + * @return void + */ + public function commit() + { + parent::commit(); + if ($this->transactions == 0 && $this->pdo->getAttribute(PDO::ATTR_AUTOCOMMIT) == 0) { + $this->pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); + } + } + + /** + * Rollback the active database transaction. + * + * @param int|null $toLevel + * @return void + * @throws \Exception + */ + public function rollBack($toLevel = null) + { + parent::rollBack($toLevel); + if ($this->transactions == 0 && $this->pdo->getAttribute(PDO::ATTR_AUTOCOMMIT) == 0) { + $this->pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); + } + } + } diff --git a/src/Firebird/ConnectionFactory.php b/src/Firebird/ConnectionFactory.php deleted file mode 100644 index 1fa797e..0000000 --- a/src/Firebird/ConnectionFactory.php +++ /dev/null @@ -1,103 +0,0 @@ -container->bound($key = "db.connector.{$config['driver']}")) - { - return $this->container->make($key); - } - - switch ($config['driver']) - { - case 'mysql': - return new MySqlConnector; - - case 'pgsql': - return new PostgresConnector; - - case 'sqlite': - return new SQLiteConnector; - - case 'sqlsrv': - return new SqlServerConnector; - - case 'firebird': - return new FirebirdConnector; - } - - throw new InvalidArgumentException("Unsupported driver [{$config['driver']}]".__FILE__); - } - - /** - * Create a new connection instance. - * - * @param string $driver - * @param \PDO $connection - * @param string $database - * @param string $prefix - * @param array $config - * @return \Illuminate\Database\Connection - * - * @throws \InvalidArgumentException - */ - protected function createConnection($driver, PDO $connection, $database, $prefix = '', array $config = array()) - { - if ($this->container->bound($key = "db.connection.{$driver}")) - { - return $this->container->make($key, array($connection, $database, $prefix, $config)); - } - - switch ($driver) - { - case 'mysql': - return new MySqlConnection($connection, $database, $prefix, $config); - - case 'pgsql': - return new PostgresConnection($connection, $database, $prefix, $config); - - case 'sqlite': - return new SQLiteConnection($connection, $database, $prefix, $config); - - case 'sqlsrv': - return new SqlServerConnection($connection, $database, $prefix, $config); - - case 'firebird': - return new FirebirdConnection($connection, $database, $prefix, $config); - } - - throw new InvalidArgumentException("Unsupported driver [$driver]"); - } -} \ No newline at end of file diff --git a/src/Firebird/DatabaseManager.php b/src/Firebird/DatabaseManager.php deleted file mode 100644 index a25d8a9..0000000 --- a/src/Firebird/DatabaseManager.php +++ /dev/null @@ -1,22 +0,0 @@ -app = $app; - $this->factory = $factory; - } - -} \ No newline at end of file diff --git a/src/Firebird/Eloquent/Model.php b/src/Firebird/Eloquent/Model.php new file mode 100644 index 0000000..285327b --- /dev/null +++ b/src/Firebird/Eloquent/Model.php @@ -0,0 +1,65 @@ +getTable(), 0, 31); + return $this->sequence ? $this->sequence : $autoSequence; + } + + /** + * Get next sequence value + * + * @param string $sequence + * + * @return int + */ + protected function nextSequenceValue($sequence = null) + { + $query = $this->getConnection()->getQueryBuilder(); + + $id = $query->nextSequenceValue($sequence ? $sequence : $this->getSequence()); + + return $id; + } + + /** + * Insert the given attributes and set the ID on the model. + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param array $attributes + * @return void + */ + protected function insertAndSetId(Builder $query, $attributes) + { + $id = $this->nextSequenceValue(); + + $keyName = $this->getKeyName(); + + $attributes[$keyName] = $id; + + $query->insert($attributes); + + $this->setAttribute($keyName, $id); + } + +} diff --git a/src/Firebird/FirebirdConnector.php b/src/Firebird/FirebirdConnector.php index 26dbec4..efa8cf1 100644 --- a/src/Firebird/FirebirdConnector.php +++ b/src/Firebird/FirebirdConnector.php @@ -1,34 +1,66 @@ -getOptions($config); - - $path = $config['database']; - - $charset = $config['charset']; - - $host = $config['host']; - if ( empty($host)) + /** + * Establish a database connection. + * + * @param array $config + * @return PDO + */ + public function connect(array $config) { - throw new InvalidArgumentException("Host not given, required."); + $dsn = $this->getDsn($config); + + $options = $this->getOptions($config); + + // We need to grab the PDO options that should be used while making the brand + // new connection instance. The PDO options control various aspects of the + // connection's behavior, and some might be specified by the developers. + $connection = $this->createConnection($dsn, $config, $options); + + return $connection; } - return $this->createConnection("firebird:dbname={$host}:{$path};charset={$charset}", $config, $options); - } + /** + * Create a DSN string from a configuration. + * + * @param array $config + * @return string + */ + protected function getDsn(array $config) + { + $dsn = ''; + if (isset($config['host'])) { + $dsn .= $config['host']; + } + if (isset($config['port'])) { + $dsn .= "/" . $config['port']; + } + if (!isset($config['database'])) { + throw new InvalidArgumentException("Database not given, required."); + } + if ($dsn) { + $dsn .= ':'; + } + $dsn .= $config['database'] . ';'; + if (isset($config['charset'])) { + $dsn .= "charset=" . $config['charset']; + } + if (isset($config['role'])) { + $dsn .= ";role=" . $config['role']; + } + $dsn = 'firebird:dbname=' . $dsn; + + return $dsn; + } } diff --git a/src/Firebird/FirebirdServiceProvider.php b/src/Firebird/FirebirdServiceProvider.php index e62ca14..7282f9b 100644 --- a/src/Firebird/FirebirdServiceProvider.php +++ b/src/Firebird/FirebirdServiceProvider.php @@ -1,61 +1,26 @@ -app['db']); +namespace Firebird; - Model::setEventDispatcher($this->app['events']); - } - - /** - * Register the application services. - * This is where the connection gets registered - * - * @return void - */ - public function register() - { - $this->registerQueueableEntityResolver(); +use Firebird\Connection as FirebirdConnection; +use Illuminate\Database\Connection; +use Illuminate\Support\ServiceProvider; - // The connection factory is used to create the actual connection instances on - // the database. We will inject the factory into the manager so that it may - // make the connections while they are actually needed and not of before. - $this->app->singleton('db.factory', function($app) - { - return new FirebirdConnectionFactory($app); - }); +class FirebirdServiceProvider extends ServiceProvider +{ - // The database manager is used to resolve various connections, since multiple - // connections might be managed. It also implements the connection resolver - // interface which may be used by other components requiring connections. - $this->app->singleton('db', function($app) + /** + * Register the application services. + * This is where the connection gets registered + * + * @return void + */ + public function register() { - return new FirebirdDatabaseManager($app, $app['db.factory']); - }); - } + Connection::resolverFor('firebird', function ($connection, $database, $tablePrefix, $config) { + return new FirebirdConnection($connection, $database, $tablePrefix, $config); + }); + $this->app->bind('db.connector.firebird', FirebirdConnector::class); + } - /** - * Register the queueable entity resolver implementation. - * - * @return void - */ - protected function registerQueueableEntityResolver() - { - $this->app->singleton('Illuminate\Contracts\Queue\EntityResolver', function() - { - return new Eloquent\QueueEntityResolver; - }); - } } diff --git a/src/Firebird/Model.php b/src/Firebird/Model.php deleted file mode 100644 index 2a8a2c4..0000000 --- a/src/Firebird/Model.php +++ /dev/null @@ -1,7 +0,0 @@ -grammar->compileGetContext($this, $namespace, $name); + + return $this->processor->processGetContextValue($this, $sql); + } + + /** + * Get next sequence value + * + * @param string $sequence + * @param int $increment + * @return int + */ + public function nextSequenceValue($sequence = null, $increment = null) + { + $sql = $this->grammar->compileNextSequenceValue($this, $sequence, $increment); + + return $this->processor->processNextSequenceValue($this, $sql); + } + + /** + * Execute stored procedure + * + * @param string $procedure + * @param array $values + */ + public function executeProcedure($procedure, array $values = null) + { + if (!$values) { + $values = []; + } + + $bindings = array_values($values); + + $sql = $this->grammar->compileExecProcedure($this, $procedure, $values); + + $this->connection->statement($sql, $this->cleanBindings($bindings)); + } + + /** + * Execute stored function + * + * @param string $function + * @param array $values + * + * @return mixed + */ + public function executeFunction($function, array $values = null) + { + if (!$values) { + $values = []; + } -class Builder extends BaseBuilder { + $sql = $this->grammar->compileExecProcedure($this, $function, $values); + return $this->processor->processExecuteFunction($this, $sql, $values); + } -} \ No newline at end of file +} diff --git a/src/Firebird/Query/Grammars/Firebird15Grammar.php b/src/Firebird/Query/Grammars/Firebird15Grammar.php new file mode 100644 index 0000000..00f60b8 --- /dev/null +++ b/src/Firebird/Query/Grammars/Firebird15Grammar.php @@ -0,0 +1,112 @@ +aggregate)) return; + $select = ''; + if (count($columns) > 0 && $query->limit == null && $query->aggregate == null) + { + $select = $query->distinct ? 'select distinct ' : 'select '; + } + + return $select.$this->columnize($columns); + } + + /** + * Compile a select query into SQL. + * + * @param Illuminate\Database\Query\Builder + * + * @return string + */ + public function compileSelect(Builder $query) + { + if (is_null($query->columns)) $query->columns = array('*'); + + return trim($this->concatenate($this->compileComponents($query))); + } + + /** + * Compile an aggregated select clause. + * + * @param \Illuminate\Database\Query\Builder $query + * @param array $aggregate + * @return string + */ + protected function compileAggregate(Builder $query, $aggregate) + { + $column = $this->columnize($aggregate['columns']); + + // If the query has a "distinct" constraint and we're not asking for all columns + // we need to prepend "distinct" onto the column name so that the query takes + // it into account when it performs the aggregating operations on the data. + if ($query->distinct && $column !== '*') + { + $column = 'distinct '.$column; + } + + return 'select '.$aggregate['function'].'('.$column.') as aggregate'; + } + + /** + * Compile first instead of limit + * + * @param \Illuminate\Database\Query\Builder $query + * @param int $limit + * @return string + */ + protected function compileLimit(Builder $query, $limit) + { + return 'select first '.(int) $limit; + } + + /** + * Compile skip instead of offset + * + * @param \Illuminate\Database\Query\Builder $query + * @param int $limit + * @return string + */ + protected function compileOffset(Builder $query, $limit) + { + return 'skip '.(int) $limit; + } + +} diff --git a/src/Firebird/Query/Grammars/Firebird25Grammar.php b/src/Firebird/Query/Grammars/Firebird25Grammar.php new file mode 100644 index 0000000..9c7e112 --- /dev/null +++ b/src/Firebird/Query/Grammars/Firebird25Grammar.php @@ -0,0 +1,262 @@ +', '<=', '>=', '<>', '!=', + 'like', 'not like', 'between', 'containing', 'starting with', + 'similar to', 'not similar to', + ]; + + /** + * Compile an aggregated select clause. + * + * @param \Illuminate\Database\Query\Builder $query + * @param array $aggregate + * @return string + */ + protected function compileAggregate(Builder $query, $aggregate) + { + $column = $this->columnize($aggregate['columns']); + + // If the query has a "distinct" constraint and we're not asking for all columns + // we need to prepend "distinct" onto the column name so that the query takes + // it into account when it performs the aggregating operations on the data. + if ($query->distinct && $column !== '*') { + $column = 'distinct ' . $column; + } + + return 'select ' . $aggregate['function'] . '(' . $column . ') as "aggregate"'; + } + + /** + * Compile SQL statement for get context variable value + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $namespace + * @param string $name + * @return string + */ + public function compileGetContext(Builder $query, $namespace, $name) + { + return "SELECT RDB\$GET_CONTEXT('{$namespace}', '{$name}' AS VAL FROM RDB\$DATABASE"; + } + + /** + * Compile SQL statement for execute function + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $function + * @param array $values + * @return string + */ + public function compileExecFunction(Builder $query, $function, array $values = null) + { + $function = $this->wrap($function); + + return "SELECT {$function} (" . $this->parameterize($values) . ") AS VAL FROM RDB\$DATABASE"; + } + + /** + * Compile SQL statement for execute procedure + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $procedure + * @param array $values + * @return string + */ + public function compileExecProcedure(Builder $query, $procedure, array $values = null) + { + $procedure = $this->wrap($procedure); + + return "EXECUTE PROCEDURE {$$procedure} (" . $this->parameterize($values) . ')'; + } + + /** + * Compile an insert and get ID statement into SQL. + * + * @param \Illuminate\Database\Query\Builder $query + * @param array $values + * @param string $sequence + * @return string + */ + public function compileInsertGetId(Builder $query, $values, $sequence) + { + if (is_null($sequence)) { + $sequence = 'ID'; + } + + return $this->compileInsert($query, $values) . ' RETURNING ' . $this->wrap($sequence); + } + + /** + * Compile the "limit" portions of the query. + * + * @param \Illuminate\Database\Query\Builder $query + * @param int $limit + * @return string + */ + protected function compileLimit(Builder $query, $limit) + { + if ($query->offset) { + $first = (int)$query->offset + 1; + return 'ROWS ' . (int)$first; + } else { + return 'ROWS ' . (int)$limit; + } + } + + /** + * Compile the lock into SQL. + * + * @param \Illuminate\Database\Query\Builder $query + * @param bool|string $value + * @return string + */ + protected function compileLock(Builder $query, $value) + { + if (is_string($value)) { + return $value; + } + + return $value ? 'FOR UPDATE' : ''; + } + + /** + * Compile SQL statement for get next sequence value + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $sequence + * @param int $increment + * @return string + */ + public function compileNextSequenceValue(Builder $query, $sequence = null, $increment = null) + { + if (!$sequence) { + $sequence = $this->wrap(substr('seq_' . $query->from, 0, 31)); + } + if ($increment) { + return "SELECT GEN_ID({$sequence}, {$increment}) AS ID FROM RDB\$DATABASE"; + } + return "SELECT NEXT VALUE FOR {$sequence} AS ID FROM RDB\$DATABASE"; + } + + /** + * Compile the "offset" portions of the query. + * + * @param \Illuminate\Database\Query\Builder $query + * @param int $offset + * @return string + */ + protected function compileOffset(Builder $query, $offset) + { + if ($query->limit) { + if ($offset) { + $end = (int)$query->limit + (int)$offset; + return 'TO ' . $end; + } else { + return ''; + } + } else { + $begin = (int)$offset + 1; + return 'ROWS ' . $begin . ' TO 2147483647'; + } + } + + /** + * Compile an update statement into SQL. + * + * @param \Illuminate\Database\Query\Builder $query + * @param array $values + * @return string + */ + public function compileUpdate(Builder $query, $values) + { + $table = $this->wrapTable($query->from); + + // Each one of the columns in the update statements needs to be wrapped in the + // keyword identifiers, also a place-holder needs to be created for each of + // the values in the list of bindings so we can make the sets statements. + $columns = $this->compileUpdateColumns($values); + + + $where = $this->compileUpdateWheres($query); + + return trim("UPDATE {$table} SET {$columns} $where"); + } + + /** + * Compile the columns for the update statement. + * + * @param array $values + * @return string + */ + protected function compileUpdateColumns($values) + { + $columns = []; + + // When gathering the columns for an update statement, we'll wrap each of the + // columns and convert it to a parameter value. Then we will concatenate a + // list of the columns that can be added into this update query clauses. + foreach ($values as $key => $value) { + $columns[] = $this->wrap($key) . ' = ' . $this->parameter($value); + } + + return implode(', ', $columns); + } + + /** + * Compile the additional where clauses for updates with joins. + * + * @param \Illuminate\Database\Query\Builder $query + * @return string + */ + protected function compileUpdateWheres(Builder $query) + { + $baseWhere = $this->compileWheres($query); + + return $baseWhere; + } + + /** + * Compile a date based where clause. + * + * @param string $type + * @param \Illuminate\Database\Query\Builder $query + * @param array $where + * @return string + */ + protected function dateBasedWhere($type, Builder $query, $where) + { + $value = $this->parameter($where['value']); + + return 'EXTRACT(' . $type . ' FROM ' . $this->wrap($where['column']) . ') ' . $where['operator'] . ' ' . $value; + } + + /** + * Wrap a single string in keyword identifiers. + * + * @param string $value + * @return string + */ + protected function wrapValue($value) + { + if ($value === '*') { + return $value; + } + + return '"' . str_replace('"', '""', $value) . '"'; + } + +} diff --git a/src/Firebird/Query/Grammars/Firebird30Grammar.php b/src/Firebird/Query/Grammars/Firebird30Grammar.php new file mode 100644 index 0000000..fdaeb65 --- /dev/null +++ b/src/Firebird/Query/Grammars/Firebird30Grammar.php @@ -0,0 +1,61 @@ +aggregate)) return; - $select = ''; - if (count($columns) > 0 && $query->limit == null && $query->aggregate == null) - { - $select = $query->distinct ? 'select distinct ' : 'select '; - } - - return $select.$this->columnize($columns); - } - - /** - * Compile a select query into SQL. - * - * @param Illuminate\Database\Query\Builder - * - * @return string - */ - public function compileSelect(Builder $query) - { - if (is_null($query->columns)) $query->columns = array('*'); - - return trim($this->concatenate($this->compileComponents($query))); - } - - /** - * Compile an aggregated select clause. - * - * @param \Illuminate\Database\Query\Builder $query - * @param array $aggregate - * @return string - */ - protected function compileAggregate(Builder $query, $aggregate) - { - $column = $this->columnize($aggregate['columns']); - - // If the query has a "distinct" constraint and we're not asking for all columns - // we need to prepend "distinct" onto the column name so that the query takes - // it into account when it performs the aggregating operations on the data. - if ($query->distinct && $column !== '*') - { - $column = 'distinct '.$column; - } - - return 'select '.$aggregate['function'].'('.$column.') as aggregate'; - } - - /** - * Compile first instead of limit - * - * @param \Illuminate\Database\Query\Builder $query - * @param int $limit - * @return string - */ - protected function compileLimit(Builder $query, $limit) - { - return 'select first '.(int) $limit; - } - - /** - * Compile skip instead of offset - * - * @param \Illuminate\Database\Query\Builder $query - * @param int $limit - * @return string - */ - protected function compileOffset(Builder $query, $limit) - { - return 'skip '.(int) $limit; - } - -} \ No newline at end of file diff --git a/src/Firebird/Query/Processors/FirebirdProcessor.php b/src/Firebird/Query/Processors/FirebirdProcessor.php index c114ca8..c9cbab8 100644 --- a/src/Firebird/Query/Processors/FirebirdProcessor.php +++ b/src/Firebird/Query/Processors/FirebirdProcessor.php @@ -1,7 +1,98 @@ -getConnection()->selectFromWriteConnection($sql, $values); + + $sequence = $sequence ?: 'ID'; + + $result = (array)$results[0]; + + $id = $result[$sequence]; + + return is_numeric($id) ? (int)$id : $id; + } + + /** + * Process an "next sequence value" query. + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $sql + * @return int + */ + public function processNextSequenceValue(Builder $query, $sql) + { + $results = $query->getConnection()->selectFromWriteConnection($sql); + + $result = (array)$results[0]; + + $id = $result['ID']; + + return is_numeric($id) ? (int)$id : $id; + } + + /** + * Process an "get context variable value" query. + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $sql + * @return int + */ + public function processGetContextValue(Builder $query, $sql) + { + $result = $query->getConnection()->selectOne($sql); + + return $result['VAL']; + } + + /** + * Process an "execute function" query. + * + * @param \Illuminate\Database\Query\Builder $query + * @param string $sql + * @param array $values + * + * @return mixed + */ + public function processExecuteFunction(Builder $query, $sql, $values) + { + $result = $query->getConnection()->selectOne($sql, $values); + + return $result['VAL']; + } + + /** + * Process the results of a column listing query. + * + * @param array $results + * @return array + */ + public function processColumnListing($results) + { + $mapping = function ($r) { + $r = (object)$r; + + return trim($r->{'RDB$FIELD_NAME'}); + }; + + return array_map($mapping, $results); + } -} \ No newline at end of file +} diff --git a/src/Firebird/Schema/Blueprint.php b/src/Firebird/Schema/Blueprint.php new file mode 100644 index 0000000..815b972 --- /dev/null +++ b/src/Firebird/Schema/Blueprint.php @@ -0,0 +1,138 @@ +preserve = true; + } + + /** + * Indicate that it is necessary to use a identity modifier for increment columns + * + * @return void + */ + public function useIdentity() + { + $this->use_identity = true; + } + + /** + * Indicate that it is necessary to use native boolean type + * Reserved for future versions. Now Firebird PDO driver + * does not support the type BOOLEAN + * + * @return void + */ + public function nativeBoolean() + { + $this->use_native_boolean = true; + } + + /** + * Determine if the blueprint has a create command. + * + * @return bool + */ + protected function droping() + { + foreach ($this->commands as $command) { + if (($command->name == 'drop') || ($command->name == 'dropIfExists')) { + return true; + } + } + + return false; + } + + /** + * Add the commands that are implied by the blueprint. + * + * @param \Illuminate\Database\Schema\Grammars\Grammar $grammar + * @return void + */ + protected function addImpliedCommands(Grammar $grammar) + { + parent::addImpliedCommands($grammar); + + if (!$this->use_identity) { + $this->addSequence(); + $this->addAutoIncrementTrigger(); + } + + if ($this->droping() && !$this->use_identity) { + $this->dropSequence(); + } + } + + /** + * Add the command for create sequence for table + * + * @return void + */ + protected function addSequence() + { + foreach ($this->columns as $column) { + if ($column->autoIncrement) { + array_push($this->commands, $this->createCommand('sequenceForTable')); + break; + } + } + } + + /** + * Add the command for drop sequence for table + * + * @return void + */ + protected function dropSequence() + { + array_push($this->commands, $this->createCommand('dropSequenceForTable')); + } + + /** + * Add the command for create trigger + * + * @return void + */ + protected function addAutoIncrementTrigger() + { + foreach ($this->columns as $column) { + if ($column->autoIncrement) { + array_push($this->commands, $this->createCommand('triggerForAutoincrement', ['columnname' => $column->name])); + break; + } + } + } + +} diff --git a/src/Firebird/Schema/Builder.php b/src/Firebird/Schema/Builder.php index c601d16..56ef13d 100644 --- a/src/Firebird/Schema/Builder.php +++ b/src/Firebird/Schema/Builder.php @@ -1,7 +1,127 @@ resolver)) { + return call_user_func($this->resolver, $table, $callback); + } + + return new Blueprint($table, $callback); + } + + /** + * Create a new command for Sequence set with a Closure. + * + * @param string $sequence + * @param \Closure|null $callback + * @return \Firebird\Schema\SequenceBlueprint + */ + protected function createSequenceBlueprint($sequence, Closure $callback = null) + { + if (isset($this->resolver)) { + return call_user_func($this->resolver, $sequence, $callback); + } + + return new SequenceBlueprint($sequence, $callback); + } + + /** + * Execute the blueprint to build / modify the sequence. + * + * @param \Firebird\Schema\SequenceBlueprint $seqprint + * @return void + */ + protected function buildSequence(SequenceBlueprint $seqprint) + { + $seqprint->build($this->connection, $this->grammar); + } + + /** + * Determine if the given sequence exists. + * + * @param string $sequence + * @return bool + */ + public function hasSequence($sequence) + { + $sql = $this->grammar->compileSequenceExists(); + + return count($this->connection->select($sql, [$sequence])) > 0; + } + + /** + * Create a new sequence on the schema + * + * @param string $sequence + * @param \Closure $callback + * @return void + */ + public function createSequence($sequence, Closure $callback = null) + { + $seqprint = $this->createSequenceBlueprint($sequence); + + $seqprint->create(); + + if ($callback) { + $callback($seqprint); + } + + $this->buildSequence($seqprint); + } + + /** + * Drop a sequence from the schema. + * + * @param string $sequence + * @param \Closure $callback + */ + public function dropSequence($sequence) + { + $seqprint = $this->createSequenceBlueprint($sequence); + + $seqprint->drop(); + + $this->buildSequence($seqprint); + } + + /** + * Modify a sequence on the schema. + * + * @param string $sequence + * @param \Closure $callback + * @return void + */ + public function sequence($sequence, Closure $callback) + { + $this->buildSequence($this->createSequenceBlueprint($sequence, $callback)); + } + + /** + * Drop a sequence from the schema if it exists. + * + * @param string $sequence + * @return void + */ + public function dropSequenceIfExists($sequence) + { + $blueprint = $this->createSequenceBlueprint($sequence); + + $blueprint->dropIfExists(); + + $this->buildSequence($blueprint); + } + +} diff --git a/src/Firebird/Schema/Grammars/FirebirdGrammar.php b/src/Firebird/Schema/Grammars/FirebirdGrammar.php index b00fdcd..9394e56 100644 --- a/src/Firebird/Schema/Grammars/FirebirdGrammar.php +++ b/src/Firebird/Schema/Grammars/FirebirdGrammar.php @@ -1,437 +1,763 @@ -getColumns($blueprint)); - - $sql = 'create table '.$this->wrapTable($blueprint)." ($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 primary key command. - * - * @param \Illuminate\Database\Schema\Blueprint $blueprint - * @param \Illuminate\Support\Fluent $command - * @return string - */ - public function compilePrimary(Blueprint $blueprint, Fluent $command) - { - $command->name(null); - - return $this->compileKey($blueprint, $command, 'primary key'); - } - - /** - * 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) - { - $columns = $this->columnize($command->columns); - - $table = $this->wrapTable($blueprint); - - return "CREATE UNIQUE INDEX ".strtoupper(substr($command->index, 0, 31))." ON {$table} ($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) - { - $columns = $this->columnize($command->columns); - - $table = $this->wrapTable($blueprint); - - return "CREATE INDEX ".strtoupper(substr($command->index, 0, 31))." ON {$table} ($columns)"; - } - - /** - * Compile an index creation command. - * - * @param \Illuminate\Database\Schema\Blueprint $blueprint - * @param \Illuminate\Support\Fluent $command - * @param string $type - * @return string - */ - protected function compileKey(Blueprint $blueprint, Fluent $command, $type) - { - $columns = $this->columnize($command->columns); - - $table = $this->wrapTable($blueprint); - - return "alter table {$table} add {$type} ($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); - - $sql = "alter table {$table} add constraint ".strtoupper(substr($command->index, 0, 31))." "; - - $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 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); - - return "alter table {$table} drop constraint {$command->index}"; - } - - /** - * 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); - } - } - - /** - * Create the column definition for a char type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeChar(Fluent $column) - { - return 'VARCHAR'; - } - - /** - * 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 'BLOB SUB_TYPE TEXT'; - } - - /** - * Create the column definition for a medium text type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeMediumText(Fluent $column) - { - return 'BLOB SUB_TYPE TEXT'; - } - - /** - * Create the column definition for a long text type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeLongText(Fluent $column) - { - return 'BLOB SUB_TYPE TEXT'; - } - - /** - * Create the column definition for a integer type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeInteger(Fluent $column) - { - return 'INTEGER'; - } - - /** - * Create the column definition for a big integer type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeBigInteger(Fluent $column) - { - return 'INTEGER'; - } - - /** - * Create the column definition for a medium integer type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeMediumInteger(Fluent $column) - { - return 'INTEGER'; - } - - /** - * Create the column definition for a tiny integer type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeTinyInteger(Fluent $column) - { - return 'SMALLINT'; - } - - /** - * 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 float type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeFloat(Fluent $column) - { - return 'FLOAT'; - } - - /** - * Create the column definition for a double type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeDouble(Fluent $column) - { - return 'DOUBLE'; - } - - /** - * Create the column definition for a decimal type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeDecimal(Fluent $column) - { - return 'DECIMAL'; - } - - /** - * Create the column definition for a boolean type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeBoolean(Fluent $column) - { - return 'CHAR(1)'; - } - - /** - * Create the column definition for an enum type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeEnum(Fluent $column) - { - return 'VARCHAR'; - } - - /** - * Create the column definition for a json type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeJson(Fluent $column) - { - return 'BLOB SUB_TYPE 0'; - } - - /** - * Create the column definition for a date type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeDate(Fluent $column) - { - return 'TIMESTAMP'; - } - - /** - * Create the column definition for a date-time type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeDateTime(Fluent $column) - { - return 'TIMESTAMP'; - } - - /** - * Create the column definition for a time type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeTime(Fluent $column) - { - return 'TIMESTAMP'; - } - - /** - * Create the column definition for a timestamp type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeTimestamp(Fluent $column) - { - return 'TIMESTAMP'; - } - - /** - * Create the column definition for a binary type. - * - * @param \Illuminate\Support\Fluent $column - * @return string - */ - protected function typeBinary(Fluent $column) - { - return 'BLOB SUB_TYPE 0'; - } + +class FirebirdGrammar extends Grammar +{ + + /** + * The possible column modifiers. + * + * @var array + */ + protected $modifiers = ['Charset', 'Collate', 'Increment', 'Nullable', 'Default']; + + /** + * The columns available as serials. + * + * @var array + */ + protected $serials = ['bigInteger', 'integer', 'mediumInteger', 'smallInteger', 'tinyInteger']; + + /** + * Compile the query to determine if a table exists. + * + * @return string + */ + public function compileTableExists() + { + return 'SELECT * FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = ?'; + } + + /** + * Compile the query to determine the list of columns. + * + * @param string $table + * @return string + */ + public function compileColumnExists($table) + { + return 'SELECT TRIM(RDB$FIELD_NAME) AS "column_name" ' + . "FROM RDB\$RELATION_FIELDS WHERE RDB\$RELATION_NAME = '$table'"; + } + + /** + * Compile the query to determine if a sequence exists. + * + * @return string + */ + public function compileSequenceExists() + { + return 'SELECT * FROM RDB$GENERATORS WHERE RDB$GENERATOR_NAME = ?'; + } + + /** + * Compile a create table command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileCreate(Blueprint $blueprint, Fluent $command) + { + $columns = implode(', ', $this->getColumns($blueprint)); + + $sql = $blueprint->temporary ? 'CREATE TEMPORARY' : 'CREATE'; + + $sql .= ' TABLE ' . $this->wrapTable($blueprint) . " ($columns)"; + + if ($blueprint->temporary) { + if ($blueprint->preserve) { + $sql .= ' ON COMMIT DELETE ROWS'; + } else { + $sql .= ' ON COMMIT PRESERVE ROWS'; + } + } + + 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 column addition 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)); + + return 'ALTER TABLE ' . $table . ' ' . implode(', ', $columns); + } + + /** + * 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) + { + $columns = $this->columnize($command->columns); + + return 'ALTER TABLE ' . $this->wrapTable($blueprint) . " ADD PRIMARY KEY ({$columns})"; + } + + /** + * 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); + + $index = $this->wrap(substr($command->index, 0, 31)); + + $columns = $this->columnize($command->columns); + + return "ALTER TABLE {$table} ADD CONSTRAINT {$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) + { + $columns = $this->columnize($command->columns); + + $index = $this->wrap(substr($command->index, 0, 31)); + + $table = $this->wrapTable($blueprint); + + return "CREATE INDEX {$index} ON {$table} ($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); + + $fkName = substr($command->index, 0, 31); + + $sql = "ALTER TABLE {$table} ADD CONSTRAINT {$fkName} "; + + $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 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); + + return "ALTER TABLE {$table} DROP CONSTRAINT {$command->index}"; + } + + /** + * Get the SQL for a character set column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyCharset(Blueprint $blueprint, Fluent $column) + { + if (!is_null($column->charset)) { + return ' CHARACTER SET ' . $column->charset; + } + } + + /** + * Get the SQL for a collation column modifier. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $column + * @return string|null + */ + protected function modifyCollate(Blueprint $blueprint, Fluent $column) + { + if (!is_null($column->collation)) { + return ' COLLATE ' . $column->collation; + } + } + + /** + * 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) { + // identity columns support beginning Firebird 3.0 and above + return $blueprint->use_identity ? ' GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY' : ' PRIMARY KEY'; + } + } + + /** + * 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 'BLOB SUB_TYPE TEXT'; + } + + /** + * Create the column definition for a medium text type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeMediumText(Fluent $column) + { + return 'BLOB SUB_TYPE TEXT'; + } + + /** + * Create the column definition for a long text type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeLongText(Fluent $column) + { + return 'BLOB SUB_TYPE TEXT'; + } + + /** + * Create the column definition for a integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeInteger(Fluent $column) + { + return 'INTEGER'; + } + + /** + * 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 medium integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeMediumInteger(Fluent $column) + { + return 'INTEGER'; + } + + /** + * Create the column definition for a tiny integer type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTinyInteger(Fluent $column) + { + return 'SMALLINT'; + } + + /** + * 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 float type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeFloat(Fluent $column) + { + return 'FLOAT'; + } + + /** + * Create the column definition for a double type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDouble(Fluent $column) + { + return 'DOUBLE PRECISION'; + } + + /** + * 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) + { + // Firebird 3.0 support native type BOOLEAN, but + // PDO dosn't support + return 'CHAR(1)'; + } + + /** + * Create the column definition for an enum type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeEnum(Fluent $column) + { + $allowed = array_map(function ($a) { + return "'" . $a . "'"; + }, $column->allowed); + + return "VARCHAR(255) CHECK (\"{$column->name}\" IN (" . implode(', ', $allowed) . '))'; + } + + /** + * Create the column definition for a json type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeJson(Fluent $column) + { + return 'VARCHAR(8191)'; + } + + /** + * Create the column definition for a jsonb type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeJsonb(Fluent $column) + { + return 'VARCHAR(8191) CHARACTER SET OCTETS'; + } + + /** + * Create the column definition for a date type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDate(Fluent $column) + { + return 'DATE'; + } + + /** + * Create the column definition for a date-time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDateTime(Fluent $column) + { + return 'TIMESTAMP'; + } + + /** + * Create the column definition for a date-time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeDateTimeTz(Fluent $column) + { + // Firebird don't support timezones + return 'TIMESTAMP'; + } + + /** + * Create the column definition for a time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTime(Fluent $column) + { + return 'TIME'; + } + + /** + * Create the column definition for a time type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTimeTz(Fluent $column) + { + // Firebird don't support timezones + return 'TIME'; + } + + /** + * Create the column definition for a timestamp type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTimestamp(Fluent $column) + { + if ($column->useCurrent) { + return 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP'; + } + + return 'TIMESTAMP'; + } + + /** + * Create the column definition for a timestamp type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeTimestampTz(Fluent $column) + { + if ($column->useCurrent) { + 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 SUB_TYPE BINARY'; + } + + /** + * Create the column definition for a uuid type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeUuid(Fluent $column) + { + return 'CHAR(36)'; + } + + /** + * Create the column definition for an IP address type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeIpAddress(Fluent $column) + { + return 'VARCHAR(45)'; + } + + /** + * Create the column definition for a MAC address type. + * + * @param \Illuminate\Support\Fluent $column + * @return string + */ + protected function typeMacAddress(Fluent $column) + { + return 'VARCHAR(17)'; + } + + /** + * Compile a create sequence command. + * + * @param \Firebird\Schema\SequenceBlueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileCreateSequence(SequenceBlueprint $blueprint, Fluent $command) + { + $sql = 'CREATE SEQUENCE '; + $sql .= $this->wrapSequence($blueprint); + if ($blueprint->getInitialValue() !== 0) { + $sql .= ' START WITH ' . $blueprint->getInitialValue(); + } + if ($blueprint->getIncrement() !== 1) { + $sql .= ' INCREMENT BY ' . $blueprint->getIncrement(); + } + return $sql; + } + + /** + * Compile a create sequence command for table. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileSequenceForTable(Blueprint $blueprint, Fluent $command) + { + + $sequence = $this->wrap(substr('seq_' . $blueprint->getTable(), 0, 31)); + + return "CREATE SEQUENCE {$sequence}"; + } + + /** + * Compile a drop sequence command for table. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropSequenceForTable(Blueprint $blueprint, Fluent $command) + { + $sequenceName = substr('seq_' . $blueprint->getTable(), 0, 31); + $sequence = $this->wrap($sequenceName); + + $sql = 'EXECUTE BLOCK' . "\n"; + $sql .= 'AS' . "\n"; + $sql .= 'BEGIN' . "\n"; + $sql .= " IF (EXISTS(SELECT * FROM RDB\$GENERATORS WHERE RDB\$GENERATOR_NAME = '{$sequenceName}')) THEN" . "\n"; + $sql .= " EXECUTE STATEMENT 'DROP SEQUENCE {$sequence}';" . "\n"; + $sql .= 'END'; + return $sql; + } + + /** + * Compile a create trigger for support autoincrement. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileTriggerForAutoincrement(Blueprint $blueprint, Fluent $command) + { + $table = $this->wrapTable($blueprint); + $trigger = $this->wrap(substr('tr_' . $blueprint->getTable() . '_bi', 0, 31)); + $column = $this->wrap($command->columnname); + $sequence = $this->wrap(substr('seq_' . $blueprint->getTable(), 0, 31)); + + $sql = "CREATE OR ALTER TRIGGER {$trigger} FOR {$table}\n"; + $sql .= "ACTIVE BEFORE INSERT\n"; + $sql .= "AS\n"; + $sql .= "BEGIN\n"; + $sql .= " IF (NEW.{$column} IS NULL) THEN \n"; + $sql .= " NEW.{$column} = NEXT VALUE FOR {$sequence};\n"; + $sql .= 'END'; + + return $sql; + } + + /** + * Compile a alter sequence command. + * + * @param \Firebird\Schema\SequenceBlueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileAlterSequence(SequenceBlueprint $blueprint, Fluent $command) + { + $sql = 'ALTER SEQUENCE '; + $sql .= $this->wrapSequence($blueprint); + if ($blueprint->isRestart()) { + $sql .= ' RESTART'; + if ($blueprint->getInitialValue() !== null) { + $sql .= ' WITH ' . $blueprint->getInitialValue(); + } + } + if ($blueprint->getIncrement() !== 1) { + $sql .= ' INCREMENT BY ' . $blueprint->getIncrement(); + } + return $sql; + } + + /** + * Compile a drop sequence command. + * + * @param \Firebird\Schema\SequenceBlueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropSequence(SequenceBlueprint $blueprint, Fluent $command) + { + return 'DROP SEQUENCE ' . $this->wrapSequence($blueprint); + } + + /** + * Compile a drop sequence command. + * + * @param \Firebird\Schema\SequenceBlueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileDropSequenceIfExists(SequenceBlueprint $blueprint, Fluent $command) + { + $sql = 'EXECUTE BLOCK' . "\n"; + $sql .= 'AS' . "\n"; + $sql .= 'BEGIN' . "\n"; + $sql .= " IF (EXISTS(SELECT * FROM RDB\$GENERATORS WHERE RDB\$GENERATOR_NAME = '" . $blueprint->getSequence() . "')) THEN" . "\n"; + $sql .= " EXECUTE STATEMENT 'DROP SEQUENCE " . $this->wrapSequence($blueprint) . "';" . "\n"; + $sql .= 'END'; + return $sql; + } + + /** + * Wrap a sequence in keyword identifiers. + * + * @param mixed $sequence + * @return string + */ + public function wrapSequence($sequence) + { + if ($sequence instanceof SequenceBlueprint) { + $sequence = $sequence->getSequence(); + } + + if ($this->isExpression($sequence)) { + return $this->getValue($sequence); + } + + return $this->wrap($this->tablePrefix . $sequence, true); + } + } diff --git a/src/Firebird/Schema/SequenceBlueprint.php b/src/Firebird/Schema/SequenceBlueprint.php new file mode 100644 index 0000000..8f13a2d --- /dev/null +++ b/src/Firebird/Schema/SequenceBlueprint.php @@ -0,0 +1,293 @@ +sequence = $sequence; + + if (!is_null($callback)) { + $callback($this); + } + } + + /** + * Execute the blueprint against the database. + * + * @param \Illuminate\Database\Connection $connection + * @param \Illuminate\Database\Schema\Grammars\Grammar $grammar + * @return void + */ + public function build(Connection $connection, Grammar $grammar) + { + foreach ($this->toSql($connection, $grammar) as $statement) { + $connection->statement($statement); + } + } + + /** + * Indicate that the table needs to be created. + * + * @return \Illuminate\Support\Fluent + */ + public function create() + { + return $this->addCommand('createSequence'); + } + + /** + * Determine if the blueprint has a create command. + * + * @return bool + */ + protected function creating() + { + foreach ($this->commands as $command) { + if ($command->name == 'createSequence') { + return true; + } + } + + return false; + } + + /** + * Determine if the blueprint has a drop command. + * + * @return bool + */ + protected function dropping() + { + foreach ($this->commands as $command) { + if ($command->name == 'dropSequence') { + return true; + } + if ($command->name == 'dropSequenceIfExists') { + return true; + } + } + + return false; + } + + /** + * Indicate that the table should be dropped. + * + * @return \Illuminate\Support\Fluent + */ + public function drop() + { + return $this->addCommand('dropSequence'); + } + + /** + * Indicate that the table should be dropped if it exists. + * + * @return \Illuminate\Support\Fluent + */ + public function dropIfExists() + { + return $this->addCommand('dropSequenceIfExists'); + } + + /** + * Add a new command to the blueprint. + * + * @param string $name + * @param array $parameters + * @return \Illuminate\Support\Fluent + */ + protected function addCommand($name, array $parameters = []) + { + $this->commands[] = $command = $this->createCommand($name, $parameters); + + return $command; + } + + /** + * Create a new Fluent command. + * + * @param string $name + * @param array $parameters + * @return \Illuminate\Support\Fluent + */ + protected function createCommand($name, array $parameters = []) + { + return new Fluent(array_merge(compact('name'), $parameters)); + } + + /** + * Get the commands on the blueprint. + * + * @return array + */ + public function getCommands() + { + return $this->commands; + } + + /** + * Get increment for the sequence + * + * @return int + */ + public function getIncrement() + { + return $this->increment; + } + + /** + * Get initial value for the sequence + * + * @return int + */ + public function getInitialValue() + { + return $this->start_with; + } + + /** + * Get the sequence the blueprint describes. + * + * @return string + */ + public function getSequence() + { + return $this->sequence; + } + + /** + * Set the sequence increment + * + * @param int $increment + */ + public function increment($increment) + { + $this->increment = $increment; + } + + /** + * Get the sequence restart flag + * + * @return bool + */ + public function isRestart() + { + return $this->restart; + } + + /** + * Set initial value for the sequence + * + * @param int $startWith + */ + public function startWith($startWith) + { + $this->start_with = $startWith; + } + + /** + * Restart sequence and set initial value + * + * @param int $startWith + */ + public function restart($startWith = null) + { + $this->restart = true; + $this->start_with = $startWith; + } + + /** + * Add the commands that are implied by the blueprint. + * + * @return void + */ + protected function addImpliedCommands() + { + if (($this->restart || ($this->increment !== 1)) && + !$this->creating() && + !$this->dropping()) { + array_unshift($this->commands, $this->createCommand('alterSequence')); + } + } + + /** + * 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->addImpliedCommands(); + + $statements = []; + + // Each type of command has a corresponding compiler function on the schema + // grammar which is used to build the necessary SQL statements to build + // the sequence blueprint element, so we'll just call that compilers function. + foreach ($this->commands as $command) { + $method = 'compile' . ucfirst($command->name); + + if (method_exists($grammar, $method)) { + if (!is_null($sql = $grammar->$method($this, $command, $connection))) { + $statements = array_merge($statements, (array)$sql); + } + } + } + + return $statements; + } + +}