diff --git a/composer.lock b/composer.lock index 301c194c41..28242129ae 100644 --- a/composer.lock +++ b/composer.lock @@ -1289,16 +1289,16 @@ }, { "name": "doctrine/common", - "version": "v2.6.0", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/doctrine/common.git", - "reference": "3cb33d19beb3c62f76c55e7e9683fff12e242bc8" + "reference": "311001fd9865a4d0d59efff4eac6d7dcb3f5270c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/3cb33d19beb3c62f76c55e7e9683fff12e242bc8", - "reference": "3cb33d19beb3c62f76c55e7e9683fff12e242bc8", + "url": "https://api.github.com/repos/doctrine/common/zipball/311001fd9865a4d0d59efff4eac6d7dcb3f5270c", + "reference": "311001fd9865a4d0d59efff4eac6d7dcb3f5270c", "shasum": "" }, "require": { @@ -1307,20 +1307,20 @@ "doctrine/collections": "1.*", "doctrine/inflector": "1.*", "doctrine/lexer": "1.*", - "php": "~5.5|~7.0" + "php": ">=5.3.2" }, "require-dev": { - "phpunit/phpunit": "~4.8|~5.0" + "phpunit/phpunit": "~3.7" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7.x-dev" + "dev-master": "2.5.x-dev" } }, "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" + "psr-0": { + "Doctrine\\Common\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1358,34 +1358,42 @@ "persistence", "spl" ], - "time": "2015-12-04 13:06:46" + "time": "2015-12-04 12:49:42" }, { "name": "doctrine/dbal", - "version": "v2.4.4", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "a370e5b95e509a7809d11f3d280acfc9310d464b" + "reference": "01dbcbc5cd0a913d751418e635434a18a2f2a75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/a370e5b95e509a7809d11f3d280acfc9310d464b", - "reference": "a370e5b95e509a7809d11f3d280acfc9310d464b", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/01dbcbc5cd0a913d751418e635434a18a2f2a75c", + "reference": "01dbcbc5cd0a913d751418e635434a18a2f2a75c", "shasum": "" }, "require": { - "doctrine/common": "~2.4", + "doctrine/common": ">=2.4,<2.6-dev", "php": ">=5.3.2" }, "require-dev": { - "phpunit/phpunit": "3.7.*", - "symfony/console": "~2.0" + "phpunit/phpunit": "4.*", + "symfony/console": "2.*" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." }, + "bin": [ + "bin/doctrine-dbal" + ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5.x-dev" + } + }, "autoload": { "psr-0": { "Doctrine\\DBAL\\": "lib/" @@ -1421,7 +1429,7 @@ "persistence", "queryobject" ], - "time": "2015-01-12 21:57:01" + "time": "2015-09-16 16:29:33" }, { "name": "doctrine/inflector", @@ -1857,17 +1865,17 @@ }, { "name": "friendsofsymfony/rest-bundle", - "version": "1.7.4", + "version": "1.7.6", "target-dir": "FOS/RestBundle", "source": { "type": "git", "url": "https://github.com/FriendsOfSymfony/FOSRestBundle.git", - "reference": "64ba918b1eb47acb5aa7fef1ce95623235b53775" + "reference": "f95b2f141748e9a5e2ddae833f60c38417aee8c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/64ba918b1eb47acb5aa7fef1ce95623235b53775", - "reference": "64ba918b1eb47acb5aa7fef1ce95623235b53775", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/f95b2f141748e9a5e2ddae833f60c38417aee8c3", + "reference": "f95b2f141748e9a5e2ddae833f60c38417aee8c3", "shasum": "" }, "require": { @@ -1934,12 +1942,12 @@ "email": "ever.zet@gmail.com" } ], - "description": "This Bundle provides various tools to rapidly develop RESTful API's with Symfony2", + "description": "This Bundle provides various tools to rapidly develop RESTful API's with Symfony", "homepage": "http://friendsofsymfony.github.com", "keywords": [ "rest" ], - "time": "2015-12-05 14:55:07" + "time": "2015-12-20 13:45:30" }, { "name": "friendsofsymfony/user-bundle", diff --git a/vendor/bin/doctrine-dbal b/vendor/bin/doctrine-dbal new file mode 120000 index 0000000000..58a8a89c2c --- /dev/null +++ b/vendor/bin/doctrine-dbal @@ -0,0 +1 @@ +../doctrine/dbal/bin/doctrine-dbal \ No newline at end of file diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index e010f6831d..68448f8407 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -53,6 +53,7 @@ return array( 'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib'), 'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/lib'), 'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib'), + 'Doctrine\\Common\\' => array($vendorDir . '/doctrine/common/lib'), 'DigitalOcean' => array($vendorDir . '/toin0u/digitalocean/src'), 'Ddeboer\\DataImport' => array($vendorDir . '/ddeboer/data-import/src'), 'Behat\\Transliterator' => array($vendorDir . '/behat/transliterator/src'), diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index b89a83a9c9..aa80b231f7 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -71,7 +71,6 @@ return array( 'Fhaculty\\Graph\\' => array($vendorDir . '/clue/graph/src'), 'Emojione\\' => array($vendorDir . '/emojione/emojione/lib/php/src'), 'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'), - 'Doctrine\\Common\\' => array($vendorDir . '/doctrine/common/lib/Doctrine/Common'), 'CpChart\\' => array($vendorDir . '/szymach/c-pchart/src'), 'Cocur\\Slugify\\' => array($vendorDir . '/cocur/slugify/src'), 'Chamilo\\' => array($baseDir . '/src/Chamilo'), diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 8f53a027d2..64dcd52aad 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -801,81 +801,6 @@ "string" ] }, - { - "name": "doctrine/common", - "version": "v2.6.0", - "version_normalized": "2.6.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "3cb33d19beb3c62f76c55e7e9683fff12e242bc8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/3cb33d19beb3c62f76c55e7e9683fff12e242bc8", - "reference": "3cb33d19beb3c62f76c55e7e9683fff12e242bc8", - "shasum": "" - }, - "require": { - "doctrine/annotations": "1.*", - "doctrine/cache": "1.*", - "doctrine/collections": "1.*", - "doctrine/inflector": "1.*", - "doctrine/lexer": "1.*", - "php": "~5.5|~7.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8|~5.0" - }, - "time": "2015-12-04 13:06:46", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "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" - } - ], - "description": "Common Library for Doctrine projects", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "collections", - "eventmanager", - "persistence", - "spl" - ] - }, { "name": "symfony/doctrine-bridge", "version": "v2.6.4", @@ -1423,71 +1348,6 @@ "description": "Symfony Console Component", "homepage": "https://symfony.com" }, - { - "name": "doctrine/dbal", - "version": "v2.4.4", - "version_normalized": "2.4.4.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "a370e5b95e509a7809d11f3d280acfc9310d464b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/a370e5b95e509a7809d11f3d280acfc9310d464b", - "reference": "a370e5b95e509a7809d11f3d280acfc9310d464b", - "shasum": "" - }, - "require": { - "doctrine/common": "~2.4", - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*", - "symfony/console": "~2.0" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." - }, - "time": "2015-01-12 21:57:01", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "Doctrine\\DBAL\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "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" - } - ], - "description": "Database Abstraction Layer", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "database", - "dbal", - "persistence", - "queryobject" - ] - }, { "name": "doctrine/orm", "version": "v2.4.8", @@ -5356,94 +5216,6 @@ ], "description": "JSONP callback validator." }, - { - "name": "friendsofsymfony/rest-bundle", - "version": "1.7.4", - "version_normalized": "1.7.4.0", - "target-dir": "FOS/RestBundle", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfSymfony/FOSRestBundle.git", - "reference": "64ba918b1eb47acb5aa7fef1ce95623235b53775" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/64ba918b1eb47acb5aa7fef1ce95623235b53775", - "reference": "64ba918b1eb47acb5aa7fef1ce95623235b53775", - "shasum": "" - }, - "require": { - "doctrine/inflector": "~1.0", - "php": "^5.3.9|~7.0", - "psr/log": "~1.0", - "symfony/framework-bundle": "~2.3|~3.0", - "symfony/http-kernel": "^2.3.24|~3.0", - "willdurand/jsonp-callback-validator": "~1.0", - "willdurand/negotiation": "~1.2" - }, - "conflict": { - "jms/serializer": "<0.12", - "jms/serializer-bundle": "<0.11", - "symfony/validator": ">=2.5.0,<2.5.5" - }, - "require-dev": { - "jms/serializer": "~0.13|~1.0", - "jms/serializer-bundle": "~0.12|~1.0", - "phpoption/phpoption": "~1.1.0", - "sensio/framework-extra-bundle": "~2.0|~3.0", - "sllh/php-cs-fixer-styleci-bridge": "^1.3", - "symfony/browser-kit": "~2.3|~3.0", - "symfony/dependency-injection": "~2.3|~3.0", - "symfony/form": "~2.3|~3.0", - "symfony/phpunit-bridge": "~2.7|~3.0", - "symfony/security": "~2.3|~3.0", - "symfony/serializer": "~2.3|~3.0", - "symfony/validator": "~2.3|~3.0", - "symfony/yaml": "~2.3|~3.0" - }, - "suggest": { - "jms/serializer-bundle": "Add support for advanced serialization capabilities, recommended, requires ~0.12||~1.0", - "sensio/framework-extra-bundle": "Add support for route annotations and the view response listener, requires ~3.0", - "symfony/serializer": "Add support for basic serialization capabilities and xml decoding, requires ~2.3", - "symfony/validator": "Add support for validation capabilities in the ParamFetcher, requires ~2.3" - }, - "time": "2015-12-05 14:55:07", - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "1.7-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "FOS\\RestBundle": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Lukas Kahwe Smith", - "email": "smith@pooteeweet.org" - }, - { - "name": "FriendsOfSymfony Community", - "homepage": "https://github.com/friendsofsymfony/FOSRestBundle/contributors" - }, - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com" - } - ], - "description": "This Bundle provides various tools to rapidly develop RESTful API's with Symfony2", - "homepage": "http://friendsofsymfony.github.com", - "keywords": [ - "rest" - ] - }, { "name": "sonata-project/google-authenticator", "version": "1.0.2", @@ -8485,5 +8257,241 @@ "testing", "webdriver" ] + }, + { + "name": "doctrine/common", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "311001fd9865a4d0d59efff4eac6d7dcb3f5270c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/311001fd9865a4d0d59efff4eac6d7dcb3f5270c", + "reference": "311001fd9865a4d0d59efff4eac6d7dcb3f5270c", + "shasum": "" + }, + "require": { + "doctrine/annotations": "1.*", + "doctrine/cache": "1.*", + "doctrine/collections": "1.*", + "doctrine/inflector": "1.*", + "doctrine/lexer": "1.*", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~3.7" + }, + "time": "2015-12-04 12:49:42", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Doctrine\\Common\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "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" + } + ], + "description": "Common Library for Doctrine projects", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "collections", + "eventmanager", + "persistence", + "spl" + ] + }, + { + "name": "doctrine/dbal", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "01dbcbc5cd0a913d751418e635434a18a2f2a75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/01dbcbc5cd0a913d751418e635434a18a2f2a75c", + "reference": "01dbcbc5cd0a913d751418e635434a18a2f2a75c", + "shasum": "" + }, + "require": { + "doctrine/common": ">=2.4,<2.6-dev", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "symfony/console": "2.*" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "time": "2015-09-16 16:29:33", + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Doctrine\\DBAL\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "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" + } + ], + "description": "Database Abstraction Layer", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "dbal", + "persistence", + "queryobject" + ] + }, + { + "name": "friendsofsymfony/rest-bundle", + "version": "1.7.6", + "version_normalized": "1.7.6.0", + "target-dir": "FOS/RestBundle", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfSymfony/FOSRestBundle.git", + "reference": "f95b2f141748e9a5e2ddae833f60c38417aee8c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/f95b2f141748e9a5e2ddae833f60c38417aee8c3", + "reference": "f95b2f141748e9a5e2ddae833f60c38417aee8c3", + "shasum": "" + }, + "require": { + "doctrine/inflector": "~1.0", + "php": "^5.3.9|~7.0", + "psr/log": "~1.0", + "symfony/framework-bundle": "~2.3|~3.0", + "symfony/http-kernel": "^2.3.24|~3.0", + "willdurand/jsonp-callback-validator": "~1.0", + "willdurand/negotiation": "~1.2" + }, + "conflict": { + "jms/serializer": "<0.12", + "jms/serializer-bundle": "<0.11", + "symfony/validator": ">=2.5.0,<2.5.5" + }, + "require-dev": { + "jms/serializer": "~0.13|~1.0", + "jms/serializer-bundle": "~0.12|~1.0", + "phpoption/phpoption": "~1.1.0", + "sensio/framework-extra-bundle": "~2.0|~3.0", + "sllh/php-cs-fixer-styleci-bridge": "^1.3", + "symfony/browser-kit": "~2.3|~3.0", + "symfony/dependency-injection": "~2.3|~3.0", + "symfony/form": "~2.3|~3.0", + "symfony/phpunit-bridge": "~2.7|~3.0", + "symfony/security": "~2.3|~3.0", + "symfony/serializer": "~2.3|~3.0", + "symfony/validator": "~2.3|~3.0", + "symfony/yaml": "~2.3|~3.0" + }, + "suggest": { + "jms/serializer-bundle": "Add support for advanced serialization capabilities, recommended, requires ~0.12||~1.0", + "sensio/framework-extra-bundle": "Add support for route annotations and the view response listener, requires ~3.0", + "symfony/serializer": "Add support for basic serialization capabilities and xml decoding, requires ~2.3", + "symfony/validator": "Add support for validation capabilities in the ParamFetcher, requires ~2.3" + }, + "time": "2015-12-20 13:45:30", + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "1.7-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "FOS\\RestBundle": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lukas Kahwe Smith", + "email": "smith@pooteeweet.org" + }, + { + "name": "FriendsOfSymfony Community", + "homepage": "https://github.com/friendsofsymfony/FOSRestBundle/contributors" + }, + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com" + } + ], + "description": "This Bundle provides various tools to rapidly develop RESTful API's with Symfony", + "homepage": "http://friendsofsymfony.github.com", + "keywords": [ + "rest" + ] } ] diff --git a/vendor/doctrine/common/.gitignore b/vendor/doctrine/common/.gitignore new file mode 100644 index 0000000000..b15c686b46 --- /dev/null +++ b/vendor/doctrine/common/.gitignore @@ -0,0 +1,10 @@ +build/ +logs/ +reports/ +dist/ +tests/Doctrine/Tests/Common/Proxy/generated/ +vendor/ +.idea +composer.lock +doctrine-common-*.tar +doctrine-common-*.tar.gz diff --git a/vendor/doctrine/common/.gitmodules b/vendor/doctrine/common/.gitmodules new file mode 100644 index 0000000000..51f0843511 --- /dev/null +++ b/vendor/doctrine/common/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/vendor/doctrine-build-common"] + path = lib/vendor/doctrine-build-common + url = git://github.com/doctrine/doctrine-build-common.git diff --git a/vendor/doctrine/common/.travis.yml b/vendor/doctrine/common/.travis.yml new file mode 100644 index 0000000000..9c20a84b43 --- /dev/null +++ b/vendor/doctrine/common/.travis.yml @@ -0,0 +1,26 @@ +language: php + +sudo: false + +cache: + directory: + - $HOME/.composer/cache + +php: + - 5.3.3 + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - hhvm + +before_script: + - composer --prefer-source install + +script: + - ./vendor/bin/phpunit + +matrix: + allow_failures: + - php: 7.0 diff --git a/vendor/doctrine/common/LICENSE b/vendor/doctrine/common/LICENSE index 8c38cc1bc2..4a91f0bf28 100644 --- a/vendor/doctrine/common/LICENSE +++ b/vendor/doctrine/common/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2006-2015 Doctrine Project +Copyright (c) 2006-2012 Doctrine Project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/vendor/doctrine/common/build.properties b/vendor/doctrine/common/build.properties new file mode 100644 index 0000000000..ef51d207f6 --- /dev/null +++ b/vendor/doctrine/common/build.properties @@ -0,0 +1,3 @@ +# Version class and file +project.version_class = Doctrine\\Common\\Version +project.version_file = lib/Doctrine/Common/Version.php diff --git a/vendor/doctrine/common/build.xml b/vendor/doctrine/common/build.xml new file mode 100644 index 0000000000..429b7688fe --- /dev/null +++ b/vendor/doctrine/common/build.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/doctrine/common/composer.json b/vendor/doctrine/common/composer.json index a12495ab1d..4f4f2158ba 100644 --- a/vendor/doctrine/common/composer.json +++ b/vendor/doctrine/common/composer.json @@ -13,24 +13,26 @@ {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} ], "require": { - "php": "~5.5|~7.0", + "php": ">=5.3.2", "doctrine/inflector": "1.*", "doctrine/cache": "1.*", "doctrine/collections": "1.*", "doctrine/lexer": "1.*", "doctrine/annotations": "1.*" }, + "minimum-stability": "dev", "require-dev": { - "phpunit/phpunit": "~4.8|~5.0" + "phpunit/phpunit": "~3.7" }, "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } + "psr-0": { "Doctrine\\Common\\": "lib/" } }, "extra": { "branch-alias": { - "dev-master": "2.7.x-dev" + "dev-master": "2.5.x-dev" } + }, + "archive": { + "exclude": ["!vendor", "tests", "*phpunit.xml", ".travis.yml", "build.xml", "build.properties", "composer.phar"] } } diff --git a/vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php b/vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php index 78eeb35d3a..d65b9a631f 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php @@ -153,7 +153,7 @@ class ClassLoader */ public function register() { - spl_autoload_register([$this, 'loadClass']); + spl_autoload_register(array($this, 'loadClass')); } /** @@ -163,7 +163,7 @@ class ClassLoader */ public function unregister() { - spl_autoload_unregister([$this, 'loadClass']); + spl_autoload_unregister(array($this, 'loadClass')); } /** @@ -275,6 +275,6 @@ class ClassLoader { return class_exists($type, $autoload) || interface_exists($type, $autoload) - || trait_exists($type, $autoload); + || (function_exists('trait_exists') && trait_exists($type, $autoload)); } } diff --git a/vendor/doctrine/common/lib/Doctrine/Common/EventManager.php b/vendor/doctrine/common/lib/Doctrine/Common/EventManager.php index 0ee04a15a4..69eb17ec69 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/EventManager.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/EventManager.php @@ -38,7 +38,7 @@ class EventManager * * @var array */ - private $_listeners = []; + private $_listeners = array(); /** * Dispatches an event to all registered listeners. diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/AbstractManagerRegistry.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/AbstractManagerRegistry.php index 12de462943..5334d2ae16 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/AbstractManagerRegistry.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/AbstractManagerRegistry.php @@ -141,7 +141,7 @@ abstract class AbstractManagerRegistry implements ManagerRegistry */ public function getConnections() { - $connections = []; + $connections = array(); foreach ($this->connections as $name => $id) { $connections[$name] = $this->getService($id); } @@ -226,7 +226,7 @@ abstract class AbstractManagerRegistry implements ManagerRegistry */ public function getManagers() { - $dms = []; + $dms = array(); foreach ($this->managers as $name => $id) { $dms[$name] = $this->getService($id); } diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php index 586b2da2c0..404fea91a3 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php @@ -53,7 +53,7 @@ abstract class AbstractClassMetadataFactory implements ClassMetadataFactory /** * @var ClassMetadata[] */ - private $loadedMetadata = []; + private $loadedMetadata = array(); /** * @var bool @@ -110,7 +110,7 @@ abstract class AbstractClassMetadataFactory implements ClassMetadataFactory } $driver = $this->getDriver(); - $metadata = []; + $metadata = array(); foreach ($driver->getAllClassNames() as $className) { $metadata[] = $this->getMetadataFor($className); } @@ -277,7 +277,7 @@ abstract class AbstractClassMetadataFactory implements ClassMetadataFactory protected function getParentClasses($name) { // Collect parent classes, ignoring transient (not-mapped) classes. - $parentClasses = []; + $parentClasses = array(); foreach (array_reverse($this->getReflectionService()->getParentClasses($name)) as $parentClass) { if ( ! $this->getDriver()->isTransient($parentClass)) { $parentClasses[] = $parentClass; @@ -306,7 +306,7 @@ abstract class AbstractClassMetadataFactory implements ClassMetadataFactory $this->initialize(); } - $loaded = []; + $loaded = array(); $parentClasses = $this->getParentClasses($name); $parentClasses[] = $name; @@ -314,7 +314,7 @@ abstract class AbstractClassMetadataFactory implements ClassMetadataFactory // Move down the hierarchy of parent classes, starting from the topmost class $parent = null; $rootEntityFound = false; - $visited = []; + $visited = array(); $reflService = $this->getReflectionService(); foreach ($parentClasses as $className) { if (isset($this->loadedMetadata[$className])) { diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php index deb82c0c97..8bb574d92e 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php @@ -45,14 +45,14 @@ abstract class AnnotationDriver implements MappingDriver * * @var array */ - protected $paths = []; + protected $paths = array(); /** * The paths excluded from path where to look for mapping files. * * @var array */ - protected $excludePaths = []; + protected $excludePaths = array(); /** * The file extension of mapping documents. @@ -73,7 +73,7 @@ abstract class AnnotationDriver implements MappingDriver * * @var array */ - protected $entityAnnotationClasses = []; + protected $entityAnnotationClasses = array(); /** * Initializes a new AnnotationDriver that uses the given AnnotationReader for reading @@ -200,8 +200,8 @@ abstract class AnnotationDriver implements MappingDriver throw MappingException::pathRequired(); } - $classes = []; - $includedFiles = []; + $classes = array(); + $includedFiles = array(); foreach ($this->paths as $path) { if ( ! is_dir($path)) { diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php index 6ed7f6d0d5..58a740b570 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php @@ -37,7 +37,7 @@ class DefaultFileLocator implements FileLocator * * @var array */ - protected $paths = []; + protected $paths = array(); /** * The file extension of mapping documents. @@ -125,7 +125,7 @@ class DefaultFileLocator implements FileLocator */ public function getAllClassNames($globalBasename) { - $classes = []; + $classes = array(); if ($this->paths) { foreach ($this->paths as $path) { diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php index dc799d5cc8..ccc64faf8c 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php @@ -145,14 +145,11 @@ abstract class FileDriver implements MappingDriver $this->initialize(); } - if (! $this->classCache) { - return (array) $this->locator->getAllClassNames($this->globalBasename); + $classNames = (array)$this->locator->getAllClassNames($this->globalBasename); + if ($this->classCache) { + $classNames = array_merge(array_keys($this->classCache), $classNames); } - - return array_merge( - array_keys($this->classCache), - (array) $this->locator->getAllClassNames($this->globalBasename) - ); + return $classNames; } /** @@ -178,7 +175,7 @@ abstract class FileDriver implements MappingDriver */ protected function initialize() { - $this->classCache = []; + $this->classCache = array(); if (null !== $this->globalBasename) { foreach ($this->locator->getPaths() as $path) { $file = $path.'/'.$this->globalBasename.$this->locator->getFileExtension(); diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php index 50d9785bcd..26a9f3e2cb 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php @@ -39,12 +39,12 @@ class MappingDriverChain implements MappingDriver * * @var MappingDriver|null */ - private $defaultDriver; + private $defaultDriver = null; /** * @var array */ - private $drivers = []; + private $drivers = array(); /** * Gets the default driver. @@ -117,8 +117,8 @@ class MappingDriverChain implements MappingDriver */ public function getAllClassNames() { - $classNames = []; - $driverClasses = []; + $classNames = array(); + $driverClasses = array(); /* @var $driver MappingDriver */ foreach ($this->drivers AS $namespace => $driver) { diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php index efffa6aa4c..6df54b0f7a 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php @@ -44,7 +44,8 @@ class PHPDriver extends FileDriver */ public function __construct($locator, $fileExtension = null) { - parent::__construct($locator, '.php'); + $fileExtension = ".php"; + parent::__construct($locator, $fileExtension); } /** @@ -53,7 +54,6 @@ class PHPDriver extends FileDriver public function loadMetadataForClass($className, ClassMetadata $metadata) { $this->metadata = $metadata; - $this->loadMappingFile($this->locator->findMappingFile($className)); } @@ -65,6 +65,6 @@ class PHPDriver extends FileDriver $metadata = $this->metadata; include $file; - return [$metadata->getName() => $metadata]; + return array($metadata->getName() => $metadata); } } diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php index 8e37e5a7a1..df8f47700b 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php @@ -40,7 +40,7 @@ class StaticPHPDriver implements MappingDriver * * @var array */ - private $paths = []; + private $paths = array(); /** * Map of all class names. @@ -93,8 +93,8 @@ class StaticPHPDriver implements MappingDriver throw MappingException::pathRequired(); } - $classes = []; - $includedFiles = []; + $classes = array(); + $includedFiles = array(); foreach ($this->paths as $path) { if (!is_dir($path)) { diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php index 49a0584221..1f32a66c8d 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php @@ -37,14 +37,14 @@ class SymfonyFileLocator implements FileLocator * * @var array */ - protected $paths = []; + protected $paths = array(); /** * A map of mapping directory path to namespace prefix used to expand class shortnames. * * @var array */ - protected $prefixes = []; + protected $prefixes = array(); /** * File extension that is searched for. @@ -164,7 +164,7 @@ class SymfonyFileLocator implements FileLocator */ public function getAllClassNames($globalBasename = null) { - $classes = []; + $classes = array(); if ($this->paths) { foreach ((array) $this->paths as $path) { diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php index 7d01766492..e5bcb06e7c 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php @@ -31,7 +31,7 @@ class StaticReflectionService implements ReflectionService */ public function getParentClasses($class) { - return []; + return array(); } /** diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/PersistentObject.php b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/PersistentObject.php index 990642e78e..a35b71a288 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Persistence/PersistentObject.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Persistence/PersistentObject.php @@ -198,7 +198,7 @@ abstract class PersistentObject implements ObjectManagerAware throw new \InvalidArgumentException("Expected persistent object of type '".$targetClass."'"); } if (!($this->$field instanceof Collection)) { - $this->$field = new ArrayCollection($this->$field ?: []); + $this->$field = new ArrayCollection($this->$field ?: array()); } $this->$field->add($args[0]); $this->completeOwningSide($field, $targetClass, $args[0]); diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php index 7eb216bfc5..bc546902e1 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php @@ -87,7 +87,7 @@ abstract class AbstractProxyFactory /** * @var \Doctrine\Common\Proxy\ProxyDefinition[] */ - private $definitions = []; + private $definitions = array(); /** * @param \Doctrine\Common\Proxy\ProxyGenerator $proxyGenerator diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php index 925dcd1b7b..2fdeb95aa9 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php @@ -58,10 +58,10 @@ class ProxyGenerator * * @var string[]|callable[] */ - protected $placeholders = [ - 'baseProxyInterface' => Proxy::class, + protected $placeholders = array( + 'baseProxyInterface' => 'Doctrine\Common\Proxy\Proxy', 'additionalProperties' => '', - ]; + ); /** * Template used as a blueprint to generate proxies. @@ -106,7 +106,7 @@ class extends \ implements \]; + public static $lazyPropertiesDefaults = array(); @@ -129,7 +129,7 @@ class extends \ implements \__initializer__ && $this->__initializer__->__invoke($this, \'__load\', []); + $this->__initializer__ && $this->__initializer__->__invoke($this, \'__load\', array()); } /** @@ -263,12 +263,12 @@ class extends \ implements \)', $this->proxyClassTemplate, $placeholderMatches); $placeholderMatches = array_combine($placeholderMatches[0], $placeholderMatches[1]); - $placeholders = []; + $placeholders = array(); foreach ($placeholderMatches as $placeholder => $name) { $placeholders[$placeholder] = isset($this->placeholders[$name]) ? $this->placeholders[$name] - : [$this, 'generate' . $name]; + : array($this, 'generate' . $name); } foreach ($placeholders as & $placeholder) { @@ -358,7 +358,7 @@ class extends \ implements \getLazyLoadedPublicProperties($class); - $values = []; + $values = array(); foreach ($lazyPublicProperties as $key => $value) { $values[] = var_export($key, true) . ' => ' . var_export($value, true); @@ -385,7 +385,7 @@ class extends \ implements \getLazyLoadedPublicProperties($class) as $lazyPublicProperty => $unused) { $toUnset[] = '$this->' . $lazyPublicProperty; @@ -443,7 +443,7 @@ EOT; if ( ! empty($lazyPublicProperties)) { $magicGet .= <<<'EOT' if (array_key_exists($name, $this->__getLazyProperties())) { - $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', [$name]); + $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', array($name)); return $this->$name; } @@ -454,7 +454,7 @@ EOT; if ($hasParentGet) { $magicGet .= <<<'EOT' - $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', [$name]); + $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', array($name)); return parent::__get($name); @@ -502,7 +502,7 @@ EOT; if ( ! empty($lazyPublicProperties)) { $magicSet .= <<<'EOT' if (array_key_exists($name, $this->__getLazyProperties())) { - $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', [$name, $value]); + $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', array($name, $value)); $this->$name = $value; @@ -515,7 +515,7 @@ EOT; if ($hasParentSet) { $magicSet .= <<<'EOT' - $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', [$name, $value]); + $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', array($name, $value)); return parent::__set($name, $value); EOT; @@ -559,7 +559,7 @@ EOT; if ( ! empty($lazyPublicProperties)) { $magicIsset .= <<<'EOT' if (array_key_exists($name, $this->__getLazyProperties())) { - $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', [$name]); + $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', array($name)); return isset($this->$name); } @@ -570,7 +570,7 @@ EOT; if ($hasParentIsset) { $magicIsset .= <<<'EOT' - $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', [$name]); + $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', array($name)); return parent::__isset($name); @@ -605,7 +605,7 @@ EOT; if ($hasParentSleep) { return $sleepImpl . <<<'EOT' - $properties = array_merge(['__isInitialized__'], parent::__sleep()); + $properties = array_merge(array('__isInitialized__'), parent::__sleep()); if ($this->__isInitialized__) { $properties = array_diff($properties, array_keys($this->__getLazyProperties())); @@ -616,7 +616,7 @@ EOT; EOT; } - $allProperties = ['__isInitialized__']; + $allProperties = array('__isInitialized__'); /* @var $prop \ReflectionProperty */ foreach ($class->getReflectionClass()->getProperties() as $prop) { @@ -645,10 +645,10 @@ EOT; return $sleepImpl . <<__isInitialized__) { - return [$allProperties]; + return array($allProperties); } - return [$protectedProperties]; + return array($protectedProperties); } EOT; } @@ -662,7 +662,7 @@ EOT; */ private function generateWakeupImpl(ClassMetadata $class) { - $unsetPublicProperties = []; + $unsetPublicProperties = array(); $hasWakeup = $class->getReflectionClass()->hasMethod('__wakeup'); foreach (array_keys($this->getLazyLoadedPublicProperties($class)) as $lazyPublicProperty) { @@ -727,7 +727,7 @@ EOT; */ public function __clone() { - \$this->__cloner__ && \$this->__cloner__->__invoke(\$this, '__clone', []); + \$this->__cloner__ && \$this->__cloner__->__invoke(\$this, '__clone', array()); $callParentClone } EOT; } @@ -742,16 +742,16 @@ EOT; private function generateMethods(ClassMetadata $class) { $methods = ''; - $methodNames = []; + $methodNames = array(); $reflectionMethods = $class->getReflectionClass()->getMethods(\ReflectionMethod::IS_PUBLIC); - $skippedMethods = [ + $skippedMethods = array( '__sleep' => true, '__clone' => true, '__wakeup' => true, '__get' => true, '__set' => true, '__isset' => true, - ]; + ); foreach ($reflectionMethods as $method) { $name = $method->getName(); @@ -778,13 +778,12 @@ EOT; } $methods .= $name . '(' . $this->buildParametersString($class, $method, $method->getParameters()) . ')'; - $methods .= $this->getMethodReturnType($method); $methods .= "\n" . ' {' . "\n"; if ($this->isShortIdentifierGetter($method, $class)) { $identifier = lcfirst(substr($name, 3)); $fieldType = $class->getTypeOfField($identifier); - $cast = in_array($fieldType, ['integer', 'smallint']) ? '(int) ' : ''; + $cast = in_array($fieldType, array('integer', 'smallint')) ? '(int) ' : ''; $methods .= ' if ($this->__isInitialized__ === false) {' . "\n"; $methods .= ' return ' . $cast . ' parent::' . $method->getName() . "();\n"; @@ -796,7 +795,7 @@ EOT; $methods .= "\n \$this->__initializer__ " . "&& \$this->__initializer__->__invoke(\$this, " . var_export($name, true) - . ", [" . $invokeParamsString . "]);" + . ", array(" . $invokeParamsString . "));" . "\n\n return parent::" . $name . '(' . $callParamsString . ');' . "\n" . ' }' . "\n"; } @@ -873,7 +872,7 @@ EOT; private function getLazyLoadedPublicProperties(ClassMetadata $class) { $defaultProperties = $class->getReflectionClass()->getDefaultProperties(); - $properties = []; + $properties = array(); foreach ($class->getReflectionClass()->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { $name = $property->getName(); @@ -895,7 +894,7 @@ EOT; */ private function buildParametersString(ClassMetadata $class, \ReflectionMethod $method, array $parameters) { - $parameterDefinitions = []; + $parameterDefinitions = array(); /* @var $param \ReflectionParameter */ foreach ($parameters as $param) { @@ -909,8 +908,10 @@ EOT; $parameterDefinition .= '&'; } - if (method_exists($param, 'isVariadic') && $param->isVariadic()) { - $parameterDefinition .= '...'; + if (method_exists($param, 'isVariadic')) { + if ($param->isVariadic()) { + $parameterDefinition .= '...'; + } } $parameters[] = '$' . $param->getName(); @@ -941,14 +942,10 @@ EOT; return 'array'; } - if ($parameter->isCallable()) { + if (method_exists($parameter, 'isCallable') && $parameter->isCallable()) { return 'callable'; } - if (method_exists($parameter, 'hasType') && $parameter->hasType() && $parameter->getType()->isBuiltin()) { - return (string) $parameter->getType(); - } - try { $parameterClass = $parameter->getClass(); @@ -993,8 +990,10 @@ EOT; function (\ReflectionParameter $parameter) { $name = ''; - if (method_exists($parameter, 'isVariadic') && $parameter->isVariadic()) { - $name .= '...'; + if (method_exists($parameter, 'isVariadic')) { + if ($parameter->isVariadic()) { + $name .= '...'; + } } $name .= '$' . $parameter->getName(); @@ -1004,34 +1003,4 @@ EOT; $parameters ); } - - /** - * @Param \ReflectionMethod $method - * - * @return string - */ - private function getMethodReturnType(\ReflectionMethod $method) - { - if (! (method_exists($method, 'hasReturnType') && $method->hasReturnType())) { - return ''; - } - - $returnType = $method->getReturnType(); - - if ($returnType->isBuiltin()) { - return ': ' . $returnType; - } - - $nameLower = strtolower((string) $returnType); - - if ('self' === $nameLower) { - return ': \\' . $method->getDeclaringClass()->getName(); - } - - if ('parent' === $nameLower) { - return ': \\' . $method->getDeclaringClass()->getParentClass()->getName(); - } - - return ': \\' . (string) $returnType; - } } diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionClass.php b/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionClass.php index 2d0f5b0077..b65979add3 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionClass.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionClass.php @@ -402,7 +402,7 @@ class StaticReflectionClass extends ReflectionClass /** * {@inheritDoc} */ - public function newInstanceArgs(array $args = []) + public function newInstanceArgs(array $args = array()) { throw new ReflectionException('Method not implemented'); } diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionParser.php b/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionParser.php index c48e9ba73a..922404d987 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionParser.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionParser.php @@ -69,18 +69,18 @@ class StaticReflectionParser implements ReflectionProviderInterface * * @var array */ - protected $useStatements = []; + protected $useStatements = array(); /** * The docComment of the class. * * @var string */ - protected $docComment = [ + protected $docComment = array( 'class' => '', - 'property' => [], - 'method' => [] - ]; + 'property' => array(), + 'method' => array() + ); /** * The name of the class this class extends, if any. diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php b/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php index 7f6522bbac..79b40d4a0c 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php @@ -91,7 +91,7 @@ class StaticReflectionProperty extends ReflectionProperty /** * {@inheritDoc} */ - public static function export($class, $name, $return = false) + public static function export ($class, $name, $return = false) { throw new ReflectionException('Method not implemented'); } @@ -155,7 +155,7 @@ class StaticReflectionProperty extends ReflectionProperty /** * {@inheritDoc} */ - public function setAccessible($accessible) + public function setAccessible ($accessible) { throw new ReflectionException('Method not implemented'); } @@ -163,7 +163,7 @@ class StaticReflectionProperty extends ReflectionProperty /** * {@inheritDoc} */ - public function setValue($object, $value = null) + public function setValue ($object, $value = null) { throw new ReflectionException('Method not implemented'); } diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php b/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php index 7f675328f8..0959ce5d5b 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php @@ -19,7 +19,6 @@ namespace Doctrine\Common\Util; -use Doctrine\Common\Collections\Collection; use Doctrine\Common\Persistence\Proxy; /** @@ -96,13 +95,13 @@ final class Debug $return = null; $isObj = is_object($var); - if ($var instanceof Collection) { + if ($isObj && in_array('Doctrine\Common\Collections\Collection', class_implements($var))) { $var = $var->toArray(); } if ($maxDepth) { if (is_array($var)) { - $return = []; + $return = array(); foreach ($var as $k => $v) { $return[$k] = self::export($v, $maxDepth - 1); diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Version.php b/vendor/doctrine/common/lib/Doctrine/Common/Version.php index 47e0fcf5b7..fbb6532395 100644 --- a/vendor/doctrine/common/lib/Doctrine/Common/Version.php +++ b/vendor/doctrine/common/lib/Doctrine/Common/Version.php @@ -34,7 +34,7 @@ class Version /** * Current Doctrine Version. */ - const VERSION = '2.6.0'; + const VERSION = '2.5.2'; /** * Compares a Doctrine version with the current one. diff --git a/vendor/doctrine/common/phpunit.xml.dist b/vendor/doctrine/common/phpunit.xml.dist new file mode 100644 index 0000000000..f6fcf84984 --- /dev/null +++ b/vendor/doctrine/common/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + + ./tests/Doctrine/ + + + + + + ./lib/Doctrine/ + + + diff --git a/vendor/doctrine/common/tests/.gitignore b/vendor/doctrine/common/tests/.gitignore new file mode 100644 index 0000000000..7210405266 --- /dev/null +++ b/vendor/doctrine/common/tests/.gitignore @@ -0,0 +1,3 @@ +Doctrine/Tests/Proxies/ +Doctrine/Tests/ORM/Proxy/generated/ +Doctrine/Tests/ORM/Tools/Export/export diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/ClassLoaderTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/ClassLoaderTest.php new file mode 100644 index 0000000000..801a685835 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/ClassLoaderTest.php @@ -0,0 +1,133 @@ +setIncludePath(__DIR__); + $classLoader->setFileExtension('.class.php'); + $classLoader->setNamespaceSeparator('_'); + + $this->assertTrue($classLoader->canLoadClass('ClassLoaderTest_ClassA')); + $this->assertTrue($classLoader->canLoadClass('ClassLoaderTest_ClassB')); + $this->assertTrue($classLoader->canLoadClass('ClassLoaderTest_ClassC')); + $this->assertFalse($classLoader->canLoadClass('OtherClass')); + $this->assertEquals($classLoader->loadClass('ClassLoaderTest_ClassA'), true); + $this->assertEquals($classLoader->loadClass('ClassLoaderTest_ClassB'), true); + $this->assertEquals($classLoader->loadClass('ClassLoaderTest_ClassC'), true); + } + + public function testClassExists() + { + $this->assertFalse(ClassLoader::classExists('ClassLoaderTest\ClassD')); + $badLoader = function($className) { + require __DIR__ . '/ClassLoaderTest/ClassD.php'; + return true; + }; + spl_autoload_register($badLoader); + $this->assertTrue(ClassLoader::classExists('ClassLoaderTest\ClassD')); + spl_autoload_unregister($badLoader); + } + + public function testGetClassLoader() + { + $cl = new ClassLoader('ClassLoaderTest', __DIR__); + $cl->register(); + $this->assertTrue(ClassLoader::getClassLoader('ClassLoaderTest\ClassD') instanceof \Doctrine\Common\ClassLoader); + $this->assertNull(ClassLoader::getClassLoader('This\Class\Does\Not\Exist')); + $cl->unregister(); + } + + public function testClassExistsWithSilentAutoloader() + { + $test = $this; + $silentLoader = function ($className) use ($test) { + $test->assertSame('ClassLoaderTest\ClassE', $className); + require __DIR__ . '/ClassLoaderTest/ClassE.php'; + }; + $additionalLoader = function () use ($test) { + $test->fail('Should not call this loader, class was already loaded'); + }; + + $this->assertFalse(ClassLoader::classExists('ClassLoaderTest\ClassE')); + spl_autoload_register($silentLoader); + spl_autoload_register($additionalLoader); + $this->assertTrue(ClassLoader::classExists('ClassLoaderTest\ClassE')); + spl_autoload_unregister($additionalLoader); + spl_autoload_unregister($silentLoader); + } + + public function testClassExistsWhenLoaderIsProtected() + { + require_once __DIR__ . '/ClassLoaderTest/ExternalLoader.php'; + + // Test static call + \ClassLoaderTest\ExternalLoader::registerStatic(); + $this->assertFalse(ClassLoader::classExists('ClassLoaderTest\Class\That\Does\Not\Exist')); + \ClassLoaderTest\ExternalLoader::unregisterStatic(); + + // Test object + $loader = new \ClassLoaderTest\ExternalLoader(); + $loader->register(); + $this->assertFalse(ClassLoader::classExists('ClassLoaderTest\Class\That\Does\Not\Exist')); + $loader->unregister(); + } + + public function testLoadNonExistingClass() + { + $classLoader = new ClassLoader('ClassLoaderTest', __DIR__); + + $this->assertFalse($classLoader->loadClass('ClassLoaderTest\Non\Existing\ClassName')); + } + + public function testLoadFileNotContainingClassClass() + { + $classLoader = new ClassLoader('ClassLoaderTest', __DIR__); + + $classLoader->setFileExtension('.class.php'); + + $this->assertFalse($classLoader->loadClass('ClassLoaderTest\EmptyFile')); + } + + public function testSupportsInterfaceAutoloading() + { + $classLoader = new ClassLoader(); + $classLoader->setIncludePath(__DIR__); + $classLoader->setFileExtension('.class.php'); + $classLoader->setNamespaceSeparator('_'); + + $this->assertTrue($classLoader->loadClass('ClassLoaderTest_InterfaceA')); + $this->assertTrue(interface_exists('ClassLoaderTest_InterfaceA', false)); + } + + public function testSupportsTraitAutoloading() + { + if (! function_exists('trait_exists')) { + $this->markTestSkipped('You need a PHP version that supports traits in order to run this test'); + } + + $classLoader = new ClassLoader(); + $classLoader->setIncludePath(__DIR__); + $classLoader->setFileExtension('.class.php'); + $classLoader->setNamespaceSeparator('_'); + + $this->assertTrue($classLoader->loadClass('ClassLoaderTest_TraitA')); + $this->assertTrue(trait_exists('ClassLoaderTest_TraitA', false)); + } + + public function testMultipleAutoloadRequestsWillProduceSameResult() + { + $classLoader = new ClassLoader(); + $classLoader->setIncludePath(__DIR__); + $classLoader->setFileExtension('.class.php'); + $classLoader->setNamespaceSeparator('_'); + + $this->assertTrue($classLoader->loadClass('ClassLoaderTest_ClassA')); + $this->assertTrue($classLoader->loadClass('ClassLoaderTest_ClassA')); + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/ClassLoaderTest/ClassA.class.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/ClassLoaderTest/ClassA.class.php new file mode 100644 index 0000000000..8554654738 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/ClassLoaderTest/ClassA.class.php @@ -0,0 +1,6 @@ +_eventManager = new EventManager; + $this->_preFooInvoked = false; + $this->_postFooInvoked = false; + } + + public function testInitialState() + { + $this->assertEquals(array(), $this->_eventManager->getListeners()); + $this->assertFalse($this->_eventManager->hasListeners(self::preFoo)); + $this->assertFalse($this->_eventManager->hasListeners(self::postFoo)); + } + + public function testAddEventListener() + { + $this->_eventManager->addEventListener(array('preFoo', 'postFoo'), $this); + $this->assertTrue($this->_eventManager->hasListeners(self::preFoo)); + $this->assertTrue($this->_eventManager->hasListeners(self::postFoo)); + $this->assertEquals(1, count($this->_eventManager->getListeners(self::preFoo))); + $this->assertEquals(1, count($this->_eventManager->getListeners(self::postFoo))); + $this->assertEquals(2, count($this->_eventManager->getListeners())); + } + + public function testDispatchEvent() + { + $this->_eventManager->addEventListener(array('preFoo', 'postFoo'), $this); + $this->_eventManager->dispatchEvent(self::preFoo); + $this->assertTrue($this->_preFooInvoked); + $this->assertFalse($this->_postFooInvoked); + } + + public function testRemoveEventListener() + { + $this->_eventManager->addEventListener(array('preBar'), $this); + $this->assertTrue($this->_eventManager->hasListeners(self::preBar)); + $this->_eventManager->removeEventListener(array('preBar'), $this); + $this->assertFalse($this->_eventManager->hasListeners(self::preBar)); + } + + public function testAddEventSubscriber() + { + $eventSubscriber = new TestEventSubscriber(); + $this->_eventManager->addEventSubscriber($eventSubscriber); + $this->assertTrue($this->_eventManager->hasListeners(self::preFoo)); + $this->assertTrue($this->_eventManager->hasListeners(self::postFoo)); + } + + /* Listener methods */ + + public function preFoo(EventArgs $e) + { + $this->_preFooInvoked = true; + } + + public function postFoo(EventArgs $e) + { + $this->_postFooInvoked = true; + } +} + +class TestEventSubscriber implements \Doctrine\Common\EventSubscriber +{ + public function getSubscribedEvents() + { + return array('preFoo', 'postFoo'); + } +} \ No newline at end of file diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/ManagerRegistryTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/ManagerRegistryTest.php new file mode 100644 index 0000000000..9129858fcb --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/ManagerRegistryTest.php @@ -0,0 +1,102 @@ +mr = new TestManagerRegistry( + 'ORM', + array('default_connection'), + array('default_manager'), + 'default', + 'default', + 'Doctrine\Common\Persistence\ObjectManagerAware' + ); + } + + public function testGetManagerForClass() + { + $this->mr->getManagerForClass('Doctrine\Tests\Common\Persistence\TestObject'); + } + + public function testGetManagerForProxyInterface() + { + $this->assertNull($this->mr->getManagerForClass('Doctrine\Common\Persistence\ObjectManagerAware')); + } + + public function testGetManagerForInvalidClass() + { + $this->setExpectedException( + 'ReflectionException', + 'Class Doctrine\Tests\Common\Persistence\TestObjectInexistent does not exist' + ); + + $this->mr->getManagerForClass('prefix:TestObjectInexistent'); + } + + public function testGetManagerForAliasedClass() + { + $this->mr->getManagerForClass('prefix:TestObject'); + } + + public function testGetManagerForInvalidAliasedClass() + { + $this->setExpectedException( + 'ReflectionException', + 'Class Doctrine\Tests\Common\Persistence\TestObject:Foo does not exist' + ); + + $this->mr->getManagerForClass('prefix:TestObject:Foo'); + } +} + +class TestManager extends PHPUnit_Framework_TestCase +{ + public function getMetadataFactory() + { + $driver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + + return new TestClassMetadataFactory($driver, $metadata); + } +} + +class TestManagerRegistry extends AbstractManagerRegistry +{ + protected function getService($name) + { + return new TestManager(); + } + + /** + * {@inheritdoc} + */ + protected function resetService($name) + { + + } + + public function getAliasNamespace($alias) + { + return __NAMESPACE__; + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/AnnotationDriverTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/AnnotationDriverTest.php new file mode 100644 index 0000000000..ab6cc5ce46 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/AnnotationDriverTest.php @@ -0,0 +1,29 @@ +getAllClassNames(); + + $this->assertEquals(array('Doctrine\TestClass'), $classes); + } +} + +class SimpleAnnotationDriver extends AnnotationDriver +{ + protected $entityAnnotationClasses = array('Doctrine\Entity' => true); + + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/ChainDriverTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/ChainDriverTest.php new file mode 100644 index 0000000000..f9edd10f09 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/ChainDriverTest.php @@ -0,0 +1,152 @@ +getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + + $chain = new MappingDriverChain(); + + $driver1 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $driver1->expects($this->never()) + ->method('loadMetadataForClass'); + $driver1->expectS($this->never()) + ->method('isTransient'); + + $driver2 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $driver2->expects($this->at(0)) + ->method('loadMetadataForClass') + ->with($this->equalTo($className), $this->equalTo($classMetadata)); + $driver2->expects($this->at(1)) + ->method('isTransient') + ->with($this->equalTo($className)) + ->will($this->returnValue( true )); + + $chain->addDriver($driver1, 'Doctrine\Tests\Models\Company'); + $chain->addDriver($driver2, 'Doctrine\Tests\Common\Persistence\Mapping'); + + $chain->loadMetadataForClass($className, $classMetadata); + + $this->assertTrue( $chain->isTransient($className) ); + } + + public function testLoadMetadata_NoDelegatorFound_ThrowsMappingException() + { + $className = 'Doctrine\Tests\Common\Persistence\Mapping\DriverChainEntity'; + $classMetadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + + $chain = new MappingDriverChain(); + + $this->setExpectedException('Doctrine\Common\Persistence\Mapping\MappingException'); + $chain->loadMetadataForClass($className, $classMetadata); + } + + public function testGatherAllClassNames() + { + $className = 'Doctrine\Tests\Common\Persistence\Mapping\DriverChainEntity'; + $classMetadata = $this->getMock('Doctrine\Common\Persistence\ClassMetadata'); + + $chain = new MappingDriverChain(); + + $driver1 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $driver1->expects($this->once()) + ->method('getAllClassNames') + ->will($this->returnValue(array('Doctrine\Tests\Models\Company\Foo'))); + + $driver2 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $driver2->expects($this->once()) + ->method('getAllClassNames') + ->will($this->returnValue(array('Doctrine\Tests\ORM\Mapping\Bar', 'Doctrine\Tests\ORM\Mapping\Baz', 'FooBarBaz'))); + + $chain->addDriver($driver1, 'Doctrine\Tests\Models\Company'); + $chain->addDriver($driver2, 'Doctrine\Tests\ORM\Mapping'); + + $this->assertEquals(array( + 'Doctrine\Tests\Models\Company\Foo', + 'Doctrine\Tests\ORM\Mapping\Bar', + 'Doctrine\Tests\ORM\Mapping\Baz' + ), $chain->getAllClassNames()); + } + + /** + * @group DDC-706 + */ + public function testIsTransient() + { + $driver1 = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $chain = new MappingDriverChain(); + $chain->addDriver($driver1, 'Doctrine\Tests\Models\CMS'); + + $this->assertTrue($chain->isTransient('stdClass'), "stdClass isTransient"); + } + + /** + * @group DDC-1412 + */ + public function testDefaultDriver() + { + $companyDriver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $defaultDriver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $entityClassName = 'Doctrine\Tests\ORM\Mapping\DriverChainEntity'; + $managerClassName = 'Doctrine\Tests\Models\Company\CompanyManager'; + $chain = new MappingDriverChain(); + + $companyDriver->expects($this->never()) + ->method('loadMetadataForClass'); + $companyDriver->expects($this->once()) + ->method('isTransient') + ->with($this->equalTo($managerClassName)) + ->will($this->returnValue(false)); + + $defaultDriver->expects($this->never()) + ->method('loadMetadataForClass'); + $defaultDriver->expects($this->once()) + ->method('isTransient') + ->with($this->equalTo($entityClassName)) + ->will($this->returnValue(true)); + + $this->assertNull($chain->getDefaultDriver()); + + $chain->setDefaultDriver($defaultDriver); + $chain->addDriver($companyDriver, 'Doctrine\Tests\Models\Company'); + + $this->assertSame($defaultDriver, $chain->getDefaultDriver()); + + $this->assertTrue($chain->isTransient($entityClassName)); + $this->assertFalse($chain->isTransient($managerClassName)); + } + + public function testDefaultDriverGetAllClassNames() + { + $companyDriver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $defaultDriver = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $chain = new MappingDriverChain(); + + $companyDriver->expects($this->once()) + ->method('getAllClassNames') + ->will($this->returnValue(array('Doctrine\Tests\Models\Company\Foo'))); + + $defaultDriver->expects($this->once()) + ->method('getAllClassNames') + ->will($this->returnValue(array('Other\Class'))); + + $chain->setDefaultDriver($defaultDriver); + $chain->addDriver($companyDriver, 'Doctrine\Tests\Models\Company'); + + $classNames = $chain->getAllClassNames(); + + $this->assertEquals(array('Doctrine\Tests\Models\Company\Foo', 'Other\Class'), $classNames); + } +} + +class DriverChainEntity +{ + +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/ClassMetadataFactoryTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/ClassMetadataFactoryTest.php new file mode 100644 index 0000000000..b3815de97c --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/ClassMetadataFactoryTest.php @@ -0,0 +1,209 @@ +getMock('Doctrine\Common\Persistence\Mapping\Driver\MappingDriver'); + $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + $this->cmf = new TestClassMetadataFactory($driver, $metadata); + } + + public function testGetCacheDriver() + { + $this->assertNull($this->cmf->getCacheDriver()); + $cache = new ArrayCache(); + $this->cmf->setCacheDriver($cache); + $this->assertSame($cache, $this->cmf->getCacheDriver()); + } + + public function testGetMetadataFor() + { + $metadata = $this->cmf->getMetadataFor('stdClass'); + + $this->assertInstanceOf('Doctrine\Common\Persistence\Mapping\ClassMetadata', $metadata); + $this->assertTrue($this->cmf->hasMetadataFor('stdClass')); + } + + public function testGetMetadataForAbsentClass() + { + $this->setExpectedException('Doctrine\Common\Persistence\Mapping\MappingException'); + $this->cmf->getMetadataFor(__NAMESPACE__ . '\AbsentClass'); + } + + public function testGetParentMetadata() + { + $metadata = $this->cmf->getMetadataFor(__NAMESPACE__ . '\ChildEntity'); + + $this->assertInstanceOf('Doctrine\Common\Persistence\Mapping\ClassMetadata', $metadata); + $this->assertTrue($this->cmf->hasMetadataFor(__NAMESPACE__ . '\ChildEntity')); + $this->assertTrue($this->cmf->hasMetadataFor(__NAMESPACE__ . '\RootEntity')); + } + + public function testGetCachedMetadata() + { + $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + $cache = new ArrayCache(); + $cache->save(__NAMESPACE__. '\ChildEntity$CLASSMETADATA', $metadata); + + $this->cmf->setCacheDriver($cache); + + $loadedMetadata = $this->cmf->getMetadataFor(__NAMESPACE__ . '\ChildEntity'); + $this->assertSame($loadedMetadata, $metadata); + } + + public function testCacheGetMetadataFor() + { + $cache = new ArrayCache(); + $this->cmf->setCacheDriver($cache); + + $loadedMetadata = $this->cmf->getMetadataFor(__NAMESPACE__ . '\ChildEntity'); + + $this->assertSame($loadedMetadata, $cache->fetch(__NAMESPACE__. '\ChildEntity$CLASSMETADATA')); + } + + public function testGetAliasedMetadata() + { + $this->cmf->getMetadataFor('prefix:ChildEntity'); + + $this->assertTrue($this->cmf->hasMetadataFor(__NAMESPACE__ . '\ChildEntity')); + $this->assertTrue($this->cmf->hasMetadataFor('prefix:ChildEntity')); + } + + /** + * @group DCOM-270 + */ + public function testGetInvalidAliasedMetadata() + { + $this->setExpectedException( + 'Doctrine\Common\Persistence\Mapping\MappingException', + 'Class \'Doctrine\Tests\Common\Persistence\Mapping\ChildEntity:Foo\' does not exist' + ); + + $this->cmf->getMetadataFor('prefix:ChildEntity:Foo'); + } + + /** + * @group DCOM-270 + */ + public function testClassIsTransient() + { + $this->assertTrue($this->cmf->isTransient('prefix:ChildEntity:Foo')); + } + + public function testWillFallbackOnNotLoadedMetadata() + { + $classMetadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + + $this->cmf->fallbackCallback = function () use ($classMetadata) { + return $classMetadata; + }; + + $this->cmf->metadata = null; + + $this->assertSame($classMetadata, $this->cmf->getMetadataFor('Foo')); + } + + public function testWillFailOnFallbackFailureWithNotLoadedMetadata() + { + $this->cmf->fallbackCallback = function () { + return null; + }; + + $this->cmf->metadata = null; + + $this->setExpectedException('Doctrine\Common\Persistence\Mapping\MappingException'); + + $this->cmf->getMetadataFor('Foo'); + } +} + +class TestClassMetadataFactory extends AbstractClassMetadataFactory +{ + public $driver; + public $metadata; + + /** @var callable|null */ + public $fallbackCallback; + + public function __construct($driver, $metadata) + { + $this->driver = $driver; + $this->metadata = $metadata; + } + + protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents) + { + + } + + protected function getFqcnFromAlias($namespaceAlias, $simpleClassName) + { + return __NAMESPACE__ . '\\' . $simpleClassName; + } + + protected function initialize() + { + + } + + protected function newClassMetadataInstance($className) + { + return $this->metadata; + } + + protected function getDriver() + { + return $this->driver; + } + protected function wakeupReflection(ClassMetadata $class, ReflectionService $reflService) + { + } + + protected function initializeReflection(ClassMetadata $class, ReflectionService $reflService) + { + } + + protected function isEntity(ClassMetadata $class) + { + return true; + } + + protected function onNotFoundMetadata($className) + { + if (! $fallback = $this->fallbackCallback) { + return null; + } + + return $fallback(); + } + + public function isTransient($class) + { + return true; + } +} + +class RootEntity +{ + +} + +class ChildEntity extends RootEntity +{ + +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/DefaultFileLocatorTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/DefaultFileLocatorTest.php new file mode 100644 index 0000000000..d25d0d745b --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/DefaultFileLocatorTest.php @@ -0,0 +1,98 @@ +assertEquals(array($path), $locator->getPaths()); + + $locator = new DefaultFileLocator($path); + $this->assertEquals(array($path), $locator->getPaths()); + } + + public function testGetFileExtension() + { + $locator = new DefaultFileLocator(array(), ".yml"); + $this->assertEquals(".yml", $locator->getFileExtension()); + $locator->setFileExtension(".xml"); + $this->assertEquals(".xml", $locator->getFileExtension()); + } + + public function testUniquePaths() + { + $path = __DIR__ . "/_files"; + + $locator = new DefaultFileLocator(array($path, $path)); + $this->assertEquals(array($path), $locator->getPaths()); + } + + public function testFindMappingFile() + { + $path = __DIR__ . "/_files"; + + $locator = new DefaultFileLocator(array($path), ".yml"); + + $this->assertEquals(__DIR__ . '/_files' . DIRECTORY_SEPARATOR . 'stdClass.yml', $locator->findMappingFile('stdClass')); + } + + public function testFindMappingFileNotFound() + { + $path = __DIR__ . "/_files"; + + $locator = new DefaultFileLocator(array($path), ".yml"); + + $this->setExpectedException( + 'Doctrine\Common\Persistence\Mapping\MappingException', + "No mapping file found named 'stdClass2.yml' for class 'stdClass2'" + ); + $locator->findMappingFile('stdClass2'); + } + + public function testGetAllClassNames() + { + $path = __DIR__ . "/_files"; + + $locator = new DefaultFileLocator(array($path), ".yml"); + $allClasses = $locator->getAllClassNames(null); + $globalClasses = $locator->getAllClassNames("global"); + + $expectedAllClasses = array('global', 'stdClass', 'subDirClass'); + $expectedGlobalClasses = array('subDirClass', 'stdClass'); + + sort($allClasses); + sort($globalClasses); + sort($expectedAllClasses); + sort($expectedGlobalClasses); + + $this->assertEquals($expectedAllClasses, $allClasses); + $this->assertEquals($expectedGlobalClasses, $globalClasses); + } + + public function testGetAllClassNamesNonMatchingFileExtension() + { + $path = __DIR__ . "/_files"; + + $locator = new DefaultFileLocator(array($path), ".xml"); + $this->assertEquals(array(), $locator->getAllClassNames("global")); + } + + public function testFileExists() + { + $path = __DIR__ . "/_files"; + + $locator = new DefaultFileLocator(array($path), ".yml"); + + $this->assertTrue($locator->fileExists("stdClass")); + $this->assertFalse($locator->fileExists("stdClass2")); + $this->assertTrue($locator->fileExists("global")); + $this->assertFalse($locator->fileExists("global2")); + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/FileDriverTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/FileDriverTest.php new file mode 100644 index 0000000000..020c242474 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/FileDriverTest.php @@ -0,0 +1,142 @@ +assertNull($driver->getGlobalBasename()); + + $driver->setGlobalBasename("global"); + $this->assertEquals("global", $driver->getGlobalBasename()); + } + + public function testGetElementFromGlobalFile() + { + $driver = new TestFileDriver($this->newLocator()); + $driver->setGlobalBasename("global"); + + $element = $driver->getElement('stdGlobal'); + + $this->assertEquals('stdGlobal', $element); + } + + public function testGetElementFromFile() + { + $locator = $this->newLocator(); + $locator->expects($this->once()) + ->method('findMappingFile') + ->with($this->equalTo('stdClass')) + ->will($this->returnValue(__DIR__ . '/_files/stdClass.yml')); + + $driver = new TestFileDriver($locator); + + $this->assertEquals('stdClass', $driver->getElement('stdClass')); + } + + public function testGetAllClassNamesGlobalBasename() + { + $driver = new TestFileDriver($this->newLocator()); + $driver->setGlobalBasename("global"); + + $classNames = $driver->getAllClassNames(); + + $this->assertEquals(array('stdGlobal', 'stdGlobal2'), $classNames); + } + + public function testGetAllClassNamesFromMappingFile() + { + $locator = $this->newLocator(); + $locator->expects($this->any()) + ->method('getAllClassNames') + ->with($this->equalTo(null)) + ->will($this->returnValue(array('stdClass'))); + $driver = new TestFileDriver($locator); + + $classNames = $driver->getAllClassNames(); + + $this->assertEquals(array('stdClass'), $classNames); + } + + public function testGetAllClassNamesBothSources() + { + $locator = $this->newLocator(); + $locator->expects($this->any()) + ->method('getAllClassNames') + ->with($this->equalTo('global')) + ->will($this->returnValue(array('stdClass'))); + $driver = new TestFileDriver($locator); + $driver->setGlobalBasename("global"); + + $classNames = $driver->getAllClassNames(); + + $this->assertEquals(array('stdGlobal', 'stdGlobal2', 'stdClass'), $classNames); + } + + public function testIsNotTransient() + { + $locator = $this->newLocator(); + $locator->expects($this->once()) + ->method('fileExists') + ->with($this->equalTo('stdClass')) + ->will($this->returnValue( true )); + + $driver = new TestFileDriver($locator); + $driver->setGlobalBasename("global"); + + $this->assertFalse($driver->isTransient('stdClass')); + $this->assertFalse($driver->isTransient('stdGlobal')); + $this->assertFalse($driver->isTransient('stdGlobal2')); + } + + public function testIsTransient() + { + $locator = $this->newLocator(); + $locator->expects($this->once()) + ->method('fileExists') + ->with($this->equalTo('stdClass2')) + ->will($this->returnValue( false )); + + $driver = new TestFileDriver($locator); + + $this->assertTrue($driver->isTransient('stdClass2')); + } + + public function testNonLocatorFallback() + { + $driver = new TestFileDriver(__DIR__ . '/_files', '.yml'); + $this->assertTrue($driver->isTransient('stdClass2')); + $this->assertFalse($driver->isTransient('stdClass')); + } + + private function newLocator() + { + $locator = $this->getMock('Doctrine\Common\Persistence\Mapping\Driver\FileLocator'); + $locator->expects($this->any())->method('getFileExtension')->will($this->returnValue('.yml')); + $locator->expects($this->any())->method('getPaths')->will($this->returnValue(array(__DIR__ . "/_files"))); + return $locator; + } +} + +class TestFileDriver extends FileDriver +{ + protected function loadMappingFile($file) + { + if (strpos($file, "global.yml") !== false) { + return array('stdGlobal' => 'stdGlobal', 'stdGlobal2' => 'stdGlobal2'); + } + return array('stdClass' => 'stdClass'); + } + + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + + } +} \ No newline at end of file diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/PHPDriverTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/PHPDriverTest.php new file mode 100644 index 0000000000..8fc4d80711 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/PHPDriverTest.php @@ -0,0 +1,18 @@ +getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + $metadata->expects($this->once())->method('getFieldNames'); + + $driver = new PHPDriver(array(__DIR__ . "/_files")); + $driver->loadMetadataForClass('TestEntity', $metadata); + } +} \ No newline at end of file diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/RuntimeReflectionServiceTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/RuntimeReflectionServiceTest.php new file mode 100644 index 0000000000..767ccd6394 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/RuntimeReflectionServiceTest.php @@ -0,0 +1,84 @@ +. + */ + +namespace Doctrine\Tests\Common\Persistence\Mapping; + +use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService; + +/** + * @group DCOM-93 + */ +class RuntimeReflectionServiceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var RuntimeReflectionService + */ + private $reflectionService; + + public $unusedPublicProperty; + + public function setUp() + { + $this->reflectionService = new RuntimeReflectionService(); + } + + public function testShortname() + { + $this->assertEquals("RuntimeReflectionServiceTest", $this->reflectionService->getClassShortName(__CLASS__)); + } + + public function testClassNamespaceName() + { + $this->assertEquals("Doctrine\Tests\Common\Persistence\Mapping", $this->reflectionService->getClassNamespace(__CLASS__)); + } + + public function testGetParentClasses() + { + $classes = $this->reflectionService->getParentClasses(__CLASS__); + $this->assertTrue(count($classes) >= 1, "The test class ".__CLASS__." should have at least one parent."); + } + + public function testGetParentClassesForAbsentClass() + { + $this->setExpectedException('Doctrine\Common\Persistence\Mapping\MappingException'); + $this->reflectionService->getParentClasses(__NAMESPACE__ . '\AbsentClass'); + } + + public function testGetReflectionClass() + { + $class = $this->reflectionService->getClass(__CLASS__); + $this->assertInstanceOf("ReflectionClass", $class); + } + + public function testGetMethods() + { + $this->assertTrue($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods")); + $this->assertFalse($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods2")); + } + + public function testGetAccessibleProperty() + { + $reflProp = $this->reflectionService->getAccessibleProperty(__CLASS__, "reflectionService"); + $this->assertInstanceOf("ReflectionProperty", $reflProp); + + $reflProp = $this->reflectionService->getAccessibleProperty(__CLASS__, "unusedPublicProperty"); + $this->assertInstanceOf("Doctrine\Common\Reflection\RuntimePublicReflectionProperty", $reflProp); + } +} + diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/StaticPHPDriverTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/StaticPHPDriverTest.php new file mode 100644 index 0000000000..9f1c5684e7 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/StaticPHPDriverTest.php @@ -0,0 +1,35 @@ +getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + $metadata->expects($this->once())->method('getFieldNames'); + + $driver = new StaticPHPDriver(array(__DIR__)); + $driver->loadMetadataForClass(__NAMESPACE__ . '\\TestEntity', $metadata); + } + + public function testGetAllClassNames() + { + $driver = new StaticPHPDriver(array(__DIR__)); + $classNames = $driver->getAllClassNames(); + + $this->assertContains( + 'Doctrine\Tests\Common\Persistence\Mapping\TestEntity', $classNames); + } +} + +class TestEntity +{ + static public function loadMetadata($metadata) + { + $metadata->getFieldNames(); + } +} \ No newline at end of file diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/StaticReflectionServiceTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/StaticReflectionServiceTest.php new file mode 100644 index 0000000000..9054b6c313 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/StaticReflectionServiceTest.php @@ -0,0 +1,70 @@ +. + */ + +namespace Doctrine\Tests\Common\Persistence\Mapping; + +use Doctrine\Common\Persistence\Mapping\StaticReflectionService; + +/** + * @group DCOM-93 + */ +class StaticReflectionServiceTest extends \PHPUnit_Framework_TestCase +{ + private $reflectionService; + + public function setUp() + { + $this->reflectionService = new StaticReflectionService(); + } + + public function testShortname() + { + $this->assertEquals("StaticReflectionServiceTest", $this->reflectionService->getClassShortName(__CLASS__)); + } + + public function testClassNamespaceName() + { + $this->assertEquals("Doctrine\Tests\Common\Persistence\Mapping", $this->reflectionService->getClassNamespace(__CLASS__)); + } + + public function testGetParentClasses() + { + $classes = $this->reflectionService->getParentClasses(__CLASS__); + $this->assertTrue(count($classes) == 0, "The test class ".__CLASS__." should have no parents according to static reflection."); + } + + public function testGetReflectionClass() + { + $class = $this->reflectionService->getClass(__CLASS__); + $this->assertNull($class); + } + + public function testGetMethods() + { + $this->assertTrue($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods")); + $this->assertTrue($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods2")); + } + + public function testGetAccessibleProperty() + { + $reflProp = $this->reflectionService->getAccessibleProperty(__CLASS__, "reflectionService"); + $this->assertNull($reflProp); + } +} + diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/SymfonyFileLocatorTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/SymfonyFileLocatorTest.php new file mode 100644 index 0000000000..e68b06330a --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/SymfonyFileLocatorTest.php @@ -0,0 +1,181 @@ + $prefix)); + $this->assertEquals(array($path), $locator->getPaths()); + + $locator = new SymfonyFileLocator(array($path => $prefix)); + $this->assertEquals(array($path), $locator->getPaths()); + } + + public function testGetPrefixes() + { + $path = __DIR__ . "/_files"; + $prefix = "Foo"; + + $locator = new SymfonyFileLocator(array($path => $prefix)); + $this->assertEquals(array($path => $prefix), $locator->getNamespacePrefixes()); + } + + public function testGetFileExtension() + { + $locator = new SymfonyFileLocator(array(), ".yml"); + $this->assertEquals(".yml", $locator->getFileExtension()); + $locator->setFileExtension(".xml"); + $this->assertEquals(".xml", $locator->getFileExtension()); + } + + public function testFileExists() + { + $path = __DIR__ . "/_files"; + $prefix = "Foo"; + + $locator = new SymfonyFileLocator(array($path => $prefix), ".yml"); + + $this->assertTrue($locator->fileExists("Foo\stdClass")); + $this->assertTrue($locator->fileExists("Foo\global")); + $this->assertFalse($locator->fileExists("Foo\stdClass2")); + $this->assertFalse($locator->fileExists("Foo\global2")); + } + + public function testGetAllClassNames() + { + $path = __DIR__ . "/_files"; + $prefix = "Foo"; + + $locator = new SymfonyFileLocator(array($path => $prefix), ".yml"); + $allClasses = $locator->getAllClassNames(null); + $globalClasses = $locator->getAllClassNames("global"); + + $expectedAllClasses = array("Foo\\Bar\\subDirClass", "Foo\\global", "Foo\\stdClass"); + $expectedGlobalClasses = array("Foo\\Bar\\subDirClass", "Foo\\stdClass"); + + sort($allClasses); + sort($globalClasses); + sort($expectedAllClasses); + sort($expectedGlobalClasses); + + $this->assertEquals($expectedAllClasses, $allClasses); + $this->assertEquals($expectedGlobalClasses, $globalClasses); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Namespace separator should not be empty + */ + public function testInvalidCustomNamespaceSeparator() + { + $path = __DIR__ . "/_files"; + $prefix = "Foo"; + + new SymfonyFileLocator(array($path => $prefix), ".yml", null); + } + + public function customNamespaceSeparatorProvider() + { + return array( + 'directory separator' => array(DIRECTORY_SEPARATOR, "/_custom_ns/dir"), + 'default dot separator' => array('.', "/_custom_ns/dot"), + ); + } + + /** + * @dataProvider customNamespaceSeparatorProvider + * + * @param $separator string Directory separator to test against + * @param $dir string Path to load mapping data from + * + * @throws \Doctrine\Common\Persistence\Mapping\MappingException + */ + public function testGetClassNamesWithCustomNsSeparator($separator, $dir) + { + $path = __DIR__ . $dir; + $prefix = "Foo"; + + $locator = new SymfonyFileLocator(array($path => $prefix), ".yml", $separator); + $classes = $locator->getAllClassNames(null); + sort($classes); + + $this->assertEquals(array("Foo\\stdClass", "Foo\\sub\\subClass", "Foo\\sub\\subsub\\subSubClass"), $classes); + } + + public function customNamespaceLookupQueryProvider() + { + return array( + 'directory separator' => array( + DIRECTORY_SEPARATOR, + "/_custom_ns/dir", + array( + "stdClass.yml" => "Foo\\stdClass", + "sub/subClass.yml" => "Foo\\sub\\subClass", + "sub/subsub/subSubClass.yml" => "Foo\\sub\\subsub\\subSubClass", + ) + ), + 'default dot separator' => array( + '.', + "/_custom_ns/dot", + array( + "stdClass.yml" => "Foo\\stdClass", + "sub.subClass.yml" => "Foo\\sub\\subClass", + "sub.subsub.subSubClass.yml" => "Foo\\sub\\subsub\\subSubClass", + ) + ), + ); + } + + /** @dataProvider customNamespaceLookupQueryProvider + * @param $separator string Directory separator to test against + * @param $dir string Path to load mapping data from + * @param $files array Files to lookup classnames + * + * @throws \Doctrine\Common\Persistence\Mapping\MappingException + */ + public function testFindMappingFileWithCustomNsSeparator($separator, $dir, $files) + { + $path = __DIR__ . $dir; + $prefix = "Foo"; + + $locator = new SymfonyFileLocator(array($path => $prefix), ".yml", $separator); + + foreach ($files as $filePath => $className) { + $this->assertEquals(realpath($path .'/'. $filePath), realpath($locator->findMappingFile($className))); + } + + } + + + public function testFindMappingFile() + { + $path = __DIR__ . "/_files"; + $prefix = "Foo"; + + $locator = new SymfonyFileLocator(array($path => $prefix), ".yml"); + + $this->assertEquals(__DIR__ . "/_files/stdClass.yml", $locator->findMappingFile("Foo\\stdClass")); + } + + public function testFindMappingFileNotFound() + { + $path = __DIR__ . "/_files"; + $prefix = "Foo"; + + $locator = new SymfonyFileLocator(array($path => $prefix), ".yml"); + + $this->setExpectedException( + "Doctrine\Common\Persistence\Mapping\MappingException", + "No mapping file found named '".__DIR__."/_files/stdClass2.yml' for class 'Foo\stdClass2'." + ); + $locator->findMappingFile("Foo\\stdClass2"); + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dir/stdClass.yml b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dir/stdClass.yml new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dir/stdClass.yml @@ -0,0 +1 @@ +test diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dir/sub/subClass.yml b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dir/sub/subClass.yml new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dir/sub/subClass.yml @@ -0,0 +1 @@ +test diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dir/sub/subsub/subSubClass.yml b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dir/sub/subsub/subSubClass.yml new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dir/sub/subsub/subSubClass.yml @@ -0,0 +1 @@ +test diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dot/stdClass.yml b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dot/stdClass.yml new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dot/stdClass.yml @@ -0,0 +1 @@ +test diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dot/sub.subClass.yml b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dot/sub.subClass.yml new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dot/sub.subClass.yml @@ -0,0 +1 @@ +test diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dot/sub.subsub.subSubClass.yml b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dot/sub.subsub.subSubClass.yml new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_custom_ns/dot/sub.subsub.subSubClass.yml @@ -0,0 +1 @@ +test diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_files/Bar/subDirClass.yml b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_files/Bar/subDirClass.yml new file mode 100644 index 0000000000..30d74d2584 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_files/Bar/subDirClass.yml @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_files/TestEntity.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_files/TestEntity.php new file mode 100644 index 0000000000..d0e9976ae5 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_files/TestEntity.php @@ -0,0 +1,3 @@ +getFieldNames(); \ No newline at end of file diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_files/annotation/TestClass.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_files/annotation/TestClass.php new file mode 100644 index 0000000000..ff03568217 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/Mapping/_files/annotation/TestClass.php @@ -0,0 +1,17 @@ +wrapped = $wrapped; + } +} + +class ObjectManagerDecoratorTest extends \PHPUnit_Framework_TestCase +{ + private $wrapped; + private $decorated; + + public function setUp() + { + $this->wrapped = $this->getMock('Doctrine\Common\Persistence\ObjectManager'); + $this->decorated = new NullObjectManagerDecorator($this->wrapped); + } + + public function getMethodParameters() + { + $class = new \ReflectionClass('Doctrine\Common\Persistence\ObjectManager'); + + $methods = array(); + foreach ($class->getMethods() as $method) { + if ($method->getNumberOfRequiredParameters() === 0) { + $methods[] = array($method->getName(), array()); + } elseif ($method->getNumberOfRequiredParameters() > 0) { + $methods[] = array($method->getName(), array_fill(0, $method->getNumberOfRequiredParameters(), 'req') ?: array()); + } + if ($method->getNumberOfParameters() != $method->getNumberOfRequiredParameters()) { + $methods[] = array($method->getName(), array_fill(0, $method->getNumberOfParameters(), 'all') ?: array()); + } + } + + return $methods; + } + + /** + * @dataProvider getMethodParameters + */ + public function testAllMethodCallsAreDelegatedToTheWrappedInstance($method, array $parameters) + { + $stub = $this->wrapped + ->expects($this->once()) + ->method($method) + ->will($this->returnValue('INNER VALUE FROM ' . $method)); + + call_user_func_array(array($stub, 'with'), $parameters); + + $this->assertSame('INNER VALUE FROM ' . $method, call_user_func_array(array($this->decorated, $method), $parameters)); + } +} \ No newline at end of file diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/PersistentObjectTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/PersistentObjectTest.php new file mode 100644 index 0000000000..180d0f0d00 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Persistence/PersistentObjectTest.php @@ -0,0 +1,247 @@ +cm = new TestObjectMetadata; + $this->om = $this->getMock('Doctrine\Common\Persistence\ObjectManager'); + $this->om->expects($this->any())->method('getClassMetadata') + ->will($this->returnValue($this->cm)); + $this->object = new TestObject; + PersistentObject::setObjectManager($this->om); + $this->object->injectObjectManager($this->om, $this->cm); + } + + public function testGetObjectManager() + { + $this->assertSame($this->om, PersistentObject::getObjectManager()); + } + + public function testNonMatchingObjectManager() + { + $this->setExpectedException('RuntimeException'); + $om = $this->getMock('Doctrine\Common\Persistence\ObjectManager'); + $this->object->injectObjectManager($om, $this->cm); + } + + public function testGetField() + { + $this->assertEquals('beberlei', $this->object->getName()); + } + + public function testSetField() + { + $this->object->setName("test"); + $this->assertEquals("test", $this->object->getName()); + } + + public function testGetIdentifier() + { + $this->assertEquals(1, $this->object->getId()); + } + + public function testSetIdentifier() + { + $this->setExpectedException('BadMethodCallException'); + $this->object->setId(2); + } + + public function testSetUnknownField() + { + $this->setExpectedException('BadMethodCallException'); + $this->object->setUnknown("test"); + } + + public function testGetUnknownField() + { + $this->setExpectedException('BadMethodCallException'); + $this->object->getUnknown(); + } + + public function testGetToOneAssociation() + { + $this->assertNull($this->object->getParent()); + } + + public function testSetToOneAssociation() + { + $parent = new TestObject(); + $this->object->setParent($parent); + $this->assertSame($parent, $this->object->getParent($parent)); + } + + public function testSetInvalidToOneAssociation() + { + $parent = new \stdClass(); + + $this->setExpectedException('InvalidArgumentException'); + $this->object->setParent($parent); + } + + public function testSetToOneAssociationNull() + { + $parent = new TestObject(); + $this->object->setParent($parent); + $this->object->setParent(null); + $this->assertNull($this->object->getParent()); + } + + public function testAddToManyAssociation() + { + $child = new TestObject(); + $this->object->addChildren($child); + + $this->assertSame($this->object, $child->getParent()); + $this->assertEquals(1, count($this->object->getChildren())); + + $child = new TestObject(); + $this->object->addChildren($child); + + $this->assertEquals(2, count($this->object->getChildren())); + } + + public function testAddInvalidToManyAssociation() + { + $this->setExpectedException('InvalidArgumentException'); + $this->object->addChildren(new \stdClass()); + } + + public function testNoObjectManagerSet() + { + PersistentObject::setObjectManager(null); + $child = new TestObject(); + + $this->setExpectedException('RuntimeException'); + $child->setName("test"); + } + + public function testInvalidMethod() + { + $this->setExpectedException('BadMethodCallException'); + $this->object->asdf(); + } + + public function testAddInvalidCollection() + { + $this->setExpectedException('BadMethodCallException'); + $this->object->addAsdf(new \stdClass()); + } +} + +class TestObject extends PersistentObject +{ + protected $id = 1; + protected $name = 'beberlei'; + protected $parent; + protected $children; +} + +class TestObjectMetadata implements ClassMetadata +{ + + public function getAssociationMappedByTargetField($assocName) + { + $assoc = array('children' => 'parent'); + return $assoc[$assocName]; + } + + public function getAssociationNames() + { + return array('parent', 'children'); + } + + public function getAssociationTargetClass($assocName) + { + return __NAMESPACE__ . '\TestObject'; + } + + public function getFieldNames() + { + return array('id', 'name'); + } + + public function getIdentifier() + { + return array('id'); + } + + public function getName() + { + return __NAMESPACE__ . '\TestObject'; + } + + public function getReflectionClass() + { + return new \ReflectionClass($this->getName()); + } + + public function getTypeOfField($fieldName) + { + $types = array('id' => 'integer', 'name' => 'string'); + return $types[$fieldName]; + } + + public function hasAssociation($fieldName) + { + return in_array($fieldName, array('parent', 'children')); + } + + public function hasField($fieldName) + { + return in_array($fieldName, array('id', 'name')); + } + + public function isAssociationInverseSide($assocName) + { + return ($assocName === 'children'); + } + + public function isCollectionValuedAssociation($fieldName) + { + return ($fieldName === 'children'); + } + + public function isIdentifier($fieldName) + { + return $fieldName === 'id'; + } + + public function isSingleValuedAssociation($fieldName) + { + return $fieldName === 'parent'; + } + + public function getIdentifierValues($entity) + { + + } + + public function getIdentifierFieldNames() + { + + } + + public function initializeReflection(ReflectionService $reflService) + { + + } + + public function wakeupReflection(ReflectionService $reflService) + { + + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/AbstractProxyFactoryTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/AbstractProxyFactoryTest.php new file mode 100644 index 0000000000..6ae9316383 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/AbstractProxyFactoryTest.php @@ -0,0 +1,146 @@ +getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + $proxyGenerator = $this->getMock('Doctrine\Common\Proxy\ProxyGenerator', array(), array(), '', false); + + $proxyGenerator + ->expects($this->once()) + ->method('getProxyFileName'); + $proxyGenerator + ->expects($this->once()) + ->method('generateProxyClass'); + + $metadataFactory = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadataFactory'); + $proxyFactory = $this->getMockForAbstractClass( + 'Doctrine\Common\Proxy\AbstractProxyFactory', + array($proxyGenerator, $metadataFactory, true) + ); + + $proxyFactory + ->expects($this->any()) + ->method('skipClass') + ->will($this->returnValue(false)); + + $generated = $proxyFactory->generateProxyClasses(array($metadata), sys_get_temp_dir()); + + $this->assertEquals(1, $generated, 'One proxy was generated'); + } + + public function testGetProxy() + { + $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + $proxy = $this->getMock('Doctrine\Common\Proxy\Proxy'); + $definition = new ProxyDefinition(get_class($proxy), array(), array(), null, null); + $proxyGenerator = $this->getMock('Doctrine\Common\Proxy\ProxyGenerator', array(), array(), '', false); + $metadataFactory = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadataFactory'); + + $metadataFactory + ->expects($this->once()) + ->method('getMetadataFor') + ->will($this->returnValue($metadata)); + + $proxyFactory = $this->getMockForAbstractClass( + 'Doctrine\Common\Proxy\AbstractProxyFactory', + array($proxyGenerator, $metadataFactory, true) + ); + + $proxyFactory + ->expects($this->any()) + ->method('createProxyDefinition') + ->will($this->returnValue($definition)); + + $generatedProxy = $proxyFactory->getProxy('Class', array('id' => 1)); + + $this->assertInstanceOf(get_class($proxy), $generatedProxy); + } + + public function testResetUnitializedProxy() + { + $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + $proxy = $this->getMock('Doctrine\Common\Proxy\Proxy'); + $definition = new ProxyDefinition(get_class($proxy), array(), array(), null, null); + $proxyGenerator = $this->getMock('Doctrine\Common\Proxy\ProxyGenerator', array(), array(), '', false); + $metadataFactory = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadataFactory'); + + $metadataFactory + ->expects($this->once()) + ->method('getMetadataFor') + ->will($this->returnValue($metadata)); + + $proxyFactory = $this->getMockForAbstractClass( + 'Doctrine\Common\Proxy\AbstractProxyFactory', + array($proxyGenerator, $metadataFactory, true) + ); + + $proxyFactory + ->expects($this->any()) + ->method('createProxyDefinition') + ->will($this->returnValue($definition)); + + $proxy + ->expects($this->once()) + ->method('__isInitialized') + ->will($this->returnValue(false)); + $proxy + ->expects($this->once()) + ->method('__setInitializer'); + $proxy + ->expects($this->once()) + ->method('__setCloner'); + + $proxyFactory->resetUninitializedProxy($proxy); + } + + public function testDisallowsResettingInitializedProxy() + { + $proxyFactory = $this->getMockForAbstractClass('Doctrine\Common\Proxy\AbstractProxyFactory', array(), '', false); + $proxy = $this->getMock('Doctrine\Common\Proxy\Proxy'); + + $proxy + ->expects($this->any()) + ->method('__isInitialized') + ->will($this->returnValue(true)); + + $this->setExpectedException('Doctrine\Common\Proxy\Exception\InvalidArgumentException'); + + $proxyFactory->resetUninitializedProxy($proxy); + } + + public function testMissingPrimaryKeyValue() + { + $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + $proxy = $this->getMock('Doctrine\Common\Proxy\Proxy'); + $definition = new ProxyDefinition(get_class($proxy), array('missingKey'), array(), null, null); + $proxyGenerator = $this->getMock('Doctrine\Common\Proxy\ProxyGenerator', array(), array(), '', false); + $metadataFactory = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadataFactory'); + + $metadataFactory + ->expects($this->once()) + ->method('getMetadataFor') + ->will($this->returnValue($metadata)); + + $proxyFactory = $this->getMockForAbstractClass( + 'Doctrine\Common\Proxy\AbstractProxyFactory', + array($proxyGenerator, $metadataFactory, true) + ); + + $proxyFactory + ->expects($this->any()) + ->method('createProxyDefinition') + ->will($this->returnValue($definition)); + + $this->setExpectedException('\OutOfBoundsException'); + + $generatedProxy = $proxyFactory->getProxy('Class', array()); + } +} + diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/AutoloaderTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/AutoloaderTest.php new file mode 100644 index 0000000000..be713fcd28 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/AutoloaderTest.php @@ -0,0 +1,72 @@ +. + */ + +namespace Doctrine\Tests\Common\Proxy; + +use PHPUnit_Framework_TestCase; +use Doctrine\Common\Proxy\Autoloader; + +/** + * @group DDC-1698 + */ +class AutoloaderTest extends PHPUnit_Framework_TestCase +{ + public static function dataResolveFile() + { + return array( + array('/tmp', 'MyProxy', 'MyProxy\__CG__\RealClass', '/tmp' . DIRECTORY_SEPARATOR . '__CG__RealClass.php'), + array('/tmp', 'MyProxy\Subdir', 'MyProxy\Subdir\__CG__\RealClass', '/tmp' . DIRECTORY_SEPARATOR . '__CG__RealClass.php'), + array('/tmp', 'MyProxy', 'MyProxy\__CG__\Other\RealClass', '/tmp' . DIRECTORY_SEPARATOR . '__CG__OtherRealClass.php'), + ); + } + + /** + * @dataProvider dataResolveFile + */ + public function testResolveFile($proxyDir, $proxyNamespace, $className, $expectedProxyFile) + { + $actualProxyFile = Autoloader::resolveFile($proxyDir, $proxyNamespace, $className); + $this->assertEquals($expectedProxyFile, $actualProxyFile); + } + + public function testAutoload() + { + if (file_exists(sys_get_temp_dir() ."/AutoloaderTestClass.php")) { + unlink(sys_get_temp_dir() ."/AutoloaderTestClass.php"); + } + + $autoloader = Autoloader::register(sys_get_temp_dir(), 'ProxyAutoloaderTest', function($proxyDir, $proxyNamespace, $className) { + file_put_contents(sys_get_temp_dir() . "/AutoloaderTestClass.php", "assertTrue(class_exists('ProxyAutoloaderTest\AutoloaderTestClass', true)); + unlink(sys_get_temp_dir() ."/AutoloaderTestClass.php"); + } + + public function testRegisterWithInvalidCallback() + { + $this->setExpectedException( + 'Doctrine\Common\Proxy\Exception\InvalidArgumentException', + 'Invalid \$notFoundCallback given: must be a callable, "stdClass" given' + ); + + Autoloader::register('', '', new \stdClass()); + } +} + diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/CallableTypeHintClass.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/CallableTypeHintClass.php new file mode 100644 index 0000000000..f5fccb0dc0 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/CallableTypeHintClass.php @@ -0,0 +1,16 @@ +. + */ + +namespace Doctrine\Tests\Common\Proxy; + +/** + * Test asset representing a lazy loadable object + * + * @author Marco Pivetta + * @since 2.4 + */ +class LazyLoadableObject +{ + /** + * @var string + */ + public $publicIdentifierField; + + /** + * @var string + */ + protected $protectedIdentifierField; + + /** + * @var string + */ + public $publicTransientField = 'publicTransientFieldValue'; + + /** + * @var string + */ + protected $protectedTransientField = 'protectedTransientFieldValue'; + + /** + * @var string + */ + public $publicPersistentField = 'publicPersistentFieldValue'; + + /** + * @var string + */ + protected $protectedPersistentField = 'protectedPersistentFieldValue'; + + /** + * @var string + */ + public $publicAssociation = 'publicAssociationValue'; + + /** + * @var string + */ + protected $protectedAssociation = 'protectedAssociationValue'; + + /** + * @return string + */ + public function getProtectedIdentifierField() + { + return $this->protectedIdentifierField; + } + + /** + * @return string + */ + public function testInitializationTriggeringMethod() + { + return 'testInitializationTriggeringMethod'; + } + + /** + * @return string + */ + public function getProtectedAssociation() + { + return $this->protectedAssociation; + } + + /** + * @param \stdClass $param + */ + public function publicTypeHintedMethod(\stdClass $param) + { + } + + /** + * + */ + public function &byRefMethod() + { + } + + /** + * @param mixed $thisIsNotByRef + * @param &mixed $thisIsByRef + */ + public function byRefParamMethod($thisIsNotByRef, &$thisIsByRef) + { + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/LazyLoadableObjectClassMetadata.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/LazyLoadableObjectClassMetadata.php new file mode 100644 index 0000000000..167386e35d --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/LazyLoadableObjectClassMetadata.php @@ -0,0 +1,195 @@ +. + */ + +namespace Doctrine\Tests\Common\Proxy; + +use ReflectionClass; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; + +/** + * Class metadata test asset for @see LazyLoadableObject + * + * @author Marco Pivetta + * @since 2.4 + */ +class LazyLoadableObjectClassMetadata implements ClassMetadata +{ + /** + * @var ReflectionClass + */ + protected $reflectionClass; + + /** + * @var array + */ + protected $identifier = array( + 'publicIdentifierField' => true, + 'protectedIdentifierField' => true, + ); + + /** + * @var array + */ + protected $fields = array( + 'publicIdentifierField' => true, + 'protectedIdentifierField' => true, + 'publicPersistentField' => true, + 'protectedPersistentField' => true, + ); + + /** + * @var array + */ + protected $associations = array( + 'publicAssociation' => true, + 'protectedAssociation' => true, + ); + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->getReflectionClass()->getName(); + } + + /** + * {@inheritDoc} + */ + public function getIdentifier() + { + return array_keys($this->identifier); + } + + /** + * {@inheritDoc} + */ + public function getReflectionClass() + { + if (null === $this->reflectionClass) { + $this->reflectionClass = new \ReflectionClass(__NAMESPACE__ . '\LazyLoadableObject'); + } + + return $this->reflectionClass; + } + + /** + * {@inheritDoc} + */ + public function isIdentifier($fieldName) + { + return isset($this->identifier[$fieldName]); + } + + /** + * {@inheritDoc} + */ + public function hasField($fieldName) + { + return isset($this->fields[$fieldName]); + } + + /** + * {@inheritDoc} + */ + public function hasAssociation($fieldName) + { + return isset($this->associations[$fieldName]); + } + + /** + * {@inheritDoc} + */ + public function isSingleValuedAssociation($fieldName) + { + throw new \BadMethodCallException('not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isCollectionValuedAssociation($fieldName) + { + throw new \BadMethodCallException('not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getFieldNames() + { + return array_keys($this->fields); + } + + /** + * {@inheritDoc} + */ + public function getIdentifierFieldNames() + { + return $this->getIdentifier(); + } + + /** + * {@inheritDoc} + */ + public function getAssociationNames() + { + return array_keys($this->associations); + } + + /** + * {@inheritDoc} + */ + public function getTypeOfField($fieldName) + { + return 'string'; + } + + /** + * {@inheritDoc} + */ + public function getAssociationTargetClass($assocName) + { + throw new \BadMethodCallException('not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isAssociationInverseSide($assocName) + { + throw new \BadMethodCallException('not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getAssociationMappedByTargetField($assocName) + { + throw new \BadMethodCallException('not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getIdentifierValues($object) + { + throw new \BadMethodCallException('not implemented'); + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicCloneClass.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicCloneClass.php new file mode 100644 index 0000000000..33b983dc67 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicCloneClass.php @@ -0,0 +1,37 @@ +clonedValue = 'newClonedValue'; + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicGetByRefClass.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicGetByRefClass.php new file mode 100644 index 0000000000..6adf1f5741 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicGetByRefClass.php @@ -0,0 +1,51 @@ +. + */ + +namespace Doctrine\Tests\Common\Proxy; + +use InvalidArgumentException; + +/** + * Test asset class + * + * @since 2.4 + */ +class MagicGetByRefClass +{ + /** + * @var mixed + */ + public $valueField; + + /** + * @param string $name + * + * @return mixed + * + * @throws \InvalidArgumentException + */ + public function & __get($name) + { + if ($name === 'value') { + return $this->valueField; + } + + throw new InvalidArgumentException(); + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicGetClass.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicGetClass.php new file mode 100644 index 0000000000..0cab36a961 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicGetClass.php @@ -0,0 +1,38 @@ +testAttribute = $value; + } + + if ($name === 'publicField' || $name === 'id') { + throw new \BadMethodCallException('Should never be called for "publicField" or "id"'); + } + + $this->testAttribute = $value; + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicSleepClass.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicSleepClass.php new file mode 100644 index 0000000000..3934a05e7c --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/MagicSleepClass.php @@ -0,0 +1,37 @@ +wakeupValue = 'newWakeupValue'; + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyClassGeneratorTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyClassGeneratorTest.php new file mode 100644 index 0000000000..5de83a180b --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyClassGeneratorTest.php @@ -0,0 +1,249 @@ +. + */ + + +namespace Doctrine\Tests\Common\Proxy; + +use Doctrine\Common\Proxy\ProxyGenerator; +use ReflectionClass; +use ReflectionMethod; +use PHPUnit_Framework_TestCase; + +/** + * Test the proxy generator. Its work is generating on-the-fly subclasses of a given model, which implement the Proxy + * pattern. + * + * @author Giorgio Sironi + * @author Marco Pivetta + */ +class ProxyClassGeneratorTest extends PHPUnit_Framework_TestCase +{ + /** + * @var string + */ + protected $proxyClass = 'Doctrine\Tests\Common\ProxyProxy\__CG__\Doctrine\Tests\Common\Proxy\LazyLoadableObject'; + + /** + * @var LazyLoadableObjectClassMetadata + */ + protected $metadata; + + /** + * @var ProxyGenerator + */ + protected $proxyGenerator; + + /** + * {@inheritDoc} + */ + protected function setUp() + { + $this->metadata = new LazyLoadableObjectClassMetadata(); + $this->proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); + + if (class_exists($this->proxyClass, false)) { + return; + } + + $this->generateAndRequire($this->proxyGenerator, $this->metadata); + } + + public function testReferenceProxyRespectsMethodsParametersTypeHinting() + { + $method = new ReflectionMethod($this->proxyClass, 'publicTypeHintedMethod'); + $params = $method->getParameters(); + + $this->assertEquals(1, count($params)); + $this->assertEquals('stdClass', $params[0]->getClass()->getName()); + } + + public function testProxyRespectsMethodsWhichReturnValuesByReference() + { + $method = new ReflectionMethod($this->proxyClass, 'byRefMethod'); + + $this->assertTrue($method->returnsReference()); + } + + public function testProxyRespectsByRefMethodParameters() + { + $method = new ReflectionMethod($this->proxyClass, 'byRefParamMethod'); + $parameters = $method->getParameters(); + $this->assertSame('thisIsNotByRef', $parameters[0]->getName()); + $this->assertFalse($parameters[0]->isPassedByReference()); + $this->assertSame('thisIsByRef', $parameters[1]->getName()); + $this->assertTrue($parameters[1]->isPassedByReference()); + } + + public function testCreatesAssociationProxyAsSubclassOfTheOriginalOne() + { + $this->assertTrue(is_subclass_of($this->proxyClass, $this->metadata->getName())); + } + + public function testNonNamespacedProxyGeneration() + { + $classCode = file_get_contents($this->proxyGenerator->getProxyFileName($this->metadata->getName())); + + $this->assertNotContains("class LazyLoadableObject extends \\\\" . $this->metadata->getName(), $classCode); + $this->assertContains("class LazyLoadableObject extends \\" . $this->metadata->getName(), $classCode); + } + + public function testClassWithSleepProxyGeneration() + { + if (!class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\SleepClass', false)) { + $className = 'Doctrine\Tests\Common\Proxy\SleepClass'; + $metadata = $this->createClassMetadata($className, array('id')); + $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); + + $this->generateAndRequire($proxyGenerator, $metadata); + } + + $classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxySleepClass.php'); + $this->assertEquals(1, substr_count($classCode, 'function __sleep')); + $this->assertEquals(1, substr_count($classCode, 'parent::__sleep()')); + } + + /** + * Check that the proxy doesn't serialize static properties (in __sleep() method) + * @group DCOM-212 + */ + public function testClassWithStaticPropertyProxyGeneration() + { + if (!class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\StaticPropertyClass', false)) { + $className = 'Doctrine\Tests\Common\Proxy\StaticPropertyClass'; + $metadata = $this->createClassMetadata($className, array()); + $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); + + $this->generateAndRequire($proxyGenerator, $metadata); + } + + $classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyStaticPropertyClass.php'); + $this->assertEquals(1, substr_count($classCode, 'function __sleep')); + $this->assertNotContains('protectedStaticProperty', $classCode); + } + + private function generateAndRequire($proxyGenerator, $metadata) + { + $proxyGenerator->generateProxyClass($metadata, $proxyGenerator->getProxyFileName($metadata->getName())); + + require_once $proxyGenerator->getProxyFileName($metadata->getName()); + } + + public function testClassWithCallableTypeHintOnProxiedMethod() + { + if (PHP_VERSION_ID < 50400) { + $this->markTestSkipped('`callable` is only supported in PHP >=5.4.0'); + } + + if (!class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\CallableTypeHintClass', false)) { + $className = 'Doctrine\Tests\Common\Proxy\CallableTypeHintClass'; + $metadata = $this->createClassMetadata($className, array('id')); + + $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); + $this->generateAndRequire($proxyGenerator, $metadata); + } + + $classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyCallableTypeHintClass.php'); + + $this->assertEquals(1, substr_count($classCode, 'call(callable $foo)')); + } + + public function testClassWithVariadicArgumentOnProxiedMethod() + { + if (PHP_VERSION_ID < 50600) { + $this->markTestSkipped('`...` is only supported in PHP >=5.6.0'); + } + + if (!class_exists('Doctrine\Tests\Common\ProxyProxy\__CG__\VariadicTypeHintClass', false)) { + $className = 'Doctrine\Tests\Common\Proxy\VariadicTypeHintClass'; + $metadata = $this->createClassMetadata($className, array('id')); + + $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); + $this->generateAndRequire($proxyGenerator, $metadata); + } + + $classCode = file_get_contents(__DIR__ . '/generated/__CG__DoctrineTestsCommonProxyVariadicTypeHintClass.php'); + + $this->assertEquals(1, substr_count($classCode, 'function addType(...$types)')); + $this->assertEquals(1, substr_count($classCode, '__invoke($this, \'addType\', array($types))')); + $this->assertEquals(1, substr_count($classCode, 'parent::addType(...$types)')); + } + + public function testClassWithInvalidTypeHintOnProxiedMethod() + { + $className = 'Doctrine\Tests\Common\Proxy\InvalidTypeHintClass'; + $metadata = $this->createClassMetadata($className, array('id')); + $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); + + $this->setExpectedException( + 'Doctrine\Common\Proxy\Exception\UnexpectedValueException', + 'The type hint of parameter "foo" in method "invalidTypeHintMethod"' + .' in class "' . $className . '" is invalid.' + ); + $proxyGenerator->generateProxyClass($metadata); + } + + public function testNoConfigDirThrowsException() + { + $this->setExpectedException('Doctrine\Common\Proxy\Exception\InvalidArgumentException'); + new ProxyGenerator(null, null); + } + + public function testNoNamespaceThrowsException() + { + $this->setExpectedException('Doctrine\Common\Proxy\Exception\InvalidArgumentException'); + new ProxyGenerator(__DIR__ . '/generated', null); + } + + public function testInvalidPlaceholderThrowsException() + { + $this->setExpectedException('Doctrine\Common\Proxy\Exception\InvalidArgumentException'); + $generator = new ProxyGenerator(__DIR__ . '/generated', 'SomeNamespace'); + $generator->setPlaceholder('', array()); + } + + public function testUseEvalIfNoFilenameIsGiven() + { + $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); + + $className = __NAMESPACE__ . '\\EvalBase'; + + $metadata = $this->createClassMetadata($className, array('id')); + + $proxyGenerator->generateProxyClass($metadata); + + $reflClass = new ReflectionClass('Doctrine\Tests\Common\ProxyProxy\__CG__\Doctrine\Tests\Common\Proxy\EvalBase'); + + $this->assertContains("eval()'d code", $reflClass->getFileName()); + } + + private function createClassMetadata($className, array $ids) + { + $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + $reflClass = new ReflectionClass($className); + $metadata->expects($this->any())->method('getReflectionClass')->will($this->returnValue($reflClass)); + $metadata->expects($this->any())->method('getIdentifierFieldNames')->will($this->returnValue($ids)); + $metadata->expects($this->any())->method('getName')->will($this->returnValue($className)); + + return $metadata; + } +} + +class EvalBase +{ +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyLogicTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyLogicTest.php new file mode 100644 index 0000000000..c97ac79f27 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyLogicTest.php @@ -0,0 +1,752 @@ +. + */ + +namespace Doctrine\Tests\Common\Proxy; + +use Doctrine\Common\Proxy\ProxyGenerator; +use Doctrine\Common\Proxy\Proxy; +use Doctrine\Common\Proxy\Exception\UnexpectedValueException; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use PHPUnit_Framework_TestCase; + +/** + * Test the generated proxies behavior. These tests make assumptions about the structure of LazyLoadableObject + * + * @author Marco Pivetta + */ +class ProxyLogicTest extends PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $proxyLoader; + + /** + * @var ClassMetadata + */ + protected $lazyLoadableObjectMetadata; + + /** + * @var LazyLoadableObject|Proxy + */ + protected $lazyObject; + + protected $identifier = array( + 'publicIdentifierField' => 'publicIdentifierFieldValue', + 'protectedIdentifierField' => 'protectedIdentifierFieldValue', + ); + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Callable + */ + protected $initializerCallbackMock; + + /** + * {@inheritDoc} + */ + public function setUp() + { + $this->proxyLoader = $loader = $this->getMock('stdClass', array('load'), array(), '', false); + $this->initializerCallbackMock = $this->getMock('stdClass', array('__invoke')); + $identifier = $this->identifier; + $this->lazyLoadableObjectMetadata = $metadata = new LazyLoadableObjectClassMetadata(); + + // emulating what should happen in a proxy factory + $cloner = function (LazyLoadableObject $proxy) use ($loader, $identifier, $metadata) { + /* @var $proxy LazyLoadableObject|Proxy */ + if ($proxy->__isInitialized()) { + return; + } + + $proxy->__setInitialized(true); + $proxy->__setInitializer(null); + $original = $loader->load($identifier); + + if (null === $original) { + throw new UnexpectedValueException(); + } + + foreach ($metadata->getReflectionClass()->getProperties() as $reflProperty) { + $propertyName = $reflProperty->getName(); + + if ($metadata->hasField($propertyName) || $metadata->hasAssociation($propertyName)) { + $reflProperty->setAccessible(true); + $reflProperty->setValue($proxy, $reflProperty->getValue($original)); + } + } + }; + + $proxyClassName = 'Doctrine\Tests\Common\ProxyProxy\__CG__\Doctrine\Tests\Common\Proxy\LazyLoadableObject'; + + // creating the proxy class + if (!class_exists($proxyClassName, false)) { + $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); + $proxyGenerator->generateProxyClass($metadata); + require_once $proxyGenerator->getProxyFileName($metadata->getName()); + } + + $this->lazyObject = new $proxyClassName($this->getClosure($this->initializerCallbackMock), $cloner); + + // setting identifiers in the proxy via reflection + foreach ($metadata->getIdentifierFieldNames() as $idField) { + $prop = $metadata->getReflectionClass()->getProperty($idField); + $prop->setAccessible(true); + $prop->setValue($this->lazyObject, $identifier[$idField]); + } + + $this->assertFalse($this->lazyObject->__isInitialized()); + } + + public function testFetchingPublicIdentifierDoesNotCauseLazyLoading() + { + $this->configureInitializerMock(0); + + $this->assertSame('publicIdentifierFieldValue', $this->lazyObject->publicIdentifierField); + } + + public function testFetchingIdentifiersViaPublicGetterDoesNotCauseLazyLoading() + { + $this->configureInitializerMock(0); + + $this->assertSame('protectedIdentifierFieldValue', $this->lazyObject->getProtectedIdentifierField()); + } + + public function testCallingMethodCausesLazyLoading() + { + $this->configureInitializerMock( + 1, + array($this->lazyObject, 'testInitializationTriggeringMethod', array()), + function (Proxy $proxy) { + $proxy->__setInitializer(null); + } + ); + + $this->lazyObject->testInitializationTriggeringMethod(); + $this->lazyObject->testInitializationTriggeringMethod(); + } + + public function testFetchingPublicFieldsCausesLazyLoading() + { + $test = $this; + $this->configureInitializerMock( + 1, + array($this->lazyObject, '__get', array('publicPersistentField')), + function () use ($test) { + $test->setProxyValue('publicPersistentField', 'loadedValue'); + } + ); + + $this->assertSame('loadedValue', $this->lazyObject->publicPersistentField); + $this->assertSame('loadedValue', $this->lazyObject->publicPersistentField); + } + + public function testFetchingPublicAssociationCausesLazyLoading() + { + $test = $this; + $this->configureInitializerMock( + 1, + array($this->lazyObject, '__get', array('publicAssociation')), + function () use ($test) { + $test->setProxyValue('publicAssociation', 'loadedAssociation'); + } + ); + + $this->assertSame('loadedAssociation', $this->lazyObject->publicAssociation); + $this->assertSame('loadedAssociation', $this->lazyObject->publicAssociation); + } + + public function testFetchingProtectedAssociationViaPublicGetterCausesLazyLoading() + { + $this->configureInitializerMock( + 1, + array($this->lazyObject, 'getProtectedAssociation', array()), + function (Proxy $proxy) { + $proxy->__setInitializer(null); + } + ); + + $this->assertSame('protectedAssociationValue', $this->lazyObject->getProtectedAssociation()); + $this->assertSame('protectedAssociationValue', $this->lazyObject->getProtectedAssociation()); + } + + public function testLazyLoadingTriggeredOnlyAtFirstPublicPropertyRead() + { + $test = $this; + $this->configureInitializerMock( + 1, + array($this->lazyObject, '__get', array('publicPersistentField')), + function () use ($test) { + $test->setProxyValue('publicPersistentField', 'loadedValue'); + $test->setProxyValue('publicAssociation', 'publicAssociationValue'); + } + ); + + $this->assertSame('loadedValue', $this->lazyObject->publicPersistentField); + $this->assertSame('publicAssociationValue', $this->lazyObject->publicAssociation); + } + + public function testNoticeWhenReadingNonExistentPublicProperties() + { + $this->configureInitializerMock(0); + + $class = get_class($this->lazyObject); + $this->setExpectedException( + 'PHPUnit_Framework_Error_Notice', + 'Undefined property: ' . $class . '::$non_existing_property' + ); + + $this->lazyObject->non_existing_property; + } + + public function testFalseWhenCheckingNonExistentProperty() + { + $this->configureInitializerMock(0); + + $this->assertFalse(isset($this->lazyObject->non_existing_property)); + } + + public function testNoErrorWhenSettingNonExistentProperty() + { + $this->configureInitializerMock(0); + + $this->lazyObject->non_existing_property = 'now has a value'; + $this->assertSame('now has a value', $this->lazyObject->non_existing_property); + } + + public function testCloningCallsClonerWithClonedObject() + { + $lazyObject = $this->lazyObject; + $test = $this; + $cb = $this->getMock('stdClass', array('cb')); + $cb + ->expects($this->once()) + ->method('cb') + ->will($this->returnCallback(function (LazyLoadableObject $proxy) use ($lazyObject, $test) { + /* @var $proxy LazyLoadableObject|Proxy */ + $test->assertNotSame($proxy, $lazyObject); + $proxy->__setInitializer(null); + $proxy->publicAssociation = 'clonedAssociation'; + })); + + $this->lazyObject->__setCloner($this->getClosure(array($cb, 'cb'))); + + $cloned = clone $this->lazyObject; + $this->assertSame('clonedAssociation', $cloned->publicAssociation); + $this->assertNotSame($cloned, $lazyObject, 'a clone of the lazy object is retrieved'); + } + + public function testFetchingTransientPropertiesWillNotTriggerLazyLoading() + { + $this->configureInitializerMock(0); + + $this->assertSame( + 'publicTransientFieldValue', + $this->lazyObject->publicTransientField, + 'fetching public transient field won\'t trigger lazy loading' + ); + $property = $this + ->lazyLoadableObjectMetadata + ->getReflectionClass() + ->getProperty('protectedTransientField'); + $property->setAccessible(true); + $this->assertSame( + 'protectedTransientFieldValue', + $property->getValue($this->lazyObject), + 'fetching protected transient field via reflection won\'t trigger lazy loading' + ); + } + + /** + * Provided to guarantee backwards compatibility + */ + public function testLoadProxyMethod() + { + $this->configureInitializerMock(2, array($this->lazyObject, '__load', array())); + + $this->lazyObject->__load(); + $this->lazyObject->__load(); + } + + public function testLoadingWithPersisterWillBeTriggeredOnlyOnce() + { + $this + ->proxyLoader + ->expects($this->once()) + ->method('load') + ->with( + array( + 'publicIdentifierField' => 'publicIdentifierFieldValue', + 'protectedIdentifierField' => 'protectedIdentifierFieldValue', + ), + $this->lazyObject + ) + ->will($this->returnCallback(function ($id, LazyLoadableObject $lazyObject) { + // setting a value to verify that the persister can actually set something in the object + $lazyObject->publicAssociation = $id['publicIdentifierField'] . '-test'; + return true; + })); + $this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation()); + + $this->lazyObject->__load(); + $this->lazyObject->__load(); + $this->assertSame('publicIdentifierFieldValue-test', $this->lazyObject->publicAssociation); + } + + public function testFailedLoadingWillThrowException() + { + $this->proxyLoader->expects($this->any())->method('load')->will($this->returnValue(null)); + $this->setExpectedException('UnexpectedValueException'); + $this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation()); + + $this->lazyObject->__load(); + } + + public function testCloningWithPersister() + { + $this->lazyObject->publicTransientField = 'should-not-change'; + $this + ->proxyLoader + ->expects($this->exactly(2)) + ->method('load') + ->with(array( + 'publicIdentifierField' => 'publicIdentifierFieldValue', + 'protectedIdentifierField' => 'protectedIdentifierFieldValue', + )) + ->will($this->returnCallback(function () { + $blueprint = new LazyLoadableObject(); + $blueprint->publicPersistentField = 'checked-persistent-field'; + $blueprint->publicAssociation = 'checked-association-field'; + $blueprint->publicTransientField = 'checked-transient-field'; + + return $blueprint; + })); + + $firstClone = clone $this->lazyObject; + $this->assertSame( + 'checked-persistent-field', + $firstClone->publicPersistentField, + 'Persistent fields are cloned correctly' + ); + $this->assertSame( + 'checked-association-field', + $firstClone->publicAssociation, + 'Associations are cloned correctly' + ); + $this->assertSame( + 'should-not-change', + $firstClone->publicTransientField, + 'Transient fields are not overwritten' + ); + + $secondClone = clone $this->lazyObject; + $this->assertSame( + 'checked-persistent-field', + $secondClone->publicPersistentField, + 'Persistent fields are cloned correctly' + ); + $this->assertSame( + 'checked-association-field', + $secondClone->publicAssociation, + 'Associations are cloned correctly' + ); + $this->assertSame( + 'should-not-change', + $secondClone->publicTransientField, + 'Transient fields are not overwritten' + ); + + // those should not trigger lazy loading + $firstClone->__load(); + $secondClone->__load(); + } + + public function testNotInitializedProxyUnserialization() + { + $this->configureInitializerMock(); + + $serialized = serialize($this->lazyObject); + /* @var $unserialized LazyLoadableObject|Proxy */ + $unserialized = unserialize($serialized); + $reflClass = $this->lazyLoadableObjectMetadata->getReflectionClass(); + + $this->assertFalse($unserialized->__isInitialized(), 'serialization didn\'t cause intialization'); + + // Checking identifiers + $this->assertSame('publicIdentifierFieldValue', $unserialized->publicIdentifierField, 'identifiers are kept'); + $protectedIdentifierField = $reflClass->getProperty('protectedIdentifierField'); + $protectedIdentifierField->setAccessible(true); + $this->assertSame( + 'protectedIdentifierFieldValue', + $protectedIdentifierField->getValue($unserialized), + 'identifiers are kept' + ); + + // Checking transient fields + $this->assertSame( + 'publicTransientFieldValue', + $unserialized->publicTransientField, + 'transient fields are kept' + ); + $protectedTransientField = $reflClass->getProperty('protectedTransientField'); + $protectedTransientField->setAccessible(true); + $this->assertSame( + 'protectedTransientFieldValue', + $protectedTransientField->getValue($unserialized), + 'transient fields are kept' + ); + + // Checking persistent fields + $this->assertSame( + 'publicPersistentFieldValue', + $unserialized->publicPersistentField, + 'persistent fields are kept' + ); + $protectedPersistentField = $reflClass->getProperty('protectedPersistentField'); + $protectedPersistentField->setAccessible(true); + $this->assertSame( + 'protectedPersistentFieldValue', + $protectedPersistentField->getValue($unserialized), + 'persistent fields are kept' + ); + + // Checking associations + $this->assertSame('publicAssociationValue', $unserialized->publicAssociation, 'associations are kept'); + $protectedAssociationField = $reflClass->getProperty('protectedAssociation'); + $protectedAssociationField->setAccessible(true); + $this->assertSame( + 'protectedAssociationValue', + $protectedAssociationField->getValue($unserialized), + 'associations are kept' + ); + } + + public function testInitializedProxyUnserialization() + { + // persister will retrieve the lazy object itself, so that we don't have to re-define all field values + $this->proxyLoader->expects($this->once())->method('load')->will($this->returnValue($this->lazyObject)); + $this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation()); + $this->lazyObject->__load(); + + $serialized = serialize($this->lazyObject); + $reflClass = $this->lazyLoadableObjectMetadata->getReflectionClass(); + /* @var $unserialized LazyLoadableObject|Proxy */ + $unserialized = unserialize($serialized); + + $this->assertTrue($unserialized->__isInitialized(), 'serialization didn\'t cause intialization'); + + // Checking transient fields + $this->assertSame( + 'publicTransientFieldValue', + $unserialized->publicTransientField, + 'transient fields are kept' + ); + $protectedTransientField = $reflClass->getProperty('protectedTransientField'); + $protectedTransientField->setAccessible(true); + $this->assertSame( + 'protectedTransientFieldValue', + $protectedTransientField->getValue($unserialized), + 'transient fields are kept' + ); + + // Checking persistent fields + $this->assertSame( + 'publicPersistentFieldValue', + $unserialized->publicPersistentField, + 'persistent fields are kept' + ); + $protectedPersistentField = $reflClass->getProperty('protectedPersistentField'); + $protectedPersistentField->setAccessible(true); + $this->assertSame( + 'protectedPersistentFieldValue', + $protectedPersistentField->getValue($unserialized), + 'persistent fields are kept' + ); + + // Checking identifiers + $this->assertSame( + 'publicIdentifierFieldValue', + $unserialized->publicIdentifierField, + 'identifiers are kept' + ); + $protectedIdentifierField = $reflClass->getProperty('protectedIdentifierField'); + $protectedIdentifierField->setAccessible(true); + $this->assertSame( + 'protectedIdentifierFieldValue', + $protectedIdentifierField->getValue($unserialized), + 'identifiers are kept' + ); + + // Checking associations + $this->assertSame('publicAssociationValue', $unserialized->publicAssociation, 'associations are kept'); + $protectedAssociationField = $reflClass->getProperty('protectedAssociation'); + $protectedAssociationField->setAccessible(true); + $this->assertSame( + 'protectedAssociationValue', + $protectedAssociationField->getValue($unserialized), + 'associations are kept' + ); + } + + public function testInitializationRestoresDefaultPublicLazyLoadedFieldValues() + { + // setting noop persister + $this->proxyLoader->expects($this->once())->method('load')->will($this->returnValue($this->lazyObject)); + $this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation()); + + $this->assertSame( + 'publicPersistentFieldValue', + $this->lazyObject->publicPersistentField, + 'Persistent field is restored to default value' + ); + $this->assertSame( + 'publicAssociationValue', + $this->lazyObject->publicAssociation, + 'Association is restored to default value' + ); + } + + public function testSettingPublicFieldsCausesLazyLoading() + { + $test = $this; + $this->configureInitializerMock( + 1, + array($this->lazyObject, '__set', array('publicPersistentField', 'newPublicPersistentFieldValue')), + function () use ($test) { + $test->setProxyValue('publicPersistentField', 'overrideValue'); + $test->setProxyValue('publicAssociation', 'newAssociationValue'); + } + ); + + $this->lazyObject->publicPersistentField = 'newPublicPersistentFieldValue'; + $this->assertSame('newPublicPersistentFieldValue', $this->lazyObject->publicPersistentField); + $this->assertSame('newAssociationValue', $this->lazyObject->publicAssociation); + } + + public function testSettingPublicAssociationCausesLazyLoading() + { + $test = $this; + $this->configureInitializerMock( + 1, + array($this->lazyObject, '__set', array('publicAssociation', 'newPublicAssociationValue')), + function () use ($test) { + $test->setProxyValue('publicPersistentField', 'newPublicPersistentFieldValue'); + $test->setProxyValue('publicAssociation', 'overrideValue'); + } + ); + + $this->lazyObject->publicAssociation = 'newPublicAssociationValue'; + $this->assertSame('newPublicAssociationValue', $this->lazyObject->publicAssociation); + $this->assertSame('newPublicPersistentFieldValue', $this->lazyObject->publicPersistentField); + } + + public function testCheckingPublicFieldsCausesLazyLoading() + { + $test = $this; + $this->configureInitializerMock( + 1, + array($this->lazyObject, '__isset', array('publicPersistentField')), + function () use ($test) { + $test->setProxyValue('publicPersistentField', null); + $test->setProxyValue('publicAssociation', 'setPublicAssociation'); + } + ); + + $this->assertFalse(isset($this->lazyObject->publicPersistentField)); + $this->assertNull($this->lazyObject->publicPersistentField); + $this->assertTrue(isset($this->lazyObject->publicAssociation)); + $this->assertSame('setPublicAssociation', $this->lazyObject->publicAssociation); + } + + public function testCheckingPublicAssociationCausesLazyLoading() + { + $test = $this; + $this->configureInitializerMock( + 1, + array($this->lazyObject, '__isset', array('publicAssociation')), + function () use ($test) { + $test->setProxyValue('publicPersistentField', 'newPersistentFieldValue'); + $test->setProxyValue('publicAssociation', 'setPublicAssociation'); + } + ); + + $this->assertTrue(isset($this->lazyObject->publicAssociation)); + $this->assertSame('setPublicAssociation', $this->lazyObject->publicAssociation); + $this->assertTrue(isset($this->lazyObject->publicPersistentField)); + $this->assertSame('newPersistentFieldValue', $this->lazyObject->publicPersistentField); + } + + public function testCallingVariadicMethodCausesLazyLoading() + { + if (PHP_VERSION_ID < 50600) { + $this->markTestSkipped('Test applies only to PHP 5.6+'); + } + + $proxyClassName = 'Doctrine\Tests\Common\ProxyProxy\__CG__\Doctrine\Tests\Common\Proxy\VariadicTypeHintClass'; + + /* @var $metadata \Doctrine\Common\Persistence\Mapping\ClassMetadata|\PHPUnit_Framework_MockObject_MockObject */ + $metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); + + $metadata + ->expects($this->any()) + ->method('getName') + ->will($this->returnValue('Doctrine\Tests\Common\Proxy\VariadicTypeHintClass')); + $metadata + ->expects($this->any()) + ->method('getReflectionClass') + ->will($this->returnValue(new \ReflectionClass('Doctrine\Tests\Common\Proxy\VariadicTypeHintClass'))); + + // creating the proxy class + if (!class_exists($proxyClassName, false)) { + $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true); + $proxyGenerator->generateProxyClass($metadata); + require_once $proxyGenerator->getProxyFileName($metadata->getName()); + } + + /* @var $invocationMock callable|\PHPUnit_Framework_MockObject_MockObject */ + $invocationMock = $this->getMock('stdClass', array('__invoke')); + + /* @var $lazyObject \Doctrine\Tests\Common\Proxy\VariadicTypeHintClass */ + $lazyObject = new $proxyClassName( + function ($proxy, $method, $parameters) use ($invocationMock) { + $invocationMock($proxy, $method, $parameters); + }, + function () {} + ); + + $invocationMock + ->expects($this->at(0)) + ->method('__invoke') + ->with($lazyObject, 'addType', array(array('type1', 'type2'))); + $invocationMock + ->expects($this->at(1)) + ->method('__invoke') + ->with($lazyObject, 'addTypeWithMultipleParameters', array('foo', 'bar', array('baz1', 'baz2'))); + + $lazyObject->addType('type1', 'type2'); + $this->assertSame(array('type1', 'type2'), $lazyObject->types); + + $lazyObject->addTypeWithMultipleParameters('foo', 'bar', 'baz1', 'baz2'); + $this->assertSame('foo', $lazyObject->foo); + $this->assertSame('bar', $lazyObject->bar); + $this->assertSame(array('baz1', 'baz2'), $lazyObject->baz); + } + + /** + * Converts a given callable into a closure + * + * @param callable $callable + * @return \Closure + */ + public function getClosure($callable) { + return function () use ($callable) { + call_user_func_array($callable, func_get_args()); + }; + } + + /** + * Configures the current initializer callback mock with provided matcher params + * + * @param int $expectedCallCount the number of invocations to be expected. If a value< 0 is provided, `any` is used + * @param array $callParamsMatch an ordered array of parameters to be expected + * @param callable $callbackClosure a return callback closure + * + * @return \PHPUnit_Framework_MockObject_MockObject| + */ + protected function configureInitializerMock( + $expectedCallCount = 0, + array $callParamsMatch = null, + \Closure $callbackClosure = null + ) { + if (!$expectedCallCount) { + $invocationCountMatcher = $this->exactly((int) $expectedCallCount); + } else { + $invocationCountMatcher = $expectedCallCount < 0 ? $this->any() : $this->exactly($expectedCallCount); + } + + $invocationMocker = $this->initializerCallbackMock->expects($invocationCountMatcher)->method('__invoke'); + + if (null !== $callParamsMatch) { + call_user_func_array(array($invocationMocker, 'with'), $callParamsMatch); + } + + if ($callbackClosure) { + $invocationMocker->will($this->returnCallback($callbackClosure)); + } + } + + /** + * Sets a value in the current proxy object without triggering lazy loading through `__set` + * + * @link https://bugs.php.net/bug.php?id=63463 + * + * @param string $property + * @param mixed $value + */ + public function setProxyValue($property, $value) + { + $reflectionProperty = new \ReflectionProperty($this->lazyObject, $property); + $initializer = $this->lazyObject->__getInitializer(); + + // disabling initializer since setting `publicPersistentField` triggers `__set`/`__get` + $this->lazyObject->__setInitializer(null); + $reflectionProperty->setValue($this->lazyObject, $value); + $this->lazyObject->__setInitializer($initializer); + } + + /** + * Retrieves the suggested implementation of an initializer that proxy factories in O*M + * are currently following, and that should be used to initialize the current proxy object + * + * @return \Closure + */ + protected function getSuggestedInitializerImplementation() + { + $loader = $this->proxyLoader; + $identifier = $this->identifier; + + return function (LazyLoadableObject $proxy) use ($loader, $identifier) { + /* @var $proxy LazyLoadableObject|Proxy */ + $proxy->__setInitializer(null); + $proxy->__setCloner(null); + + + if ($proxy->__isInitialized()) { + return; + } + + $properties = $proxy->__getLazyProperties(); + + foreach ($properties as $propertyName => $property) { + if (!isset($proxy->$propertyName)) { + $proxy->$propertyName = $properties[$propertyName]; + } + } + + $proxy->__setInitialized(true); + + if (method_exists($proxy, '__wakeup')) { + $proxy->__wakeup(); + } + + if (null === $loader->load($identifier, $proxy)) { + throw new \UnexpectedValueException('Couldn\'t load'); + } + }; + } +} \ No newline at end of file diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyMagicMethodsTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyMagicMethodsTest.php new file mode 100644 index 0000000000..1ed9d92a72 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/ProxyMagicMethodsTest.php @@ -0,0 +1,327 @@ +. + */ + +namespace Doctrine\Tests\Common\Proxy; + +use Doctrine\Common\Proxy\ProxyGenerator; +use Doctrine\Common\Proxy\Proxy; +use Doctrine\Common\Proxy\Exception\UnexpectedValueException; +use PHPUnit_Framework_TestCase; +use ReflectionClass; + +/** + * Test for behavior of proxies with inherited magic methods + * + * @author Marco Pivetta + */ +class ProxyMagicMethodsTest extends PHPUnit_Framework_TestCase +{ + /** + * @var \Doctrine\Common\Proxy\ProxyGenerator + */ + protected $proxyGenerator; + + /** + * @var LazyLoadableObject|Proxy + */ + protected $lazyObject; + + protected $identifier = array( + 'publicIdentifierField' => 'publicIdentifierFieldValue', + 'protectedIdentifierField' => 'protectedIdentifierFieldValue', + ); + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Callable + */ + protected $initializerCallbackMock; + + /** + * {@inheritDoc} + */ + public function setUp() + { + $this->proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . '\\MagicMethodProxy'); + } + + public static function tearDownAfterClass() + { + + } + + public function testInheritedMagicGet() + { + $proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicGetClass'); + $proxy = new $proxyClassName( + function (Proxy $proxy, $method, $params) use (&$counter) { + if ( ! in_array($params[0], array('publicField', 'test', 'notDefined'))) { + throw new \InvalidArgumentException('Unexpected access to field "' . $params[0] . '"'); + } + + $initializer = $proxy->__getInitializer(); + + $proxy->__setInitializer(null); + + $proxy->publicField = 'modifiedPublicField'; + $counter += 1; + + $proxy->__setInitializer($initializer); + + } + ); + + $this->assertSame('id', $proxy->id); + $this->assertSame('modifiedPublicField', $proxy->publicField); + $this->assertSame('test', $proxy->test); + $this->assertSame('not defined', $proxy->notDefined); + + $this->assertSame(3, $counter); + } + + /** + * @group DCOM-194 + */ + public function testInheritedMagicGetByRef() + { + $proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicGetByRefClass'); + /* @var $proxy \Doctrine\Tests\Common\Proxy\MagicGetByRefClass */ + $proxy = new $proxyClassName(); + $proxy->valueField = 123; + $value = & $proxy->__get('value'); + + $this->assertSame(123, $value); + + $value = 456; + + $this->assertSame(456, $proxy->__get('value'), 'Value was fetched by reference'); + + $this->setExpectedException('InvalidArgumentException'); + + $undefined = $proxy->nonExisting; + } + + public function testInheritedMagicSet() + { + $proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicSetClass'); + $proxy = new $proxyClassName( + function (Proxy $proxy, $method, $params) use (&$counter) { + if ( ! in_array($params[0], array('publicField', 'test', 'notDefined'))) { + throw new \InvalidArgumentException('Unexpected access to field "' . $params[0] . '"'); + } + + $counter += 1; + } + ); + + $this->assertSame('id', $proxy->id); + + $proxy->publicField = 'publicFieldValue'; + + $this->assertSame('publicFieldValue', $proxy->publicField); + + $proxy->test = 'testValue'; + + $this->assertSame('testValue', $proxy->testAttribute); + + $proxy->notDefined = 'not defined'; + + $this->assertSame('not defined', $proxy->testAttribute); + $this->assertSame(3, $counter); + } + + public function testInheritedMagicSleep() + { + $proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicSleepClass'); + $proxy = new $proxyClassName(); + + $this->assertSame('defaultValue', $proxy->serializedField); + $this->assertSame('defaultValue', $proxy->nonSerializedField); + + $proxy->serializedField = 'changedValue'; + $proxy->nonSerializedField = 'changedValue'; + + $unserialized = unserialize(serialize($proxy)); + + $this->assertSame('changedValue', $unserialized->serializedField); + $this->assertSame('defaultValue', $unserialized->nonSerializedField, 'Field was not returned by "__sleep"'); + } + + public function testInheritedMagicWakeup() + { + $proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicWakeupClass'); + $proxy = new $proxyClassName(); + + $this->assertSame('defaultValue', $proxy->wakeupValue); + + $proxy->wakeupValue = 'changedValue'; + $unserialized = unserialize(serialize($proxy)); + + $this->assertSame('newWakeupValue', $unserialized->wakeupValue, '"__wakeup" was called'); + + $unserialized->__setInitializer(function (Proxy $proxy) { + $proxy->__setInitializer(null); + + $proxy->publicField = 'newPublicFieldValue'; + }); + + $this->assertSame('newPublicFieldValue', $unserialized->publicField, 'Proxy can still be initialized'); + } + + public function testInheritedMagicIsset() + { + $proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicIssetClass'); + $proxy = new $proxyClassName(function (Proxy $proxy, $method, $params) use (&$counter) { + if (in_array($params[0], array('publicField', 'test', 'nonExisting'))) { + $initializer = $proxy->__getInitializer(); + + $proxy->__setInitializer(null); + + $proxy->publicField = 'modifiedPublicField'; + $counter += 1; + + $proxy->__setInitializer($initializer); + + return; + } + + throw new \InvalidArgumentException( + sprintf('Should not be initialized when checking isset("%s")', $params[0]) + ); + }); + + $this->assertTrue(isset($proxy->id)); + $this->assertTrue(isset($proxy->publicField)); + $this->assertTrue(isset($proxy->test)); + $this->assertFalse(isset($proxy->nonExisting)); + + $this->assertSame(3, $counter); + } + + public function testInheritedMagicClone() + { + $proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\MagicCloneClass'); + $proxy = new $proxyClassName( + null, + function ($proxy) { + $proxy->cloned = true; + } + ); + + $cloned = clone $proxy; + + $this->assertSame('newClonedValue', $cloned->clonedValue); + $this->assertFalse($proxy->cloned); + $this->assertTrue($cloned->cloned); + } + + /** + * @group DCOM-175 + */ + public function testClonesPrivateProperties() + { + $proxyClassName = $this->generateProxyClass(__NAMESPACE__ . '\\SerializedClass'); + /* @var $proxy SerializedClass */ + $proxy = new $proxyClassName(); + + $proxy->setFoo(1); + $proxy->setBar(2); + $proxy->setBaz(3); + + $unserialized = unserialize(serialize($proxy)); + + $this->assertSame(1, $unserialized->getFoo()); + $this->assertSame(2, $unserialized->getBar()); + $this->assertSame(3, $unserialized->getBaz()); + } + + /** + * @param $className + * + * @return string + */ + private function generateProxyClass($className) + { + $proxyClassName = 'Doctrine\\Tests\\Common\\Proxy\\MagicMethodProxy\\__CG__\\' . $className; + + if (class_exists($proxyClassName, false)) { + return $proxyClassName; + } + + $metadata = $this->getMock('Doctrine\\Common\\Persistence\\Mapping\\ClassMetadata'); + + $metadata + ->expects($this->any()) + ->method('getName') + ->will($this->returnValue($className)); + + $metadata + ->expects($this->any()) + ->method('getIdentifier') + ->will($this->returnValue(array('id'))); + + $metadata + ->expects($this->any()) + ->method('getReflectionClass') + ->will($this->returnValue(new ReflectionClass($className))); + + $metadata + ->expects($this->any()) + ->method('isIdentifier') + ->will($this->returnCallback(function ($fieldName) { + return 'id' === $fieldName; + })); + + $metadata + ->expects($this->any()) + ->method('hasField') + ->will($this->returnCallback(function ($fieldName) { + return in_array($fieldName, array('id', 'publicField')); + })); + + $metadata + ->expects($this->any()) + ->method('hasAssociation') + ->will($this->returnValue(false)); + + $metadata + ->expects($this->any()) + ->method('getFieldNames') + ->will($this->returnValue(array('id', 'publicField'))); + + $metadata + ->expects($this->any()) + ->method('getIdentifierFieldNames') + ->will($this->returnValue(array('id'))); + + $metadata + ->expects($this->any()) + ->method('getAssociationNames') + ->will($this->returnValue(array())); + + $metadata + ->expects($this->any()) + ->method('getTypeOfField') + ->will($this->returnValue('string')); + + $this->proxyGenerator->generateProxyClass($metadata, $this->proxyGenerator->getProxyFileName($className)); + require_once $this->proxyGenerator->getProxyFileName($className); + + return $proxyClassName; + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/SerializedClass.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/SerializedClass.php new file mode 100644 index 0000000000..a36c3bb74b --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/SerializedClass.php @@ -0,0 +1,72 @@ +foo = $foo; + } + + /** + * @return mixed|string + */ + public function getFoo() + { + return $this->foo; + } + + /** + * @param $bar + */ + public function setBar($bar) + { + $this->bar = $bar; + } + + /** + * @return mixed|string + */ + public function getBar() + { + return $this->bar; + } + + /** + * @param $baz + */ + public function setBaz($baz) + { + $this->baz = $baz; + } + + /** + * @return mixed|string + */ + public function getBaz() + { + return $this->baz; + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/SleepClass.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/SleepClass.php new file mode 100644 index 0000000000..3c6ffcdba3 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Proxy/SleepClass.php @@ -0,0 +1,19 @@ +types = $types; + } + + public function addTypeWithMultipleParameters($foo, $bar, ...$baz) + { + $this->foo = $foo; + $this->bar = $bar; + $this->baz = $baz; + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Reflection/DeeperNamespaceParent.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Reflection/DeeperNamespaceParent.php new file mode 100644 index 0000000000..11b3fc8fa4 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Reflection/DeeperNamespaceParent.php @@ -0,0 +1,7 @@ +getMock('stdClass', array('callGet')); + $getCheckMock->expects($this->never())->method('callGet'); + $initializer = function () use ($getCheckMock) { + call_user_func($getCheckMock); + }; + + $mockProxy = new RuntimePublicReflectionPropertyTestProxyMock(); + $mockProxy->__setInitializer($initializer); + + $reflProperty = new RuntimePublicReflectionProperty( + __NAMESPACE__ . '\RuntimePublicReflectionPropertyTestProxyMock', + 'checkedProperty' + ); + + $this->assertSame('testValue', $reflProperty->getValue($mockProxy)); + unset($mockProxy->checkedProperty); + $this->assertNull($reflProperty->getValue($mockProxy)); + } + + public function testSetValueOnProxyPublicProperty() + { + $setCheckMock = $this->getMock('stdClass', array('neverCallSet')); + $setCheckMock->expects($this->never())->method('neverCallSet'); + $initializer = function () use ($setCheckMock) { + call_user_func(array($setCheckMock, 'neverCallSet')); + }; + + $mockProxy = new RuntimePublicReflectionPropertyTestProxyMock(); + $mockProxy->__setInitializer($initializer); + + $reflProperty = new RuntimePublicReflectionProperty( + __NAMESPACE__ . '\RuntimePublicReflectionPropertyTestProxyMock', + 'checkedProperty' + ); + + $reflProperty->setValue($mockProxy, 'newValue'); + $this->assertSame('newValue', $mockProxy->checkedProperty); + + unset($mockProxy->checkedProperty); + $reflProperty->setValue($mockProxy, 'otherNewValue'); + $this->assertSame('otherNewValue', $mockProxy->checkedProperty); + + $setCheckMock = $this->getMock('stdClass', array('callSet')); + $setCheckMock->expects($this->once())->method('callSet'); + $initializer = function () use ($setCheckMock) { + call_user_func(array($setCheckMock, 'callSet')); + }; + + $mockProxy->__setInitializer($initializer); + $mockProxy->__setInitialized(true); + + unset($mockProxy->checkedProperty); + $reflProperty->setValue($mockProxy, 'againNewValue'); + $this->assertSame('againNewValue', $mockProxy->checkedProperty); + } +} + +/** + * Mock that simulates proxy public property lazy loading + */ +class RuntimePublicReflectionPropertyTestProxyMock implements Proxy +{ + /** + * @var \Closure|null + */ + private $initializer = null; + + /** + * @var \Closure|null + */ + private $initialized = false; + + /** + * @var string + */ + public $checkedProperty = 'testValue'; + + /** + * {@inheritDoc} + */ + public function __getInitializer() + { + return $this->initializer; + } + + /** + * {@inheritDoc} + */ + public function __setInitializer(\Closure $initializer = null) + { + $this->initializer = $initializer; + } + + /** + * {@inheritDoc} + */ + public function __getLazyProperties() + { + } + + /** + * {@inheritDoc} + */ + public function __load() + { + } + + /** + * {@inheritDoc} + */ + public function __isInitialized() + { + return $this->initialized; + } + + /** + * {@inheritDoc} + */ + public function __setInitialized($initialized) + { + $this->initialized = (bool) $initialized; + } + + /** + * @param string $name + */ + public function __get($name) + { + if ($this->initializer) { + $cb = $this->initializer; + $cb(); + } + + return $this->checkedProperty; + } + + /** + * @param string $name + * @param mixed $value + */ + public function __set($name, $value) + { + if ($this->initializer) { + $cb = $this->initializer; + $cb(); + } + + // triggers notices if `$name` is used: see https://bugs.php.net/bug.php?id=63463 + $this->checkedProperty = $value; + } + + /** + * @param string $name + * + * @return integer + */ + public function __isset($name) + { + if ($this->initializer) { + $cb = $this->initializer; + $cb(); + } + + return isset($this->checkedProperty); + } + + /** + * {@inheritDoc} + */ + public function __setCloner(\Closure $cloner = null) + { + } + + /** + * {@inheritDoc} + */ + public function __getCloner() + { + } +} \ No newline at end of file diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Reflection/SameNamespaceParent.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Reflection/SameNamespaceParent.php new file mode 100644 index 0000000000..844d4a55e7 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Reflection/SameNamespaceParent.php @@ -0,0 +1,7 @@ +setExpectedException('ReflectionException'); + } + + $testsRoot = substr(__DIR__, 0, -strlen(__NAMESPACE__) - 1); + $paths = array( + 'Doctrine\\Tests' => array($testsRoot), + ); + $staticReflectionParser = new StaticReflectionParser($parsedClassName, new Psr0FindFile($paths), $classAnnotationOptimize); + $declaringClassName = $staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', 'test')->getClassName(); + $this->assertEquals($expectedClassName, $declaringClassName); + + } + + /** + * @return array + */ + public function parentClassData() + { + $data = array(); + $noParentClassName = 'Doctrine\\Tests\\Common\\Reflection\\NoParent'; + $dummyParentClassName = 'Doctrine\\Tests\\Common\\Reflection\\Dummies\\NoParent'; + foreach (array(false, true) as $classAnnotationOptimize) { + $data[] = array( + $classAnnotationOptimize, $noParentClassName, $noParentClassName, + ); + $data[] = array( + $classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\FullyClassifiedParent', $noParentClassName, + ); + $data[] = array( + $classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\SameNamespaceParent', $noParentClassName, + ); + $data[] = array( + $classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\DeeperNamespaceParent', $dummyParentClassName, + ); + $data[] = array( + $classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\UseParent', $dummyParentClassName, + ); + } + return $data; + } + + /** + * @dataProvider classAnnotationOptimize + */ + public function testClassAnnotationOptimizedParsing($classAnnotationOptimize) { + $testsRoot = substr(__DIR__, 0, -strlen(__NAMESPACE__) - 1); + $paths = array( + 'Doctrine\\Tests' => array($testsRoot), + ); + $staticReflectionParser = new StaticReflectionParser('Doctrine\\Tests\\Common\\Reflection\\ExampleAnnotationClass', new Psr0FindFile($paths), $classAnnotationOptimize); + $expectedDocComment = '/** + * @Annotation( + * key = "value" + * ) + */'; + $this->assertEquals($expectedDocComment, $staticReflectionParser->getDocComment('class')); + } + + /** + * @return array + */ + public function classAnnotationOptimize() + { + return array( + array(false), + array(true) + ); + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Reflection/UseParent.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Reflection/UseParent.php new file mode 100644 index 0000000000..dd512d4d65 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Reflection/UseParent.php @@ -0,0 +1,9 @@ +assertEquals($expectedClassName, ClassUtils::getRealClass($className)); + } + + /** + * @dataProvider dataGetClass + */ + public function testGetClass( $className, $expectedClassName ) + { + $object = new $className(); + $this->assertEquals($expectedClassName, ClassUtils::getClass($object)); + } + + public function testGetParentClass() + { + $parentClass = ClassUtils::getParentClass( 'MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\Doctrine\Tests\Common\Util\ChildObject' ); + $this->assertEquals('stdClass', $parentClass); + } + + public function testGenerateProxyClassName() + { + $this->assertEquals( 'Proxies\__CG__\stdClass', ClassUtils::generateProxyClassName( 'stdClass', 'Proxies' ) ); + } + + /** + * @dataProvider dataGetClass + */ + public function testNewReflectionClass( $className, $expectedClassName ) + { + $reflClass = ClassUtils::newReflectionClass( $className ); + $this->assertEquals( $expectedClassName, $reflClass->getName() ); + } + + /** + * @dataProvider dataGetClass + */ + public function testNewReflectionObject( $className, $expectedClassName ) + { + $object = new $className; + $reflClass = ClassUtils::newReflectionObject( $object ); + $this->assertEquals( $expectedClassName, $reflClass->getName() ); + } + } + + class ChildObject extends \stdClass + { + } +} + +namespace MyProject\Proxies\__CG__ +{ + class stdClass extends \stdClass + { + } +} + +namespace MyProject\Proxies\__CG__\Doctrine\Tests\Common\Util +{ + class ChildObject extends \Doctrine\Tests\Common\Util\ChildObject + { + } +} + +namespace MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__ +{ + class stdClass extends \MyProject\Proxies\__CG__\stdClass + { + } +} + +namespace MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\Doctrine\Tests\Common\Util +{ + class ChildObject extends \MyProject\Proxies\__CG__\Doctrine\Tests\Common\Util\ChildObject + { + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/Common/Util/DebugTest.php b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Util/DebugTest.php new file mode 100644 index 0000000000..66e83376f9 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/Common/Util/DebugTest.php @@ -0,0 +1,65 @@ +foo = "bar"; + $obj->bar = 1234; + + $var = Debug::export($obj, 2); + $this->assertEquals( "stdClass", $var->__CLASS__ ); + } + + public function testExportDateTime() + { + $obj = new \DateTime( "2010-10-10 10:10:10" ); + + $var = Debug::export( $obj, 2 ); + $this->assertEquals( "DateTime", $var->__CLASS__ ); + } + + public function testExportArrayTraversable() + { + $obj = new \ArrayObject(array('foobar')); + + $var = Debug::export($obj, 2); + $this->assertContains('foobar', $var->__STORAGE__); + + $it = new \ArrayIterator(array('foobar')); + + $var = Debug::export($it, 5); + $this->assertContains('foobar', $var->__STORAGE__); + } + + public function testReturnsOutput() + { + ob_start(); + + $dump = Debug::dump('foo'); + $outputValue = ob_get_contents(); + + ob_end_clean(); + + $this->assertSame($outputValue, $dump); + } + + public function testDisablesOutput() + { + ob_start(); + + $dump = Debug::dump('foo', 2, true, false); + $outputValue = ob_get_contents(); + + ob_end_clean(); + + $this->assertEmpty($outputValue); + $this->assertNotSame($outputValue, $dump); + } +} diff --git a/vendor/doctrine/common/tests/Doctrine/Tests/DoctrineTestCase.php b/vendor/doctrine/common/tests/Doctrine/Tests/DoctrineTestCase.php new file mode 100644 index 0000000000..e8323d2940 --- /dev/null +++ b/vendor/doctrine/common/tests/Doctrine/Tests/DoctrineTestCase.php @@ -0,0 +1,10 @@ + Doctrine/Tests/ORM/Functional/Locking/GearmanLockTest.php + +This can run considerable time, because it is using sleep() to test for the timing ranges of locks. \ No newline at end of file diff --git a/vendor/doctrine/dbal/README.md b/vendor/doctrine/dbal/README.md index 970db7bb43..b9956306ad 100644 --- a/vendor/doctrine/dbal/README.md +++ b/vendor/doctrine/dbal/README.md @@ -2,9 +2,9 @@ Powerful database abstraction layer with many features for database schema introspection, schema management and PDO abstraction. -* Master: [![Build Status](https://secure.travis-ci.org/doctrine/dbal.png?branch=master)](http://travis-ci.org/doctrine/dbal) -* 2.3: [![Build Status](https://secure.travis-ci.org/doctrine/dbal.png?branch=2.3)](http://travis-ci.org/doctrine/dbal) -* 2.2: [![Build Status](https://secure.travis-ci.org/doctrine/dbal.png?branch=2.2)](http://travis-ci.org/doctrine/dbal) +* Master: [![Build Status](https://secure.travis-ci.org/doctrine/dbal.png?branch=master)](http://travis-ci.org/doctrine/dbal) [![Dependency Status](https://www.versioneye.com/php/doctrine:dbal/dev-master/badge.png)](https://www.versioneye.com/php/doctrine:dbal/dev-master) +* 2.4: [![Build Status](https://secure.travis-ci.org/doctrine/dbal.png?branch=2.4)](http://travis-ci.org/doctrine/dbal) [![Dependency Status](https://www.versioneye.com/php/doctrine:dbal/2.4.2/badge.png)](https://www.versioneye.com/php/doctrine:dbal/2.4.2) +* 2.3: [![Build Status](https://secure.travis-ci.org/doctrine/dbal.png?branch=2.3)](http://travis-ci.org/doctrine/dbal) [![Dependency Status](https://www.versioneye.com/php/doctrine:dbal/2.3.4/badge.png)](https://www.versioneye.com/php/doctrine:dbal/2.3.4) ## More resources: diff --git a/vendor/doctrine/dbal/SECURITY.md b/vendor/doctrine/dbal/SECURITY.md new file mode 100644 index 0000000000..e18f0dd78a --- /dev/null +++ b/vendor/doctrine/dbal/SECURITY.md @@ -0,0 +1,14 @@ +Security +======== + +The Doctrine library is operating very close to your database and as such needs +to handle and make assumptions about SQL injection vulnerabilities. + +It is vital that you understand how Doctrine approaches security, because +we cannot protect you from SQL injection. + +Please read the documentation chapter on Security in Doctrine DBAL to +understand the assumptions we make. + +- [Latest security.rst page on Github](https://github.com/doctrine/dbal/blob/master/docs/en/reference/security.rst) +- [Security Page in rendered documentation](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/security.html) diff --git a/vendor/doctrine/dbal/UPGRADE b/vendor/doctrine/dbal/UPGRADE.md similarity index 54% rename from vendor/doctrine/dbal/UPGRADE rename to vendor/doctrine/dbal/UPGRADE.md index 04d488cc8b..1d628eef70 100644 --- a/vendor/doctrine/dbal/UPGRADE +++ b/vendor/doctrine/dbal/UPGRADE.md @@ -1,3 +1,89 @@ +# Upgrade to 2.5.1 + +## MINOR BC BREAK: Doctrine\DBAL\Schema\Table + +When adding indexes to ``Doctrine\DBAL\Schema\Table`` via ``addIndex()`` or ``addUniqueIndex()``, +duplicate indexes are not silently ignored/dropped anymore (based on semantics, not naming!). +Duplicate indexes are considered indexes that pass ``isFullfilledBy()`` or ``overrules()`` +in ``Doctrine\DBAL\Schema\Index``. +This is required to make the index renaming feature introduced in 2.5.0 work properly and avoid +issues in the ORM schema tool / DBAL schema manager which pretends users from updating +their schemas and migrate to DBAL 2.5.*. +Additionally it offers more flexibility in declaring indexes for the user and potentially fixes +related issues in the ORM. +With this change, the responsibility to decide which index is a "duplicate" is completely deferred +to the user. +Please also note that adding foreign key constraints to a table via ``addForeignKeyConstraint()``, +``addUnnamedForeignKeyConstraint()`` or ``addNamedForeignKeyConstraint()`` now first checks if an +appropriate index is already present and avoids adding an additional auto-generated one eventually. + +# Upgrade to 2.5 + +## BC BREAK: time type resets date fields to UNIX epoch + +When mapping `time` type field to PHP's `DateTime` instance all unused date fields are +reset to UNIX epoch (i.e. 1970-01-01). This might break any logic which relies on comparing +`DateTime` instances with date fields set to the current date. + +Use `!` format prefix (see http://php.net/manual/en/datetime.createfromformat.php) for parsing +time strings to prevent having different date fields when comparing user input and `DateTime` +instances as mapped by Doctrine. + +## BC BREAK: Doctrine\DBAL\Schema\Table + +The methods ``addIndex()`` and ``addUniqueIndex()`` in ``Doctrine\DBAL\Schema\Table`` +have an additional, optional parameter. If you override these methods, you should +add this new parameter to the declaration of your overridden methods. + +## BC BREAK: Doctrine\DBAL\Connection + +The visibility of the property ``$_platform`` in ``Doctrine\DBAL\Connection`` +was changed from protected to private. If you have subclassed ``Doctrine\DBAL\Connection`` +in your application and accessed ``$_platform`` directly, you have to change the code +portions to use ``getDatabasePlatform()`` instead to retrieve the underlying database +platform. +The reason for this change is the new automatic platform version detection feature, +which lazily evaluates the appropriate platform class to use for the underlying database +server version at runtime. +Please also note, that calling ``getDatabasePlatform()`` now needs to establish a connection +in order to evaluate the appropriate platform class if ``Doctrine\DBAL\Connection`` is not +already connected. Under the following circumstances, it is not possible anymore to retrieve +the platform instance from the connection object without having to do a real connect: + +1. ``Doctrine\DBAL\Connection`` was instantiated without the ``platform`` connection parameter. +2. ``Doctrine\DBAL\Connection`` was instantiated without the ``serverVersion`` connection parameter. +3. The underlying driver is "version aware" and can provide different platform instances + for different versions. +4. The underlying driver connection is "version aware" and can provide the database server + version without having to query for it. + +If one of the above conditions is NOT met, there is no need for ``Doctrine\DBAL\Connection`` +to do a connect when calling ``getDatabasePlatform()``. + +## datetime Type uses date_create() as fallback + +Before 2.5 the DateTime type always required a specific format, defined in +`$platform->getDateTimeFormatString()`, which could cause quite some troubles +on platforms that had various microtime precision formats. Starting with 2.5 +whenever the parsing of a date fails with the predefined platform format, +the `date_create()` function will be used to parse the date. + +This could cause some troubles when your date format is weird and not parsed +correctly by `date_create`, however since databases are rather strict on dates +there should be no problem. + +## Support for pdo_ibm driver removed + +The ``pdo_ibm`` driver is buggy and does not work well with Doctrine. Therefore it will no +longer be supported and has been removed from the ``Doctrine\DBAL\DriverManager`` drivers +map. It is highly encouraged to to use `ibm_db2` driver instead if you want to connect +to an IBM DB2 database as it is much more stable and secure. + +If for some reason you have to utilize the ``pdo_ibm`` driver you can still use the `driverClass` +connection parameter to explicitly specify the ``Doctrine\DBAL\Driver\PDOIbm\Driver`` class. +However be aware that you are doing this at your own risk and it will not be guaranteed that +Doctrine will work as expected. + # Upgrade to 2.4 ## Doctrine\DBAL\Schema\Constraint diff --git a/vendor/doctrine/dbal/bin/doctrine-dbal b/vendor/doctrine/dbal/bin/doctrine-dbal old mode 100644 new mode 100755 index 7ca0142c3c..0531527ddc --- a/vendor/doctrine/dbal/bin/doctrine-dbal +++ b/vendor/doctrine/dbal/bin/doctrine-dbal @@ -1,4 +1,4 @@ #!/usr/bin/env php . + */ -require_once 'Doctrine/Common/ClassLoader.php'; +use Symfony\Component\Console\Helper\HelperSet; +use Doctrine\DBAL\Tools\Console\ConsoleRunner; -$classLoader = new \Doctrine\Common\ClassLoader('Doctrine'); -$classLoader->register(); +$files = array(__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../../../autoload.php'); +$loader = null; +$cwd = getcwd(); +$directories = array($cwd, $cwd . DIRECTORY_SEPARATOR . 'config'); +$configFile = null; -$classLoader = new \Doctrine\Common\ClassLoader('Symfony'); -$classLoader->register(); +foreach ($files as $file) { + if (file_exists($file)) { + $loader = require $file; -$configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php'; + break; + } +} + +if ( ! $loader) { + throw new RuntimeException('vendor/autoload.php could not be found. Did you run `php composer.phar install`?'); +} -$helperSet = null; -if (file_exists($configFile)) { - if ( ! is_readable($configFile)) { - trigger_error( - 'Configuration file [' . $configFile . '] does not have read permission.', E_ERROR - ); +foreach ($directories as $directory) { + $configFile = $directory . DIRECTORY_SEPARATOR . 'cli-config.php'; + + if (file_exists($configFile)) { + break; } +} - require $configFile; +if ( ! file_exists($configFile)) { + ConsoleRunner::printCliConfigTemplate(); + + exit(1); +} +if ( ! is_readable($configFile)) { + echo 'Configuration file [' . $configFile . '] does not have read permission.' . PHP_EOL; + + exit(1); +} + +$commands = array(); +$helperSet = require $configFile; + +if ( ! $helperSet instanceof HelperSet) { foreach ($GLOBALS as $helperSetCandidate) { - if ($helperSetCandidate instanceof \Symfony\Component\Console\Helper\HelperSet) { + if ($helperSetCandidate instanceof HelperSet) { $helperSet = $helperSetCandidate; + break; } } } -$helperSet = ($helperSet) ?: new \Symfony\Component\Console\Helper\HelperSet(); - -$cli = new \Symfony\Component\Console\Application('Doctrine Command Line Interface', Doctrine\DBAL\Version::VERSION); -$cli->setCatchExceptions(true); -$cli->setHelperSet($helperSet); -$cli->addCommands(array( - // DBAL Commands - new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(), - new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(), - new \Doctrine\DBAL\Tools\Console\Command\ReservedWordsCommand(), - -)); -$cli->run(); +ConsoleRunner::run($helperSet, $commands); diff --git a/vendor/doctrine/dbal/bin/doctrine.php b/vendor/doctrine/dbal/bin/doctrine.php deleted file mode 100644 index cd3184d03b..0000000000 --- a/vendor/doctrine/dbal/bin/doctrine.php +++ /dev/null @@ -1,42 +0,0 @@ -register(); - -$classLoader = new \Doctrine\Common\ClassLoader('Symfony'); -$classLoader->register(); - -$configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php'; - -$helperSet = null; -if (file_exists($configFile)) { - if ( ! is_readable($configFile)) { - trigger_error( - 'Configuration file [' . $configFile . '] does not have read permission.', E_ERROR - ); - } - - require $configFile; - - foreach ($GLOBALS as $helperSetCandidate) { - if ($helperSetCandidate instanceof \Symfony\Component\Console\Helper\HelperSet) { - $helperSet = $helperSetCandidate; - break; - } - } -} - -$helperSet = ($helperSet) ?: new \Symfony\Component\Console\Helper\HelperSet(); - -$cli = new \Symfony\Component\Console\Application('Doctrine Command Line Interface', Doctrine\DBAL\Version::VERSION); -$cli->setCatchExceptions(true); -$cli->setHelperSet($helperSet); -$cli->addCommands(array( - // DBAL Commands - new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(), - new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(), - -)); -$cli->run(); diff --git a/vendor/doctrine/dbal/composer.json b/vendor/doctrine/dbal/composer.json index 9972c7da3f..d784b417c5 100644 --- a/vendor/doctrine/dbal/composer.json +++ b/vendor/doctrine/dbal/composer.json @@ -13,18 +13,24 @@ ], "require": { "php": ">=5.3.2", - "doctrine/common": "~2.4" + "doctrine/common": ">=2.4,<2.6-dev" }, "require-dev": { - "phpunit/phpunit": "3.7.*", - "symfony/console": "~2.0" + "phpunit/phpunit": "4.*", + "symfony/console": "2.*" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." }, + "bin": ["bin/doctrine-dbal"], "autoload": { "psr-0": { "Doctrine\\DBAL\\": "lib/" } }, + "extra": { + "branch-alias": { + "dev-master": "2.5.x-dev" + } + }, "archive": { "exclude": ["!vendor", "tests", "*phpunit.xml", ".travis.yml", "build.xml", "build.properties", "composer.phar"] } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ArrayStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ArrayStatement.php index 23f9117260..0752dda31b 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ArrayStatement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ArrayStatement.php @@ -105,11 +105,11 @@ class ArrayStatement implements \IteratorAggregate, ResultStatement $fetchMode = $fetchMode ?: $this->defaultFetchMode; if ($fetchMode === PDO::FETCH_ASSOC) { return $row; - } else if ($fetchMode === PDO::FETCH_NUM) { + } elseif ($fetchMode === PDO::FETCH_NUM) { return array_values($row); - } else if ($fetchMode === PDO::FETCH_BOTH) { + } elseif ($fetchMode === PDO::FETCH_BOTH) { return array_merge($row, array_values($row)); - } else if ($fetchMode === PDO::FETCH_COLUMN) { + } elseif ($fetchMode === PDO::FETCH_COLUMN) { return reset($row); } else { throw new \InvalidArgumentException("Invalid fetch-style given for fetching result."); diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php index a3afe50a0e..0062255e5d 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php @@ -161,11 +161,11 @@ class ResultCacheStatement implements \IteratorAggregate, ResultStatement if ($fetchMode == PDO::FETCH_ASSOC) { return $row; - } else if ($fetchMode == PDO::FETCH_NUM) { + } elseif ($fetchMode == PDO::FETCH_NUM) { return array_values($row); - } else if ($fetchMode == PDO::FETCH_BOTH) { + } elseif ($fetchMode == PDO::FETCH_BOTH) { return array_merge($row, array_values($row)); - } else if ($fetchMode == PDO::FETCH_COLUMN) { + } elseif ($fetchMode == PDO::FETCH_COLUMN) { return reset($row); } else { throw new \InvalidArgumentException("Invalid fetch-style given for caching result."); diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Configuration.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Configuration.php index 0225d1faa1..ec7c130619 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Configuration.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Configuration.php @@ -57,7 +57,7 @@ class Configuration /** * Gets the SQL logger that is used. * - * @return \Doctrine\DBAL\Logging\SQLLogger + * @return \Doctrine\DBAL\Logging\SQLLogger|null */ public function getSQLLogger() { @@ -117,4 +117,36 @@ class Configuration return null; } + + /** + * Sets the default auto-commit mode for connections. + * + * If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual + * transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either + * the method commit or the method rollback. By default, new connections are in auto-commit mode. + * + * @param boolean $autoCommit True to enable auto-commit mode; false to disable it. + * + * @see getAutoCommit + */ + public function setAutoCommit($autoCommit) + { + $this->_attributes['autoCommit'] = (boolean) $autoCommit; + } + + /** + * Returns the default auto-commit mode for connections. + * + * @return boolean True if auto-commit mode is enabled by default for connections, false otherwise. + * + * @see setAutoCommit + */ + public function getAutoCommit() + { + if (isset($this->_attributes['autoCommit'])) { + return $this->_attributes['autoCommit']; + } + + return true; + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php index 6efb24e6b6..8612540d6e 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php @@ -19,17 +19,19 @@ namespace Doctrine\DBAL; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\Exception\InvalidArgumentException; use PDO; use Closure; use Exception; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Driver\Connection as DriverConnection; use Doctrine\Common\EventManager; -use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Cache\ResultCacheStatement; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Cache\ArrayStatement; use Doctrine\DBAL\Cache\CacheException; +use Doctrine\DBAL\Driver\PingableConnection; /** * A wrapper around a Doctrine\DBAL\Driver\Connection that adds features like @@ -117,6 +119,13 @@ class Connection implements DriverConnection */ private $_isConnected = false; + /** + * The current auto-commit mode of this connection. + * + * @var boolean + */ + private $autoCommit = true; + /** * The transaction nesting level. * @@ -134,9 +143,9 @@ class Connection implements DriverConnection /** * If nested transactions should use savepoints. * - * @var integer + * @var boolean */ - private $_nestTransactionsWithSavepoints; + private $_nestTransactionsWithSavepoints = false; /** * The parameters used during creation of the Connection instance. @@ -151,7 +160,7 @@ class Connection implements DriverConnection * * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ - protected $_platform; + private $platform; /** * The schema manager. @@ -198,6 +207,7 @@ class Connection implements DriverConnection if (isset($params['pdo'])) { $this->_conn = $params['pdo']; $this->_isConnected = true; + unset($this->_params['pdo']); } // Create default config and event manager if none given @@ -214,17 +224,7 @@ class Connection implements DriverConnection $this->_expr = new Query\Expression\ExpressionBuilder($this); - if ( ! isset($params['platform'])) { - $this->_platform = $driver->getDatabasePlatform(); - } else if ($params['platform'] instanceof Platforms\AbstractPlatform) { - $this->_platform = $params['platform']; - } else { - throw DBALException::invalidPlatformSpecified(); - } - - $this->_platform->setEventManager($eventManager); - - $this->_transactionIsolationLevel = $this->_platform->getDefaultTransactionIsolationLevel(); + $this->autoCommit = $config->getAutoCommit(); } /** @@ -324,7 +324,11 @@ class Connection implements DriverConnection */ public function getDatabasePlatform() { - return $this->_platform; + if (null == $this->platform) { + $this->detectDatabasePlatform(); + } + + return $this->platform; } /** @@ -348,14 +352,22 @@ class Connection implements DriverConnection if ($this->_isConnected) return false; $driverOptions = isset($this->_params['driverOptions']) ? - $this->_params['driverOptions'] : array(); + $this->_params['driverOptions'] : array(); $user = isset($this->_params['user']) ? $this->_params['user'] : null; $password = isset($this->_params['password']) ? - $this->_params['password'] : null; + $this->_params['password'] : null; $this->_conn = $this->_driver->connect($this->_params, $user, $password, $driverOptions); $this->_isConnected = true; + if (null === $this->platform) { + $this->detectDatabasePlatform(); + } + + if (false === $this->autoCommit) { + $this->beginTransaction(); + } + if ($this->_eventManager->hasListeners(Events::postConnect)) { $eventArgs = new Event\ConnectionEventArgs($this); $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); @@ -364,6 +376,113 @@ class Connection implements DriverConnection return true; } + /** + * Detects and sets the database platform. + * + * Evaluates custom platform class and version in order to set the correct platform. + * + * @throws DBALException if an invalid platform was specified for this connection. + */ + private function detectDatabasePlatform() + { + if ( ! isset($this->_params['platform'])) { + $version = $this->getDatabasePlatformVersion(); + + if (null !== $version) { + $this->platform = $this->_driver->createDatabasePlatformForVersion($version); + } else { + $this->platform = $this->_driver->getDatabasePlatform(); + } + } elseif ($this->_params['platform'] instanceof Platforms\AbstractPlatform) { + $this->platform = $this->_params['platform']; + } else { + throw DBALException::invalidPlatformSpecified(); + } + + $this->platform->setEventManager($this->_eventManager); + } + + /** + * Returns the version of the related platform if applicable. + * + * Returns null if either the driver is not capable to create version + * specific platform instances, no explicit server version was specified + * or the underlying driver connection cannot determine the platform + * version without having to query it (performance reasons). + * + * @return string|null + */ + private function getDatabasePlatformVersion() + { + // Driver does not support version specific platforms. + if ( ! $this->_driver instanceof VersionAwarePlatformDriver) { + return null; + } + + // Explicit platform version requested (supersedes auto-detection). + if (isset($this->_params['serverVersion'])) { + return $this->_params['serverVersion']; + } + + // If not connected, we need to connect now to determine the platform version. + if (null === $this->_conn) { + $this->connect(); + } + + // Automatic platform version detection. + if ($this->_conn instanceof ServerInfoAwareConnection && + ! $this->_conn->requiresQueryForServerVersion() + ) { + return $this->_conn->getServerVersion(); + } + + // Unable to detect platform version. + return null; + } + + /** + * Returns the current auto-commit mode for this connection. + * + * @return boolean True if auto-commit mode is currently enabled for this connection, false otherwise. + * + * @see setAutoCommit + */ + public function isAutoCommit() + { + return true === $this->autoCommit; + } + + /** + * Sets auto-commit mode for this connection. + * + * If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual + * transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either + * the method commit or the method rollback. By default, new connections are in auto-commit mode. + * + * NOTE: If this method is called during a transaction and the auto-commit mode is changed, the transaction is + * committed. If this method is called and the auto-commit mode is not changed, the call is a no-op. + * + * @param boolean $autoCommit True to enable auto-commit mode; false to disable it. + * + * @see isAutoCommit + */ + public function setAutoCommit($autoCommit) + { + $autoCommit = (boolean) $autoCommit; + + // Mode not changed, no-op. + if ($autoCommit === $this->autoCommit) { + return; + } + + $this->autoCommit = $autoCommit; + + // Commit all currently active transactions if any when switching auto-commit mode. + if (true === $this->_isConnected && 0 !== $this->_transactionNestingLevel) { + $this->commitAll(); + } + } + /** * Sets the fetch mode. * @@ -382,12 +501,13 @@ class Connection implements DriverConnection * * @param string $statement The SQL query. * @param array $params The query parameters. + * @param array $types The query parameter types. * * @return array */ - public function fetchAssoc($statement, array $params = array()) + public function fetchAssoc($statement, array $params = array(), array $types = array()) { - return $this->executeQuery($statement, $params)->fetch(PDO::FETCH_ASSOC); + return $this->executeQuery($statement, $params, $types)->fetch(PDO::FETCH_ASSOC); } /** @@ -396,12 +516,13 @@ class Connection implements DriverConnection * * @param string $statement The SQL query to be executed. * @param array $params The prepared statement params. + * @param array $types The query parameter types. * * @return array */ - public function fetchArray($statement, array $params = array()) + public function fetchArray($statement, array $params = array(), array $types = array()) { - return $this->executeQuery($statement, $params)->fetch(PDO::FETCH_NUM); + return $this->executeQuery($statement, $params, $types)->fetch(PDO::FETCH_NUM); } /** @@ -410,13 +531,14 @@ class Connection implements DriverConnection * * @param string $statement The SQL query to be executed. * @param array $params The prepared statement params. - * @param integer $colnum The 0-indexed column number to retrieve. + * @param integer $column The 0-indexed column number to retrieve. + * @param array $types The query parameter types. * * @return mixed */ - public function fetchColumn($statement, array $params = array(), $colnum = 0) + public function fetchColumn($statement, array $params = array(), $column = 0, array $types = array()) { - return $this->executeQuery($statement, $params)->fetchColumn($colnum); + return $this->executeQuery($statement, $params, $types)->fetchColumn($column); } /** @@ -442,14 +564,22 @@ class Connection implements DriverConnection /** * Executes an SQL DELETE statement on a table. * - * @param string $tableName The name of the table on which to delete. + * Table expression and columns are not escaped and are not safe for user-input. + * + * @param string $tableExpression The expression of the table on which to delete. * @param array $identifier The deletion criteria. An associative array containing column-value pairs. * @param array $types The types of identifiers. * * @return integer The number of affected rows. + * + * @throws InvalidArgumentException */ - public function delete($tableName, array $identifier, array $types = array()) + public function delete($tableExpression, array $identifier, array $types = array()) { + if (empty($identifier)) { + throw InvalidArgumentException::fromEmptyCriteria(); + } + $this->connect(); $criteria = array(); @@ -458,13 +588,11 @@ class Connection implements DriverConnection $criteria[] = $columnName . ' = ?'; } - if ( ! is_int(key($types))) { - $types = $this->extractTypeValues($identifier, $types); - } - - $query = 'DELETE FROM ' . $tableName . ' WHERE ' . implode(' AND ', $criteria); - - return $this->executeUpdate($query, array_values($identifier), $types); + return $this->executeUpdate( + 'DELETE FROM ' . $tableExpression . ' WHERE ' . implode(' AND ', $criteria), + array_values($identifier), + is_string(key($types)) ? $this->extractTypeValues($identifier, $types) : $types + ); } /** @@ -474,7 +602,7 @@ class Connection implements DriverConnection */ public function close() { - unset($this->_conn); + $this->_conn = null; $this->_isConnected = false; } @@ -490,7 +618,7 @@ class Connection implements DriverConnection { $this->_transactionIsolationLevel = $level; - return $this->executeUpdate($this->_platform->getSetTransactionIsolationSQL($level)); + return $this->executeUpdate($this->getDatabasePlatform()->getSetTransactionIsolationSQL($level)); } /** @@ -500,20 +628,26 @@ class Connection implements DriverConnection */ public function getTransactionIsolation() { + if (null === $this->_transactionIsolationLevel) { + $this->_transactionIsolationLevel = $this->getDatabasePlatform()->getDefaultTransactionIsolationLevel(); + } + return $this->_transactionIsolationLevel; } /** * Executes an SQL UPDATE statement on a table. * - * @param string $tableName The name of the table to update. + * Table expression and columns are not escaped and are not safe for user-input. + * + * @param string $tableExpression The expression of the table to update quoted or unquoted. * @param array $data An associative array containing column-value pairs. * @param array $identifier The update criteria. An associative array containing column-value pairs. * @param array $types Types of the merged $data and $identifier arrays in that order. * * @return integer The number of affected rows. */ - public function update($tableName, array $data, array $identifier, array $types = array()) + public function update($tableExpression, array $data, array $identifier, array $types = array()) { $this->connect(); $set = array(); @@ -522,13 +656,13 @@ class Connection implements DriverConnection $set[] = $columnName . ' = ?'; } - if ( ! is_int(key($types))) { + if (is_string(key($types))) { $types = $this->extractTypeValues(array_merge($data, $identifier), $types); } $params = array_merge(array_values($data), array_values($identifier)); - $sql = 'UPDATE ' . $tableName . ' SET ' . implode(', ', $set) + $sql = 'UPDATE ' . $tableExpression . ' SET ' . implode(', ', $set) . ' WHERE ' . implode(' = ? AND ', array_keys($identifier)) . ' = ?'; @@ -538,25 +672,27 @@ class Connection implements DriverConnection /** * Inserts a table row with specified data. * - * @param string $tableName The name of the table to insert data into. + * Table expression and columns are not escaped and are not safe for user-input. + * + * @param string $tableExpression The expression of the table to insert data into, quoted or unquoted. * @param array $data An associative array containing column-value pairs. * @param array $types Types of the inserted data. * * @return integer The number of affected rows. */ - public function insert($tableName, array $data, array $types = array()) + public function insert($tableExpression, array $data, array $types = array()) { $this->connect(); if (empty($data)) { - return $this->executeUpdate('INSERT INTO ' . $tableName . ' ()' . ' VALUES ()'); + return $this->executeUpdate('INSERT INTO ' . $tableExpression . ' ()' . ' VALUES ()'); } return $this->executeUpdate( - 'INSERT INTO ' . $tableName . ' (' . implode(', ', array_keys($data)) . ')' . + 'INSERT INTO ' . $tableExpression . ' (' . implode(', ', array_keys($data)) . ')' . ' VALUES (' . implode(', ', array_fill(0, count($data), '?')) . ')', array_values($data), - is_int(key($types)) ? $types : $this->extractTypeValues($data, $types) + is_string(key($types)) ? $this->extractTypeValues($data, $types) : $types ); } @@ -597,7 +733,7 @@ class Connection implements DriverConnection */ public function quoteIdentifier($str) { - return $this->_platform->quoteIdentifier($str); + return $this->getDatabasePlatform()->quoteIdentifier($str); } /** @@ -646,7 +782,7 @@ class Connection implements DriverConnection try { $stmt = new Statement($statement, $this); } catch (\Exception $ex) { - throw DBALException::driverExceptionDuringQuery($ex, $statement); + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement); } $stmt->setFetchMode($this->defaultFetchMode); @@ -668,8 +804,6 @@ class Connection implements DriverConnection * @return \Doctrine\DBAL\Driver\Statement The executed statement. * * @throws \Doctrine\DBAL\DBALException - * - * @internal PERF: Directly prepares a driver statement, not a wrapper. */ public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) { @@ -699,7 +833,7 @@ class Connection implements DriverConnection $stmt = $this->_conn->query($query); } } catch (\Exception $ex) { - throw DBALException::driverExceptionDuringQuery($ex, $query, $this->resolveParams($params, $types)); + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $query, $this->resolveParams($params, $types)); } $stmt->setFetchMode($this->defaultFetchMode); @@ -737,7 +871,7 @@ class Connection implements DriverConnection // is the real key part of this row pointers map or is the cache only pointing to other cache keys? if (isset($data[$realKey])) { $stmt = new ArrayStatement($data[$realKey]); - } else if (array_key_exists($realKey, $data)) { + } elseif (array_key_exists($realKey, $data)) { $stmt = new ArrayStatement(array()); } } @@ -761,12 +895,12 @@ class Connection implements DriverConnection * The function receives a single parameter, an array, that * represents a row of the result set. * - * @return mixed The projected result of the query. + * @return array The projected result of the query. */ public function project($query, array $params, Closure $function) { $result = array(); - $stmt = $this->executeQuery($query, $params ?: array()); + $stmt = $this->executeQuery($query, $params); while ($row = $stmt->fetch()) { $result[] = $function($row); @@ -808,7 +942,7 @@ class Connection implements DriverConnection break; } } catch (\Exception $ex) { - throw DBALException::driverExceptionDuringQuery($ex, $args[0]); + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $args[0]); } $statement->setFetchMode($this->defaultFetchMode); @@ -833,8 +967,6 @@ class Connection implements DriverConnection * @return integer The number of affected rows. * * @throws \Doctrine\DBAL\DBALException - * - * @internal PERF: Directly prepares a driver statement, not a wrapper. */ public function executeUpdate($query, array $params = array(), array $types = array()) { @@ -861,7 +993,7 @@ class Connection implements DriverConnection $result = $this->_conn->exec($query); } } catch (\Exception $ex) { - throw DBALException::driverExceptionDuringQuery($ex, $query, $this->resolveParams($params, $types)); + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $query, $this->resolveParams($params, $types)); } if ($logger) { @@ -892,7 +1024,7 @@ class Connection implements DriverConnection try { $result = $this->_conn->exec($statement); } catch (\Exception $ex) { - throw DBALException::driverExceptionDuringQuery($ex, $statement); + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement); } if ($logger) { @@ -996,11 +1128,11 @@ class Connection implements DriverConnection throw ConnectionException::mayNotAlterNestedTransactionWithSavepointsInTransaction(); } - if ( ! $this->_platform->supportsSavepoints()) { + if ( ! $this->getDatabasePlatform()->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } - $this->_nestTransactionsWithSavepoints = $nestTransactionsWithSavepoints; + $this->_nestTransactionsWithSavepoints = (bool) $nestTransactionsWithSavepoints; } /** @@ -1045,7 +1177,7 @@ class Connection implements DriverConnection if ($logger) { $logger->stopQuery(); } - } else if ($this->_nestTransactionsWithSavepoints) { + } elseif ($this->_nestTransactionsWithSavepoints) { if ($logger) { $logger->startQuery('"SAVEPOINT"'); } @@ -1085,7 +1217,7 @@ class Connection implements DriverConnection if ($logger) { $logger->stopQuery(); } - } else if ($this->_nestTransactionsWithSavepoints) { + } elseif ($this->_nestTransactionsWithSavepoints) { if ($logger) { $logger->startQuery('"RELEASE SAVEPOINT"'); } @@ -1096,6 +1228,28 @@ class Connection implements DriverConnection } --$this->_transactionNestingLevel; + + if (false === $this->autoCommit && 0 === $this->_transactionNestingLevel) { + $this->beginTransaction(); + } + } + + /** + * Commits all current nesting transactions. + */ + private function commitAll() + { + while (0 !== $this->_transactionNestingLevel) { + if (false === $this->autoCommit && 1 === $this->_transactionNestingLevel) { + // When in no auto-commit mode, the last nesting commit immediately starts a new transaction. + // Therefore we need to do the final commit here and then leave to avoid an infinite loop. + $this->commit(); + + return; + } + + $this->commit(); + } } /** @@ -1126,7 +1280,11 @@ class Connection implements DriverConnection if ($logger) { $logger->stopQuery(); } - } else if ($this->_nestTransactionsWithSavepoints) { + + if (false === $this->autoCommit) { + $this->beginTransaction(); + } + } elseif ($this->_nestTransactionsWithSavepoints) { if ($logger) { $logger->startQuery('"ROLLBACK TO SAVEPOINT"'); } @@ -1152,11 +1310,11 @@ class Connection implements DriverConnection */ public function createSavepoint($savepoint) { - if ( ! $this->_platform->supportsSavepoints()) { + if ( ! $this->getDatabasePlatform()->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } - $this->_conn->exec($this->_platform->createSavePoint($savepoint)); + $this->_conn->exec($this->platform->createSavePoint($savepoint)); } /** @@ -1170,12 +1328,12 @@ class Connection implements DriverConnection */ public function releaseSavepoint($savepoint) { - if ( ! $this->_platform->supportsSavepoints()) { + if ( ! $this->getDatabasePlatform()->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } - if ($this->_platform->supportsReleaseSavepoints()) { - $this->_conn->exec($this->_platform->releaseSavePoint($savepoint)); + if ($this->platform->supportsReleaseSavepoints()) { + $this->_conn->exec($this->platform->releaseSavePoint($savepoint)); } } @@ -1190,11 +1348,11 @@ class Connection implements DriverConnection */ public function rollbackSavepoint($savepoint) { - if ( ! $this->_platform->supportsSavepoints()) { + if ( ! $this->getDatabasePlatform()->supportsSavepoints()) { throw ConnectionException::savepointsNotSupported(); } - $this->_conn->exec($this->_platform->rollbackSavePoint($savepoint)); + $this->_conn->exec($this->platform->rollbackSavePoint($savepoint)); } /** @@ -1267,7 +1425,7 @@ class Connection implements DriverConnection */ public function convertToDatabaseValue($value, $type) { - return Type::getType($type)->convertToDatabaseValue($value, $this->_platform); + return Type::getType($type)->convertToDatabaseValue($value, $this->getDatabasePlatform()); } /** @@ -1281,7 +1439,7 @@ class Connection implements DriverConnection */ public function convertToPHPValue($value, $type) { - return Type::getType($type)->convertToPHPValue($value, $this->_platform); + return Type::getType($type)->convertToPHPValue($value, $this->getDatabasePlatform()); } /** @@ -1343,7 +1501,7 @@ class Connection implements DriverConnection $type = Type::getType($type); } if ($type instanceof Type) { - $value = $type->convertToDatabaseValue($value, $this->_platform); + $value = $type->convertToDatabaseValue($value, $this->getDatabasePlatform()); $bindingType = $type->getBindingType(); } else { $bindingType = $type; // PDO::PARAM_* constants @@ -1408,4 +1566,42 @@ class Connection implements DriverConnection { return new Query\QueryBuilder($this); } + + /** + * Ping the server + * + * When the server is not available the method returns FALSE. + * It is responsibility of the developer to handle this case + * and abort the request or reconnect manually: + * + * @example + * + * if ($conn->ping() === false) { + * $conn->close(); + * $conn->connect(); + * } + * + * It is undefined if the underlying driver attempts to reconnect + * or disconnect when the connection is not available anymore + * as long it returns TRUE when a reconnect succeeded and + * FALSE when the connection was dropped. + * + * @return bool + */ + public function ping() + { + $this->connect(); + + if ($this->_conn instanceof PingableConnection) { + return $this->_conn->ping(); + } + + try { + $this->query($this->getDatabasePlatform()->getDummySelectSQL()); + + return true; + } catch (DBALException $e) { + return false; + } + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php index cca4e86b25..d38e41374d 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php @@ -109,10 +109,10 @@ class MasterSlaveConnection extends Connection */ public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null) { - if ( !isset($params['slaves']) || !isset($params['master']) ) { + if ( !isset($params['slaves']) || !isset($params['master'])) { throw new \InvalidArgumentException('master or slaves configuration missing'); } - if ( count($params['slaves']) == 0 ) { + if (count($params['slaves']) == 0) { throw new \InvalidArgumentException('You have to configure at least one slaves.'); } @@ -121,7 +121,7 @@ class MasterSlaveConnection extends Connection $params['slaves'][$slaveKey]['driver'] = $params['driver']; } - $this->keepSlave = isset($params['keepSlave']) ? (bool)$params['keepSlave'] : false; + $this->keepSlave = isset($params['keepSlave']) ? (bool) $params['keepSlave'] : false; parent::__construct($params, $driver, $config, $eventManager); } @@ -144,7 +144,7 @@ class MasterSlaveConnection extends Connection $requestedConnectionChange = ($connectionName !== null); $connectionName = $connectionName ?: 'slave'; - if ( $connectionName !== 'slave' && $connectionName !== 'master' ) { + if ($connectionName !== 'slave' && $connectionName !== 'master') { throw new \InvalidArgumentException("Invalid option to connect(), only master or slave allowed."); } @@ -248,7 +248,7 @@ class MasterSlaveConnection extends Connection { $this->connect('master'); - return parent::beginTransaction(); + parent::beginTransaction(); } /** @@ -258,7 +258,7 @@ class MasterSlaveConnection extends Connection { $this->connect('master'); - return parent::commit(); + parent::commit(); } /** @@ -290,6 +290,9 @@ class MasterSlaveConnection extends Connection unset($this->connections['slave']); parent::close(); + + $this->_conn = null; + $this->connections = array('master' => null, 'slave' => null); } /** @@ -329,7 +332,7 @@ class MasterSlaveConnection extends Connection { $this->connect('master'); - return parent::createSavepoint($savepoint); + parent::createSavepoint($savepoint); } /** @@ -339,7 +342,7 @@ class MasterSlaveConnection extends Connection { $this->connect('master'); - return parent::releaseSavepoint($savepoint); + parent::releaseSavepoint($savepoint); } /** @@ -349,7 +352,7 @@ class MasterSlaveConnection extends Connection { $this->connect('master'); - return parent::rollbackSavepoint($savepoint); + parent::rollbackSavepoint($savepoint); } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php index b101f48d9b..d85dec8d76 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php @@ -19,6 +19,9 @@ namespace Doctrine\DBAL; +use Doctrine\DBAL\Driver\DriverException; +use Doctrine\DBAL\Driver\ExceptionConverterDriver; + class DBALException extends \Exception { /** @@ -41,6 +44,26 @@ class DBALException extends \Exception "\Doctrine\DBAL\Platforms\AbstractPlatform."); } + /** + * Returns a new instance for an invalid specified platform version. + * + * @param string $version The invalid platform version given. + * @param string $expectedFormat The expected platform version format. + * + * @return DBALException + */ + public static function invalidPlatformVersionSpecified($version, $expectedFormat) + { + return new self( + sprintf( + 'Invalid platform version "%s" specified. ' . + 'The platform version has to be specified in the format: "%s".', + $version, + $expectedFormat + ) + ); + } + /** * @return \Doctrine\DBAL\DBALException */ @@ -74,13 +97,14 @@ class DBALException extends \Exception } /** + * @param \Doctrine\DBAL\Driver $driver * @param \Exception $driverEx * @param string $sql * @param array $params * * @return \Doctrine\DBAL\DBALException */ - public static function driverExceptionDuringQuery(\Exception $driverEx, $sql, array $params = array()) + public static function driverExceptionDuringQuery(Driver $driver, \Exception $driverEx, $sql, array $params = array()) { $msg = "An exception occurred while executing '".$sql."'"; if ($params) { @@ -88,6 +112,27 @@ class DBALException extends \Exception } $msg .= ":\n\n".$driverEx->getMessage(); + if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DriverException) { + return $driver->convertException($msg, $driverEx); + } + + return new self($msg, 0, $driverEx); + } + + /** + * @param \Doctrine\DBAL\Driver $driver + * @param \Exception $driverEx + * + * @return \Doctrine\DBAL\DBALException + */ + public static function driverException(Driver $driver, \Exception $driverEx) + { + $msg = "An exception occured in driver: " . $driverEx->getMessage(); + + if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DriverException) { + return $driver->convertException($msg, $driverEx); + } + return new self($msg, 0, $driverEx); } @@ -101,7 +146,7 @@ class DBALException extends \Exception */ private static function formatParameters(array $params) { - return '[' . implode(', ', array_map(function($param) { + return '[' . implode(', ', array_map(function ($param) { $json = @json_encode($param); if (! is_string($json) || $json == 'null' && is_string($param)) { diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDB2Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDB2Driver.php new file mode 100644 index 0000000000..baa081690c --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDB2Driver.php @@ -0,0 +1,60 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Platforms\DB2Platform; +use Doctrine\DBAL\Schema\DB2SchemaManager; + +/** + * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for IBM DB2 based drivers. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +abstract class AbstractDB2Driver implements Driver +{ + /** + * {@inheritdoc} + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + + return $params['dbname']; + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new DB2Platform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new DB2SchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php new file mode 100644 index 0000000000..c5eee5a073 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php @@ -0,0 +1,75 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +/** + * Abstract base implementation of the {@link DriverException} interface. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +abstract class AbstractDriverException extends \Exception implements DriverException +{ + /** + * The driver specific error code. + * + * @var integer|string|null + */ + private $errorCode; + + /** + * The SQLSTATE of the driver. + * + * @var string|null + */ + private $sqlState; + + /** + * Constructor. + * + * @param string $message The driver error message. + * @param string|null $sqlState The SQLSTATE the driver is in at the time the error occured, if any. + * @param integer|string|null $errorCode The driver specific error code if any. + */ + public function __construct($message, $sqlState = null, $errorCode = null) + { + parent::__construct($message); + + $this->errorCode = $errorCode; + $this->sqlState = $sqlState; + } + + /** + * {@inheritdoc} + */ + public function getErrorCode() + { + return $this->errorCode; + } + + /** + * {@inheritdoc} + */ + public function getSQLState() + { + return $this->sqlState; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php new file mode 100644 index 0000000000..eff7957629 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php @@ -0,0 +1,175 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Platforms\MySQL57Platform; +use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Schema\MySqlSchemaManager; +use Doctrine\DBAL\VersionAwarePlatformDriver; + +/** + * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for MySQL based drivers. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +abstract class AbstractMySQLDriver implements Driver, ExceptionConverterDriver, VersionAwarePlatformDriver +{ + /** + * {@inheritdoc} + * + * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-client.html + * @link http://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html + */ + public function convertException($message, DriverException $exception) + { + switch ($exception->getErrorCode()) { + case '1050': + return new Exception\TableExistsException($message, $exception); + + case '1051': + case '1146': + return new Exception\TableNotFoundException($message, $exception); + + case '1216': + case '1217': + case '1451': + case '1452': + case '1701': + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + + case '1062': + case '1557': + case '1569': + case '1586': + return new Exception\UniqueConstraintViolationException($message, $exception); + + case '1054': + case '1166': + case '1611': + return new Exception\InvalidFieldNameException($message, $exception); + + case '1052': + case '1060': + case '1110': + return new Exception\NonUniqueFieldNameException($message, $exception); + + case '1064': + case '1149': + case '1287': + case '1341': + case '1342': + case '1343': + case '1344': + case '1382': + case '1479': + case '1541': + case '1554': + case '1626': + return new Exception\SyntaxErrorException($message, $exception); + + case '1044': + case '1045': + case '1046': + case '1049': + case '1095': + case '1142': + case '1143': + case '1227': + case '1370': + case '2002': + case '2005': + return new Exception\ConnectionException($message, $exception); + + case '1048': + case '1121': + case '1138': + case '1171': + case '1252': + case '1263': + case '1566': + return new Exception\NotNullConstraintViolationException($message, $exception); + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + */ + public function createDatabasePlatformForVersion($version) + { + if ( ! preg_match('/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?/', $version, $versionParts)) { + throw DBALException::invalidPlatformVersionSpecified( + $version, + '..' + ); + } + + if (false !== stripos($version, 'mariadb')) { + return $this->getDatabasePlatform(); + } + + $majorVersion = $versionParts['major']; + $minorVersion = isset($versionParts['minor']) ? $versionParts['minor'] : 0; + $patchVersion = isset($versionParts['patch']) ? $versionParts['patch'] : 0; + $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion; + + if (version_compare($version, '5.7', '>=')) { + return new MySQL57Platform(); + } + + return $this->getDatabasePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + + if (isset($params['dbname'])) { + return $params['dbname']; + } + + return $conn->query('SELECT DATABASE()')->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new MySqlPlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new MySqlSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php new file mode 100644 index 0000000000..1a0d9777ff --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php @@ -0,0 +1,151 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Platforms\OraclePlatform; +use Doctrine\DBAL\Schema\OracleSchemaManager; + +/** + * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for Oracle based drivers. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +abstract class AbstractOracleDriver implements Driver, ExceptionConverterDriver +{ + /** + * {@inheritdoc} + */ + public function convertException($message, DriverException $exception) + { + switch ($exception->getErrorCode()) { + case '1': + case '2299': + case '38911': + return new Exception\UniqueConstraintViolationException($message, $exception); + + case '904': + return new Exception\InvalidFieldNameException($message, $exception); + + case '918': + case '960': + return new Exception\NonUniqueFieldNameException($message, $exception); + + case '923': + return new Exception\SyntaxErrorException($message, $exception); + + case '942': + return new Exception\TableNotFoundException($message, $exception); + + case '955': + return new Exception\TableExistsException($message, $exception); + + case '1017': + case '12545': + return new Exception\ConnectionException($message, $exception); + + case '1400': + return new Exception\NotNullConstraintViolationException($message, $exception); + + case '2266': + case '2291': + case '2292': + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + + return $params['user']; + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new OraclePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new OracleSchemaManager($conn); + } + + /** + * Returns an appropriate Easy Connect String for the given parameters. + * + * @param array $params The connection parameters to return the Easy Connect STring for. + * + * @return string + * + * @link http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm + */ + protected function getEasyConnectString(array $params) + { + if ( ! empty($params['host'])) { + if ( ! isset($params['port'])) { + $params['port'] = 1521; + } + + $serviceName = $params['dbname']; + + if ( ! empty($params['servicename'])) { + $serviceName = $params['servicename']; + } + + $service = 'SID=' . $serviceName; + $pooled = ''; + $instance = ''; + + if (isset($params['service']) && $params['service'] == true) { + $service = 'SERVICE_NAME=' . $serviceName; + } + + if (isset($params['instancename']) && ! empty($params['instancename'])) { + $instance = '(INSTANCE_NAME = ' . $params['instancename'] . ')'; + } + + if (isset($params['pooled']) && $params['pooled'] == true) { + $pooled = '(SERVER=POOLED)'; + } + + return '(DESCRIPTION=' . + '(ADDRESS=(PROTOCOL=TCP)(HOST=' . $params['host'] . ')(PORT=' . $params['port'] . '))' . + '(CONNECT_DATA=(' . $service . ')' . $instance . $pooled . '))'; + + } + + return isset($params['dbname']) ? $params['dbname'] : ''; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php new file mode 100644 index 0000000000..4ad7cbeef2 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php @@ -0,0 +1,148 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Platforms\PostgreSQL91Platform; +use Doctrine\DBAL\Platforms\PostgreSQL92Platform; +use Doctrine\DBAL\Platforms\PostgreSqlPlatform; +use Doctrine\DBAL\Schema\PostgreSqlSchemaManager; +use Doctrine\DBAL\VersionAwarePlatformDriver; + +/** + * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for PostgreSQL based drivers. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +abstract class AbstractPostgreSQLDriver implements Driver, ExceptionConverterDriver, VersionAwarePlatformDriver +{ + /** + * {@inheritdoc} + * + * @link http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html + */ + public function convertException($message, DriverException $exception) + { + switch ($exception->getSQLState()) { + case '0A000': + // Foreign key constraint violations during a TRUNCATE operation + // are considered "feature not supported" in PostgreSQL. + if (strpos($exception->getMessage(), 'truncate') !== false) { + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + } + + break; + case '23502': + return new Exception\NotNullConstraintViolationException($message, $exception); + + case '23503': + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + + case '23505': + return new Exception\UniqueConstraintViolationException($message, $exception); + + case '42601': + return new Exception\SyntaxErrorException($message, $exception); + + case '42702': + return new Exception\NonUniqueFieldNameException($message, $exception); + + case '42703': + return new Exception\InvalidFieldNameException($message, $exception); + + case '42P01': + return new Exception\TableNotFoundException($message, $exception); + + case '42P07': + return new Exception\TableExistsException($message, $exception); + + case '7': + // In some case (mainly connection errors) the PDO exception does not provide a SQLSTATE via its code. + // The exception code is always set to 7 here. + // We have to match against the SQLSTATE in the error message in these cases. + if (strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) { + return new Exception\ConnectionException($message, $exception); + } + + break; + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + */ + public function createDatabasePlatformForVersion($version) + { + if ( ! preg_match('/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?/', $version, $versionParts)) { + throw DBALException::invalidPlatformVersionSpecified( + $version, + '..' + ); + } + + $majorVersion = $versionParts['major']; + $minorVersion = isset($versionParts['minor']) ? $versionParts['minor'] : 0; + $patchVersion = isset($versionParts['patch']) ? $versionParts['patch'] : 0; + $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion; + + switch(true) { + case version_compare($version, '9.2', '>='): + return new PostgreSQL92Platform(); + case version_compare($version, '9.1', '>='): + return new PostgreSQL91Platform(); + default: + return new PostgreSqlPlatform(); + } + } + + /** + * {@inheritdoc} + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + + return (isset($params['dbname'])) + ? $params['dbname'] + : $conn->query('SELECT CURRENT_DATABASE()')->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new PostgreSqlPlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new PostgreSqlSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php new file mode 100644 index 0000000000..0527555af4 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php @@ -0,0 +1,141 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Platforms\SQLAnywhere11Platform; +use Doctrine\DBAL\Platforms\SQLAnywhere12Platform; +use Doctrine\DBAL\Platforms\SQLAnywhere16Platform; +use Doctrine\DBAL\Platforms\SQLAnywherePlatform; +use Doctrine\DBAL\Schema\SQLAnywhereSchemaManager; +use Doctrine\DBAL\VersionAwarePlatformDriver; + +/** + * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for SAP Sybase SQL Anywhere based drivers. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +abstract class AbstractSQLAnywhereDriver implements Driver, ExceptionConverterDriver, VersionAwarePlatformDriver +{ + /** + * {@inheritdoc} + * + * @link http://dcx.sybase.com/index.html#sa160/en/saerrors/sqlerror.html + */ + public function convertException($message, DriverException $exception) + { + switch ($exception->getErrorCode()) { + case '-100': + case '-103': + case '-832': + return new Exception\ConnectionException($message, $exception); + case '-143': + return new Exception\InvalidFieldNameException($message, $exception); + case '-193': + case '-196': + return new Exception\UniqueConstraintViolationException($message, $exception); + case '-194': + case '-198': + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + case '-144': + return new Exception\NonUniqueFieldNameException($message, $exception); + case '-184': + case '-195': + return new Exception\NotNullConstraintViolationException($message, $exception); + case '-131': + return new Exception\SyntaxErrorException($message, $exception); + case '-110': + return new Exception\TableExistsException($message, $exception); + case '-141': + case '-1041': + return new Exception\TableNotFoundException($message, $exception); + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + */ + public function createDatabasePlatformForVersion($version) + { + if ( ! preg_match( + '/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?)?/', + $version, + $versionParts + )) { + throw DBALException::invalidPlatformVersionSpecified( + $version, + '...' + ); + } + + $majorVersion = $versionParts['major']; + $minorVersion = isset($versionParts['minor']) ? $versionParts['minor'] : 0; + $patchVersion = isset($versionParts['patch']) ? $versionParts['patch'] : 0; + $buildVersion = isset($versionParts['build']) ? $versionParts['build'] : 0; + $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion . '.' . $buildVersion; + + switch(true) { + case version_compare($version, '16', '>='): + return new SQLAnywhere16Platform(); + case version_compare($version, '12', '>='): + return new SQLAnywhere12Platform(); + case version_compare($version, '11', '>='): + return new SQLAnywhere11Platform(); + default: + return new SQLAnywherePlatform(); + } + } + + /** + * {@inheritdoc} + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + + if (isset($params['dbname'])) { + return $params['dbname']; + } + + return $conn->query('SELECT DB_NAME()')->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new SQLAnywhere12Platform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new SQLAnywhereSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php new file mode 100644 index 0000000000..53a4dd5262 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php @@ -0,0 +1,104 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Platforms\SQLServer2005Platform; +use Doctrine\DBAL\Platforms\SQLServer2008Platform; +use Doctrine\DBAL\Platforms\SQLServer2012Platform; +use Doctrine\DBAL\Platforms\SQLServerPlatform; +use Doctrine\DBAL\Schema\SQLServerSchemaManager; +use Doctrine\DBAL\VersionAwarePlatformDriver; + +/** + * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for Microsoft SQL Server based drivers. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +abstract class AbstractSQLServerDriver implements Driver, VersionAwarePlatformDriver +{ + /** + * {@inheritdoc} + */ + public function createDatabasePlatformForVersion($version) + { + if ( ! preg_match( + '/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?)?/', + $version, + $versionParts + )) { + throw DBALException::invalidPlatformVersionSpecified( + $version, + '...' + ); + } + + $majorVersion = $versionParts['major']; + $minorVersion = isset($versionParts['minor']) ? $versionParts['minor'] : 0; + $patchVersion = isset($versionParts['patch']) ? $versionParts['patch'] : 0; + $buildVersion = isset($versionParts['build']) ? $versionParts['build'] : 0; + $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion . '.' . $buildVersion; + + switch(true) { + case version_compare($version, '11.00.2100', '>='): + return new SQLServer2012Platform(); + case version_compare($version, '10.00.1600', '>='): + return new SQLServer2008Platform(); + case version_compare($version, '9.00.1399', '>='): + return new SQLServer2005Platform(); + default: + return new SQLServerPlatform(); + } + } + + /** + * {@inheritdoc} + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + + if (isset($params['dbname'])) { + return $params['dbname']; + } + + return $conn->query('SELECT DB_NAME()')->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new SQLServer2008Platform(); + } + + /** + * {@inheritdoc} + */ + + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new SQLServerSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php new file mode 100644 index 0000000000..0facc9b815 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php @@ -0,0 +1,113 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Platforms\SqlitePlatform; +use Doctrine\DBAL\Schema\SqliteSchemaManager; + +/** + * Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for SQLite based drivers. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +abstract class AbstractSQLiteDriver implements Driver, ExceptionConverterDriver +{ + /** + * {@inheritdoc} + * + * @link http://www.sqlite.org/c3ref/c_abort.html + */ + public function convertException($message, DriverException $exception) + { + if (strpos($exception->getMessage(), 'must be unique') !== false || + strpos($exception->getMessage(), 'is not unique') !== false || + strpos($exception->getMessage(), 'are not unique') !== false || + strpos($exception->getMessage(), 'UNIQUE constraint failed') !== false + ) { + return new Exception\UniqueConstraintViolationException($message, $exception); + } + + if (strpos($exception->getMessage(), 'may not be NULL') !== false || + strpos($exception->getMessage(), 'NOT NULL constraint failed') !== false + ) { + return new Exception\NotNullConstraintViolationException($message, $exception); + } + + if (strpos($exception->getMessage(), 'no such table:') !== false) { + return new Exception\TableNotFoundException($message, $exception); + } + + if (strpos($exception->getMessage(), 'already exists') !== false) { + return new Exception\TableExistsException($message, $exception); + } + + if (strpos($exception->getMessage(), 'has no column named') !== false) { + return new Exception\InvalidFieldNameException($message, $exception); + } + + if (strpos($exception->getMessage(), 'ambiguous column name') !== false) { + return new Exception\NonUniqueFieldNameException($message, $exception); + } + + if (strpos($exception->getMessage(), 'syntax error') !== false) { + return new Exception\SyntaxErrorException($message, $exception); + } + + if (strpos($exception->getMessage(), 'attempt to write a readonly database') !== false) { + return new Exception\ReadOnlyException($message, $exception); + } + + if (strpos($exception->getMessage(), 'unable to open database file') !== false) { + return new Exception\ConnectionException($message, $exception); + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + + return isset($params['path']) ? $params['path'] : null; + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new SqlitePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new SqliteSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DriverException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DriverException.php new file mode 100644 index 0000000000..f11146b1bf --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DriverException.php @@ -0,0 +1,59 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +/** + * Contract for a driver exception. + * + * Driver exceptions provide the SQLSTATE of the driver + * and the driver specific error code at the time the error occurred. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +interface DriverException +{ + /** + * Returns the driver specific error code if available. + * + * Returns null if no driver specific error code is available + * for the error raised by the driver. + * + * @return integer|string|null + */ + public function getErrorCode(); + + /** + * Returns the driver error message. + * + * @return string + */ + public function getMessage(); + + /** + * Returns the SQLSTATE the driver was in at the time the error occurred. + * + * Returns null if the driver does not provide a SQLSTATE for the error occurred. + * + * @return string|null + */ + public function getSQLState(); +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php index 2b46c99256..92ca6601f4 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php @@ -27,7 +27,7 @@ class Connection extends \Doctrine\DBAL\Driver\PDOConnection /** * {@inheritdoc} */ - public function quote($value, $type=\PDO::PARAM_STR) + public function quote($value, $type = \PDO::PARAM_STR) { if (\PDO::PARAM_BOOL === $type) { if ($value) { @@ -36,6 +36,7 @@ class Connection extends \Doctrine\DBAL\Driver\PDOConnection return 'false'; } } + return parent::quote($value, $type); } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php index 376718b509..ff4cf3b83d 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php @@ -19,12 +19,15 @@ namespace Doctrine\DBAL\Driver\DrizzlePDOMySql; +use Doctrine\DBAL\Platforms\DrizzlePlatform; +use Doctrine\DBAL\Schema\DrizzleSchemaManager; + /** * Drizzle driver using PDO MySql. * * @author Kim Hemsø Rasmussen */ -class Driver implements \Doctrine\DBAL\Driver +class Driver extends \Doctrine\DBAL\Driver\PDOMySql\Driver { /** * {@inheritdoc} @@ -32,38 +35,21 @@ class Driver implements \Doctrine\DBAL\Driver public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { $conn = new Connection( - $this->_constructPdoDsn($params), + $this->constructPdoDsn($params), $username, $password, $driverOptions ); + return $conn; } /** - * Constructs the Drizzle MySql PDO DSN. - * - * @param array $params - * - * @return string The DSN. + * {@inheritdoc} */ - private function _constructPdoDsn(array $params) + public function createDatabasePlatformForVersion($version) { - $dsn = 'mysql:'; - if (isset($params['host']) && $params['host'] != '') { - $dsn .= 'host=' . $params['host'] . ';'; - } - if (isset($params['port'])) { - $dsn .= 'port=' . $params['port'] . ';'; - } - if (isset($params['dbname'])) { - $dsn .= 'dbname=' . $params['dbname'] . ';'; - } - if (isset($params['unix_socket'])) { - $dsn .= 'unix_socket=' . $params['unix_socket'] . ';'; - } - - return $dsn; + return $this->getDatabasePlatform(); } /** @@ -71,7 +57,7 @@ class Driver implements \Doctrine\DBAL\Driver */ public function getDatabasePlatform() { - return new \Doctrine\DBAL\Platforms\DrizzlePlatform(); + return new DrizzlePlatform(); } /** @@ -79,7 +65,7 @@ class Driver implements \Doctrine\DBAL\Driver */ public function getSchemaManager(\Doctrine\DBAL\Connection $conn) { - return new \Doctrine\DBAL\Schema\DrizzleSchemaManager($conn); + return new DrizzleSchemaManager($conn); } /** @@ -89,14 +75,4 @@ class Driver implements \Doctrine\DBAL\Driver { return 'drizzle_pdo_mysql'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - return $params['dbname']; - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php new file mode 100644 index 0000000000..0bd8d516e1 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php @@ -0,0 +1,44 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +/** + * Contract for a driver that is capable of converting DBAL driver exceptions into standardized DBAL driver exceptions. + * + * @author Benjamin Eberlei + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +interface ExceptionConverterDriver +{ + /** + * Converts a given DBAL driver exception into a standardized DBAL driver exception. + * + * It evaluates the vendor specific error code and SQLSTATE and transforms + * it into a unified {@link Doctrine\DBAL\Exception\DriverException} subclass. + * + * @param string $message The DBAL exception message to use. + * @param \Doctrine\DBAL\Driver\DriverException $exception The DBAL driver exception to convert. + * + * @return \Doctrine\DBAL\Exception\DriverException An instance of one of the DriverException subclasses. + */ + public function convertException($message, DriverException $exception); +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php index 4571c45104..0e809e2f5c 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php @@ -19,7 +19,10 @@ namespace Doctrine\DBAL\Driver\IBMDB2; -class DB2Connection implements \Doctrine\DBAL\Driver\Connection +use Doctrine\DBAL\Driver\Connection; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; + +class DB2Connection implements Connection, ServerInfoAwareConnection { /** * @var resource @@ -48,6 +51,24 @@ class DB2Connection implements \Doctrine\DBAL\Driver\Connection } } + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + $serverInfo = db2_server_info($this->_conn); + + return $serverInfo->DBMS_VER; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; + } + /** * {@inheritdoc} */ @@ -57,6 +78,7 @@ class DB2Connection implements \Doctrine\DBAL\Driver\Connection if ( ! $stmt) { throw new DB2Exception(db2_stmt_errormsg()); } + return new DB2Statement($stmt); } @@ -69,6 +91,7 @@ class DB2Connection implements \Doctrine\DBAL\Driver\Connection $sql = $args[0]; $stmt = $this->prepare($sql); $stmt->execute(); + return $stmt; } @@ -78,7 +101,7 @@ class DB2Connection implements \Doctrine\DBAL\Driver\Connection public function quote($input, $type=\PDO::PARAM_STR) { $input = db2_escape_string($input); - if ($type == \PDO::PARAM_INT ) { + if ($type == \PDO::PARAM_INT) { return $input; } else { return "'".$input."'"; @@ -92,6 +115,7 @@ class DB2Connection implements \Doctrine\DBAL\Driver\Connection { $stmt = $this->prepare($statement); $stmt->execute(); + return $stmt->rowCount(); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php index 447b2c5b13..8ed82e4dda 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php @@ -19,8 +19,7 @@ namespace Doctrine\DBAL\Driver\IBMDB2; -use Doctrine\DBAL\Driver; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\AbstractDB2Driver; /** * IBM DB2 Driver. @@ -28,7 +27,7 @@ use Doctrine\DBAL\Connection; * @since 2.0 * @author Benjamin Eberlei */ -class DB2Driver implements Driver +class DB2Driver extends AbstractDB2Driver { /** * {@inheritdoc} @@ -58,22 +57,6 @@ class DB2Driver implements Driver return new DB2Connection($params, $username, $password, $driverOptions); } - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\DB2Platform; - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(Connection $conn) - { - return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn); - } - /** * {@inheritdoc} */ @@ -81,14 +64,4 @@ class DB2Driver implements Driver { return 'ibm_db2'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - return $params['dbname']; - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php index bf63eac7c8..b8de9ea978 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php @@ -19,7 +19,7 @@ namespace Doctrine\DBAL\Driver\IBMDB2; -use \Doctrine\DBAL\Driver\Statement; +use Doctrine\DBAL\Driver\Statement; class DB2Statement implements \IteratorAggregate, Statement { @@ -33,6 +33,16 @@ class DB2Statement implements \IteratorAggregate, Statement */ private $_bindParam = array(); + /** + * @var string Name of the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. + */ + private $defaultFetchClass = '\stdClass'; + + /** + * @var string Constructor arguments for the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. + */ + private $defaultFetchClassCtorArgs = array(); + /** * @var integer */ @@ -165,7 +175,9 @@ class DB2Statement implements \IteratorAggregate, Statement */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { - $this->_defaultFetchMode = $fetchMode; + $this->_defaultFetchMode = $fetchMode; + $this->defaultFetchClass = $arg2 ? $arg2 : $this->defaultFetchClass; + $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; return true; } @@ -191,8 +203,27 @@ class DB2Statement implements \IteratorAggregate, Statement return db2_fetch_both($this->_stmt); case \PDO::FETCH_ASSOC: return db2_fetch_assoc($this->_stmt); + case \PDO::FETCH_CLASS: + $className = $this->defaultFetchClass; + $ctorArgs = $this->defaultFetchClassCtorArgs; + + if (func_num_args() >= 2) { + $args = func_get_args(); + $className = $args[1]; + $ctorArgs = isset($args[2]) ? $args[2] : array(); + } + + $result = db2_fetch_object($this->_stmt); + + if ($result instanceof \stdClass) { + $result = $this->castObject($result, $className, $ctorArgs); + } + + return $result; case \PDO::FETCH_NUM: return db2_fetch_array($this->_stmt); + case \PDO::FETCH_OBJ: + return db2_fetch_object($this->_stmt); default: throw new DB2Exception("Given Fetch-Style " . $fetchMode . " is not supported."); } @@ -204,8 +235,22 @@ class DB2Statement implements \IteratorAggregate, Statement public function fetchAll($fetchMode = null) { $rows = array(); - while ($row = $this->fetch($fetchMode)) { - $rows[] = $row; + + switch ($fetchMode) { + case \PDO::FETCH_CLASS: + while ($row = call_user_func_array(array($this, 'fetch'), func_get_args())) { + $rows[] = $row; + } + break; + case \PDO::FETCH_COLUMN: + while ($row = $this->fetchColumn()) { + $rows[] = $row; + } + break; + default: + while ($row = $this->fetch($fetchMode)) { + $rows[] = $row; + } } return $rows; @@ -217,11 +262,12 @@ class DB2Statement implements \IteratorAggregate, Statement public function fetchColumn($columnIndex = 0) { $row = $this->fetch(\PDO::FETCH_NUM); - if ($row && isset($row[$columnIndex])) { - return $row[$columnIndex]; + + if (false === $row) { + return false; } - return false; + return isset($row[$columnIndex]) ? $row[$columnIndex] : null; } /** @@ -231,4 +277,68 @@ class DB2Statement implements \IteratorAggregate, Statement { return (@db2_num_rows($this->_stmt))?:0; } + + /** + * Casts a stdClass object to the given class name mapping its' properties. + * + * @param \stdClass $sourceObject Object to cast from. + * @param string|object $destinationClass Name of the class or class instance to cast to. + * @param array $ctorArgs Arguments to use for constructing the destination class instance. + * + * @return object + * + * @throws DB2Exception + */ + private function castObject(\stdClass $sourceObject, $destinationClass, array $ctorArgs = array()) + { + if ( ! is_string($destinationClass)) { + if ( ! is_object($destinationClass)) { + throw new DB2Exception(sprintf( + 'Destination class has to be of type string or object, %s given.', gettype($destinationClass) + )); + } + } else { + $destinationClass = new \ReflectionClass($destinationClass); + $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); + } + + $sourceReflection = new \ReflectionObject($sourceObject); + $destinationClassReflection = new \ReflectionObject($destinationClass); + /** @var \ReflectionProperty[] $destinationProperties */ + $destinationProperties = array_change_key_case($destinationClassReflection->getProperties(), \CASE_LOWER); + + foreach ($sourceReflection->getProperties() as $sourceProperty) { + $sourceProperty->setAccessible(true); + + $name = $sourceProperty->getName(); + $value = $sourceProperty->getValue($sourceObject); + + // Try to find a case-matching property. + if ($destinationClassReflection->hasProperty($name)) { + $destinationProperty = $destinationClassReflection->getProperty($name); + + $destinationProperty->setAccessible(true); + $destinationProperty->setValue($destinationClass, $value); + + continue; + } + + $name = strtolower($name); + + // Try to find a property without matching case. + // Fallback for the driver returning either all uppercase or all lowercase column names. + if (isset($destinationProperties[$name])) { + $destinationProperty = $destinationProperties[$name]; + + $destinationProperty->setAccessible(true); + $destinationProperty->setValue($destinationClass, $value); + + continue; + } + + $destinationClass->$name = $value; + } + + return $destinationClass; + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php index 74d5a1ed98..8949d2b008 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php @@ -19,19 +19,24 @@ namespace Doctrine\DBAL\Driver\Mysqli; -use Doctrine\DBAL\Driver as DriverInterface; +use Doctrine\DBAL\Driver\AbstractMySQLDriver; +use Doctrine\DBAL\DBALException; /** * @author Kim Hemsø Rasmussen */ -class Driver implements DriverInterface +class Driver extends AbstractMySQLDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { - return new MysqliConnection($params, $username, $password, $driverOptions); + try { + return new MysqliConnection($params, $username, $password, $driverOptions); + } catch (MysqliException $e) { + throw DBALException::driverException($this, $e); + } } /** @@ -41,30 +46,4 @@ class Driver implements DriverInterface { return 'mysqli'; } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(\Doctrine\DBAL\Connection $conn) - { - return new \Doctrine\DBAL\Schema\MySqlSchemaManager($conn); - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\MySqlPlatform(); - } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - return $params['dbname']; - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php index b4d4f9db59..ae3502c168 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php @@ -20,12 +20,20 @@ namespace Doctrine\DBAL\Driver\Mysqli; use Doctrine\DBAL\Driver\Connection as Connection; +use Doctrine\DBAL\Driver\PingableConnection; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; /** * @author Kim Hemsø Rasmussen + * @author Till Klampaeckel */ -class MysqliConnection implements Connection +class MysqliConnection implements Connection, PingableConnection, ServerInfoAwareConnection { + /** + * Name of the option to set connection flags + */ + const OPTION_FLAGS = 'flags'; + /** * @var \mysqli */ @@ -42,14 +50,31 @@ class MysqliConnection implements Connection public function __construct(array $params, $username, $password, array $driverOptions = array()) { $port = isset($params['port']) ? $params['port'] : ini_get('mysqli.default_port'); + + // Fallback to default MySQL port if not given. + if ( ! $port) { + $port = 3306; + } + $socket = isset($params['unix_socket']) ? $params['unix_socket'] : ini_get('mysqli.default_socket'); $dbname = isset($params['dbname']) ? $params['dbname'] : null; + $flags = isset($driverOptions[static::OPTION_FLAGS]) ? $driverOptions[static::OPTION_FLAGS] : null; + $this->_conn = mysqli_init(); - if ( ! $this->_conn->real_connect($params['host'], $username, $password, $dbname, $port, $socket)) { - throw new MysqliException($this->_conn->connect_error, $this->_conn->connect_errno); + + $this->setDriverOptions($driverOptions); + + set_error_handler(function () {}); + + if ( ! $this->_conn->real_connect($params['host'], $username, $password, $dbname, $port, $socket, $flags)) { + restore_error_handler(); + + throw new MysqliException($this->_conn->connect_error, @$this->_conn->sqlstate ?: 'HY000', $this->_conn->connect_errno); } + restore_error_handler(); + if (isset($params['charset'])) { $this->_conn->set_charset($params['charset']); } @@ -67,6 +92,26 @@ class MysqliConnection implements Connection return $this->_conn; } + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + $majorVersion = floor($this->_conn->server_version / 10000); + $minorVersion = floor(($this->_conn->server_version - $majorVersion * 10000) / 100); + $patchVersion = floor($this->_conn->server_version - $majorVersion * 10000 - $minorVersion * 100); + + return $majorVersion . '.' . $minorVersion . '.' . $patchVersion; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; + } + /** * {@inheritdoc} */ @@ -84,6 +129,7 @@ class MysqliConnection implements Connection $sql = $args[0]; $stmt = $this->prepare($sql); $stmt->execute(); + return $stmt; } @@ -100,7 +146,10 @@ class MysqliConnection implements Connection */ public function exec($statement) { - $this->_conn->query($statement); + if (false === $this->_conn->query($statement)) { + throw new MysqliException($this->_conn->error, $this->_conn->sqlstate, $this->_conn->errno); + } + return $this->_conn->affected_rows; } @@ -118,6 +167,7 @@ class MysqliConnection implements Connection public function beginTransaction() { $this->_conn->query('START TRANSACTION'); + return true; } @@ -152,4 +202,65 @@ class MysqliConnection implements Connection { return $this->_conn->error; } + + /** + * Apply the driver options to the connection. + * + * @param array $driverOptions + * + * @throws MysqliException When one of of the options is not supported. + * @throws MysqliException When applying doesn't work - e.g. due to incorrect value. + */ + private function setDriverOptions(array $driverOptions = array()) + { + $supportedDriverOptions = array( + \MYSQLI_OPT_CONNECT_TIMEOUT, + \MYSQLI_OPT_LOCAL_INFILE, + \MYSQLI_INIT_COMMAND, + \MYSQLI_READ_DEFAULT_FILE, + \MYSQLI_READ_DEFAULT_GROUP, + ); + + if (defined('MYSQLI_SERVER_PUBLIC_KEY')) { + $supportedDriverOptions[] = \MYSQLI_SERVER_PUBLIC_KEY; + } + + $exceptionMsg = "%s option '%s' with value '%s'"; + + foreach ($driverOptions as $option => $value) { + + if ($option === static::OPTION_FLAGS) { + continue; + } + + if (!in_array($option, $supportedDriverOptions, true)) { + throw new MysqliException( + sprintf($exceptionMsg, 'Unsupported', $option, $value) + ); + } + + if (@mysqli_options($this->_conn, $option, $value)) { + continue; + } + + $msg = sprintf($exceptionMsg, 'Failed to set', $option, $value); + $msg .= sprintf(', error: %s (%d)', mysqli_error($this->_conn), mysqli_errno($this->_conn)); + + throw new MysqliException( + $msg, + $this->_conn->sqlstate, + $this->_conn->errno + ); + } + } + + /** + * Pings the server and re-connects when `mysqli.reconnect = 1` + * + * @return bool + */ + public function ping() + { + return $this->_conn->ping(); + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php index b5583d8532..23728b113a 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php @@ -19,9 +19,14 @@ namespace Doctrine\DBAL\Driver\Mysqli; +use Doctrine\DBAL\Driver\AbstractDriverException; + /** + * Exception thrown in case the mysqli driver errors. + * * @author Kim Hemsø Rasmussen + * @author Steve Müller */ -class MysqliException extends \Exception +class MysqliException extends AbstractDriverException { } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php index 38fed62218..edc02dff55 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php @@ -63,6 +63,11 @@ class MysqliStatement implements \IteratorAggregate, Statement */ protected $_bindedValues; + /** + * @var string + */ + protected $types; + /** * Contains ref values for bindValue(). * @@ -86,19 +91,13 @@ class MysqliStatement implements \IteratorAggregate, Statement $this->_conn = $conn; $this->_stmt = $conn->prepare($prepareString); if (false === $this->_stmt) { - throw new MysqliException($this->_conn->error, $this->_conn->errno); + throw new MysqliException($this->_conn->error, $this->_conn->sqlstate, $this->_conn->errno); } $paramCount = $this->_stmt->param_count; if (0 < $paramCount) { - // Index 0 is types - // Need to init the string else php think we are trying to access it as a array. - $bindedValues = array(0 => str_repeat('s', $paramCount)); - $null = null; - for ($i = 1; $i < $paramCount; $i++) { - $bindedValues[] =& $null; - } - $this->_bindedValues = $bindedValues; + $this->types = str_repeat('s', $paramCount); + $this->_bindedValues = array_fill(1, $paramCount, null); } } @@ -118,7 +117,7 @@ class MysqliStatement implements \IteratorAggregate, Statement } $this->_bindedValues[$column] =& $variable; - $this->_bindedValues[0][$column - 1] = $type; + $this->types[$column - 1] = $type; return true; } @@ -140,7 +139,7 @@ class MysqliStatement implements \IteratorAggregate, Statement $this->_values[$param] = $value; $this->_bindedValues[$param] =& $this->_values[$param]; - $this->_bindedValues[0][$param - 1] = $type; + $this->types[$param - 1] = $type; return true; } @@ -156,14 +155,14 @@ class MysqliStatement implements \IteratorAggregate, Statement throw new MysqliException($this->_stmt->error, $this->_stmt->errno); } } else { - if (!call_user_func_array(array($this->_stmt, 'bind_param'), $this->_bindedValues)) { - throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + if (!call_user_func_array(array($this->_stmt, 'bind_param'), array($this->types) + $this->_bindedValues)) { + throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); } } } if ( ! $this->_stmt->execute()) { - throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); } if (null === $this->_columnNames) { @@ -179,7 +178,7 @@ class MysqliStatement implements \IteratorAggregate, Statement $meta->free(); $this->_columnNames = $columnNames; - $this->_rowBindedValues = array_fill(0, count($columnNames), NULL); + $this->_rowBindedValues = array_fill(0, count($columnNames), null); $refs = array(); foreach ($this->_rowBindedValues as $key => &$value) { @@ -187,7 +186,7 @@ class MysqliStatement implements \IteratorAggregate, Statement } if (!call_user_func_array(array($this->_stmt, 'bind_result'), $refs)) { - throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); } } else { $this->_columnNames = false; @@ -227,9 +226,9 @@ class MysqliStatement implements \IteratorAggregate, Statement if (true === $ret) { $values = array(); foreach ($this->_rowBindedValues as $v) { - // Mysqli converts them to a scalar type it can fit in. - $values[] = null === $v ? null : (string)$v; + $values[] = $v; } + return $values; } @@ -247,7 +246,7 @@ class MysqliStatement implements \IteratorAggregate, Statement } if (false === $values) { - throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); } $fetchMode = $fetchMode ?: $this->_defaultFetchMode; @@ -262,6 +261,7 @@ class MysqliStatement implements \IteratorAggregate, Statement case PDO::FETCH_BOTH: $ret = array_combine($this->_columnNames, $values); $ret += $values; + return $ret; default: @@ -300,7 +300,7 @@ class MysqliStatement implements \IteratorAggregate, Statement return false; } - return $row[$columnIndex]; + return isset($row[$columnIndex]) ? $row[$columnIndex] : null; } /** @@ -337,6 +337,7 @@ class MysqliStatement implements \IteratorAggregate, Statement if (false === $this->_columnNames) { return $this->_stmt->affected_rows; } + return $this->_stmt->num_rows; } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php index 15a6984b34..1aa1b876e2 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php @@ -19,7 +19,8 @@ namespace Doctrine\DBAL\Driver\OCI8; -use Doctrine\DBAL\Platforms; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\AbstractOracleDriver; /** * A Doctrine DBAL driver for the Oracle OCI8 PHP extensions. @@ -27,21 +28,25 @@ use Doctrine\DBAL\Platforms; * @author Roman Borschel * @since 2.0 */ -class Driver implements \Doctrine\DBAL\Driver +class Driver extends AbstractOracleDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { - return new OCI8Connection( - $username, - $password, - $this->_constructDsn($params), - isset($params['charset']) ? $params['charset'] : null, - isset($params['sessionMode']) ? $params['sessionMode'] : OCI_DEFAULT, - isset($params['persistent']) ? $params['persistent'] : false - ); + try { + return new OCI8Connection( + $username, + $password, + $this->_constructDsn($params), + isset($params['charset']) ? $params['charset'] : null, + isset($params['sessionMode']) ? $params['sessionMode'] : OCI_DEFAULT, + isset($params['persistent']) ? $params['persistent'] : false + ); + } catch (OCI8Exception $e) { + throw DBALException::driverException($this, $e); + } } /** @@ -53,50 +58,7 @@ class Driver implements \Doctrine\DBAL\Driver */ protected function _constructDsn(array $params) { - $dsn = ''; - if (isset($params['host']) && $params['host'] != '') { - $dsn .= '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' . - '(HOST=' . $params['host'] . ')'; - - if (isset($params['port'])) { - $dsn .= '(PORT=' . $params['port'] . ')'; - } else { - $dsn .= '(PORT=1521)'; - } - - $database = 'SID=' . $params['dbname']; - $pooled = ''; - - if (isset($params['service']) && $params['service'] == true) { - $database = 'SERVICE_NAME=' . $params['dbname']; - } - - if (isset($params['pooled']) && $params['pooled'] == true) { - $pooled = '(SERVER=POOLED)'; - } - - $dsn .= '))(CONNECT_DATA=(' . $database . ')' . $pooled . '))'; - } else { - $dsn .= $params['dbname']; - } - - return $dsn; - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\OraclePlatform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(\Doctrine\DBAL\Connection $conn) - { - return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn); + return $this->getEasyConnectString($params); } /** @@ -106,14 +68,4 @@ class Driver implements \Doctrine\DBAL\Driver { return 'oci8'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - return $params['user']; - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php index 6776635b5a..a919ddaab8 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php @@ -19,6 +19,8 @@ namespace Doctrine\DBAL\Driver\OCI8; +use Doctrine\DBAL\Driver\Connection; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Platforms\OraclePlatform; /** @@ -26,7 +28,7 @@ use Doctrine\DBAL\Platforms\OraclePlatform; * * @since 2.0 */ -class OCI8Connection implements \Doctrine\DBAL\Driver\Connection +class OCI8Connection implements Connection, ServerInfoAwareConnection { /** * @var resource @@ -65,6 +67,35 @@ class OCI8Connection implements \Doctrine\DBAL\Driver\Connection } } + /** + * {@inheritdoc} + * + * @throws \UnexpectedValueException if the version string returned by the database server + * does not contain a parsable version number. + */ + public function getServerVersion() + { + if ( ! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', oci_server_version($this->dbh), $version)) { + throw new \UnexpectedValueException( + sprintf( + 'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' . + 'Please report this database version string to the Doctrine team.', + oci_server_version($this->dbh) + ) + ); + } + + return $version[1]; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; + } + /** * {@inheritdoc} */ diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php index 339959217e..1cd08b8a40 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php @@ -19,15 +19,17 @@ namespace Doctrine\DBAL\Driver\OCI8; -class OCI8Exception extends \Exception +use Doctrine\DBAL\Driver\AbstractDriverException; + +class OCI8Exception extends AbstractDriverException { /** * @param array $error * * @return \Doctrine\DBAL\Driver\OCI8\OCI8Exception */ - static public function fromErrorInfo($error) + public static function fromErrorInfo($error) { - return new self($error['message'], $error['code']); + return new self($error['message'], null, $error['code']); } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php index fe25ccf375..3270a0b393 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php @@ -121,7 +121,7 @@ class OCI8Statement implements \IteratorAggregate, Statement $i += $len-1; // jump ahead $stmtLen = strlen($statement); // adjust statement length ++$count; - } else if ($statement[$i] == "'" || $statement[$i] == '"') { + } elseif ($statement[$i] == "'" || $statement[$i] == '"') { $inLiteral = ! $inLiteral; // switch state! } } @@ -149,7 +149,7 @@ class OCI8Statement implements \IteratorAggregate, Statement $lob->writeTemporary($variable, OCI_TEMP_BLOB); return oci_bind_by_name($this->_sth, $column, $lob, -1, OCI_B_BLOB); - } else if ($length !== null) { + } elseif ($length !== null) { return oci_bind_by_name($this->_sth, $column, $variable, $length); } @@ -272,7 +272,7 @@ class OCI8Statement implements \IteratorAggregate, Statement } oci_fetch_all($this->_sth, $result, 0, -1, - self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS); + self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS); if ($fetchMode == PDO::FETCH_COLUMN) { $result = $result[0]; @@ -289,7 +289,11 @@ class OCI8Statement implements \IteratorAggregate, Statement { $row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS); - return isset($row[$columnIndex]) ? $row[$columnIndex] : false; + if (false === $row) { + return false; + } + + return isset($row[$columnIndex]) ? $row[$columnIndex] : null; } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php index b65290e9f8..8960de1ae9 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php @@ -27,18 +27,107 @@ use PDO; * * @since 2.0 */ -class PDOConnection extends PDO implements Connection +class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection { /** * @param string $dsn * @param string|null $user * @param string|null $password * @param array|null $options + * + * @throws PDOException in case of an error. */ public function __construct($dsn, $user = null, $password = null, array $options = null) { - parent::__construct($dsn, $user, $password, $options); - $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Doctrine\DBAL\Driver\PDOStatement', array())); - $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + try { + parent::__construct($dsn, $user, $password, $options); + $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Doctrine\DBAL\Driver\PDOStatement', array())); + $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function exec($statement) + { + try { + return parent::exec($statement); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + return PDO::getAttribute(PDO::ATTR_SERVER_VERSION); + } + + /** + * {@inheritdoc} + */ + public function prepare($prepareString, $driverOptions = array()) + { + try { + return parent::prepare($prepareString, $driverOptions); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function query() + { + $args = func_get_args(); + $argsCount = count($args); + + try { + if ($argsCount == 4) { + return parent::query($args[0], $args[1], $args[2], $args[3]); + } + + if ($argsCount == 3) { + return parent::query($args[0], $args[1], $args[2]); + } + + if ($argsCount == 2) { + return parent::query($args[0], $args[1]); + } + + return parent::query($args[0]); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function quote($input, $type = \PDO::PARAM_STR) + { + return parent::quote($input, $type); + } + + /** + * {@inheritdoc} + */ + public function lastInsertId($name = null) + { + return parent::lastInsertId($name); + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php new file mode 100644 index 0000000000..7a1a02a43f --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php @@ -0,0 +1,75 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +/** + * Tiny wrapper for PDOException instances to implement the {@link DriverException} interface. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class PDOException extends \PDOException implements DriverException +{ + /** + * The driver specific error code. + * + * @var integer|string|null + */ + private $errorCode; + + /** + * The SQLSTATE of the driver. + * + * @var string|null + */ + private $sqlState; + + /** + * Constructor. + * + * @param \PDOException $exception The PDO exception to wrap. + */ + public function __construct(\PDOException $exception) + { + parent::__construct($exception->getMessage(), 0, $exception); + + $this->code = $exception->getCode(); + $this->errorInfo = $exception->errorInfo; + $this->errorCode = isset($exception->errorInfo[1]) ? $exception->errorInfo[1] : $exception->getCode(); + $this->sqlState = isset($exception->errorInfo[0]) ? $exception->errorInfo[0] : $exception->getCode(); + } + + /** + * {@inheritdoc} + */ + public function getErrorCode() + { + return $this->errorCode; + } + + /** + * {@inheritdoc} + */ + public function getSQLState() + { + return $this->sqlState; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php index 51e637c5ee..0b929f7200 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php @@ -19,7 +19,8 @@ namespace Doctrine\DBAL\Driver\PDOIbm; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\AbstractDB2Driver; +use Doctrine\DBAL\Driver\PDOConnection; /** * Driver for the PDO IBM extension. @@ -31,14 +32,14 @@ use Doctrine\DBAL\Connection; * @author Jonathan Wage * @author Roman Borschel */ -class Driver implements \Doctrine\DBAL\Driver +class Driver extends AbstractDB2Driver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { - $conn = new \Doctrine\DBAL\Driver\PDOConnection( + $conn = new PDOConnection( $this->_constructPdoDsn($params), $username, $password, @@ -72,22 +73,6 @@ class Driver implements \Doctrine\DBAL\Driver return $dsn; } - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\DB2Platform; - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(Connection $conn) - { - return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn); - } - /** * {@inheritdoc} */ @@ -95,14 +80,4 @@ class Driver implements \Doctrine\DBAL\Driver { return 'pdo_ibm'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - return $params['dbname']; - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php index 1c54e72a6c..7e3632dde9 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php @@ -19,26 +19,33 @@ namespace Doctrine\DBAL\Driver\PDOMySql; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\AbstractMySQLDriver; +use Doctrine\DBAL\Driver\PDOConnection; +use PDOException; /** * PDO MySql driver. * * @since 2.0 */ -class Driver implements \Doctrine\DBAL\Driver +class Driver extends AbstractMySQLDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { - $conn = new \Doctrine\DBAL\Driver\PDOConnection( - $this->_constructPdoDsn($params), - $username, - $password, - $driverOptions - ); + try { + $conn = new PDOConnection( + $this->constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } catch (PDOException $e) { + throw DBALException::driverException($this, $e); + } return $conn; } @@ -50,7 +57,7 @@ class Driver implements \Doctrine\DBAL\Driver * * @return string The DSN. */ - private function _constructPdoDsn(array $params) + protected function constructPdoDsn(array $params) { $dsn = 'mysql:'; if (isset($params['host']) && $params['host'] != '') { @@ -72,22 +79,6 @@ class Driver implements \Doctrine\DBAL\Driver return $dsn; } - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\MySqlPlatform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(\Doctrine\DBAL\Connection $conn) - { - return new \Doctrine\DBAL\Schema\MySqlSchemaManager($conn); - } - /** * {@inheritdoc} */ @@ -95,17 +86,4 @@ class Driver implements \Doctrine\DBAL\Driver { return 'pdo_mysql'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - if (isset($params['dbname'])) { - return $params['dbname']; - } - return $conn->query('SELECT DATABASE()')->fetchColumn(); - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php index c6048bb41a..6e958c7448 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php @@ -19,7 +19,9 @@ namespace Doctrine\DBAL\Driver\PDOOracle; -use Doctrine\DBAL\Platforms; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\AbstractOracleDriver; +use Doctrine\DBAL\Driver\PDOConnection; /** * PDO Oracle driver. @@ -29,19 +31,23 @@ use Doctrine\DBAL\Platforms; * which leads us to the recommendation to use the "oci8" driver to connect * to Oracle instead. */ -class Driver implements \Doctrine\DBAL\Driver +class Driver extends AbstractOracleDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { - return new \Doctrine\DBAL\Driver\PDOConnection( - $this->_constructPdoDsn($params), - $username, - $password, - $driverOptions - ); + try { + return new PDOConnection( + $this->constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } catch (\PDOException $e) { + throw DBALException::driverException($this, $e); + } } /** @@ -51,35 +57,9 @@ class Driver implements \Doctrine\DBAL\Driver * * @return string The DSN. */ - private function _constructPdoDsn(array $params) + private function constructPdoDsn(array $params) { - $dsn = 'oci:dbname='; - - if (isset($params['host']) && $params['host'] != '') { - $dsn .= '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' . - '(HOST=' . $params['host'] . ')'; - - if (isset($params['port'])) { - $dsn .= '(PORT=' . $params['port'] . ')'; - } else { - $dsn .= '(PORT=1521)'; - } - - $database = 'SID=' . $params['dbname']; - $pooled = ''; - - if (isset($params['service']) && $params['service'] == true) { - $database = 'SERVICE_NAME=' . $params['dbname']; - } - - if (isset($params['pooled']) && $params['pooled'] == true) { - $pooled = '(SERVER=POOLED)'; - } - - $dsn .= '))(CONNECT_DATA=(' . $database . ')' . $pooled . '))'; - } else { - $dsn .= $params['dbname']; - } + $dsn = 'oci:dbname=' . $this->getEasyConnectString($params); if (isset($params['charset'])) { $dsn .= ';charset=' . $params['charset']; @@ -88,22 +68,6 @@ class Driver implements \Doctrine\DBAL\Driver return $dsn; } - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\OraclePlatform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(\Doctrine\DBAL\Connection $conn) - { - return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn); - } - /** * {@inheritdoc} */ @@ -111,14 +75,4 @@ class Driver implements \Doctrine\DBAL\Driver { return 'pdo_oracle'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - return $params['user']; - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php index 5da59d528b..7ebfb4ecbd 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php @@ -19,26 +19,52 @@ namespace Doctrine\DBAL\Driver\PDOPgSql; -use Doctrine\DBAL\Platforms; +use Doctrine\DBAL\Driver\AbstractPostgreSQLDriver; +use Doctrine\DBAL\Driver\PDOConnection; +use Doctrine\DBAL\DBALException; +use PDOException; +use PDO; /** * Driver that connects through pdo_pgsql. * * @since 2.0 */ -class Driver implements \Doctrine\DBAL\Driver +class Driver extends AbstractPostgreSQLDriver { /** * {@inheritdoc} */ public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) { - return new \Doctrine\DBAL\Driver\PDOConnection( - $this->_constructPdoDsn($params), - $username, - $password, - $driverOptions - ); + try { + $pdo = new PDOConnection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + + if (PHP_VERSION_ID >= 50600 + && (! isset($driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES]) + || true === $driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES] + ) + ) { + $pdo->setAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES, true); + } + + /* defining client_encoding via SET NAMES to avoid inconsistent DSN support + * - the 'client_encoding' connection param only works with postgres >= 9.1 + * - passing client_encoding via the 'options' param breaks pgbouncer support + */ + if (isset($params['charset'])) { + $pdo->query('SET NAMES \''.$params['charset'].'\''); + } + + return $pdo; + } catch (PDOException $e) { + throw DBALException::driverException($this, $e); + } } /** @@ -51,33 +77,29 @@ class Driver implements \Doctrine\DBAL\Driver private function _constructPdoDsn(array $params) { $dsn = 'pgsql:'; + if (isset($params['host']) && $params['host'] != '') { $dsn .= 'host=' . $params['host'] . ' '; } + if (isset($params['port']) && $params['port'] != '') { $dsn .= 'port=' . $params['port'] . ' '; } + if (isset($params['dbname'])) { $dsn .= 'dbname=' . $params['dbname'] . ' '; + } else { + // Used for temporary connections to allow operations like dropping the database currently connected to. + // Connecting without an explicit database does not work, therefore "template1" database is used + // as it is certainly present in every server setup. + $dsn .= 'dbname=template1' . ' '; } - return $dsn; - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\PostgreSqlPlatform(); - } + if (isset($params['sslmode'])) { + $dsn .= 'sslmode=' . $params['sslmode'] . ' '; + } - /** - * {@inheritdoc} - */ - public function getSchemaManager(\Doctrine\DBAL\Connection $conn) - { - return new \Doctrine\DBAL\Schema\PostgreSqlSchemaManager($conn); + return $dsn; } /** @@ -87,17 +109,4 @@ class Driver implements \Doctrine\DBAL\Driver { return 'pdo_pgsql'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - return (isset($params['dbname'])) - ? $params['dbname'] - : $conn->query('SELECT CURRENT_DATABASE()')->fetchColumn(); - } } - diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php index 56e0346e1a..3c5382fb5f 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php @@ -19,12 +19,17 @@ namespace Doctrine\DBAL\Driver\PDOSqlite; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\AbstractSQLiteDriver; +use Doctrine\DBAL\Driver\PDOConnection; +use PDOException; + /** * The PDO Sqlite driver. * * @since 2.0 */ -class Driver implements \Doctrine\DBAL\Driver +class Driver extends AbstractSQLiteDriver { /** * @var array @@ -46,12 +51,16 @@ class Driver implements \Doctrine\DBAL\Driver unset($driverOptions['userDefinedFunctions']); } - $pdo = new \Doctrine\DBAL\Driver\PDOConnection( - $this->_constructPdoDsn($params), - $username, - $password, - $driverOptions - ); + try { + $pdo = new PDOConnection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } catch (PDOException $ex) { + throw DBALException::driverException($this, $ex); + } foreach ($this->_userDefinedFunctions as $fn => $data) { $pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']); @@ -72,29 +81,13 @@ class Driver implements \Doctrine\DBAL\Driver $dsn = 'sqlite:'; if (isset($params['path'])) { $dsn .= $params['path']; - } else if (isset($params['memory'])) { + } elseif (isset($params['memory'])) { $dsn .= ':memory:'; } return $dsn; } - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\SqlitePlatform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(\Doctrine\DBAL\Connection $conn) - { - return new \Doctrine\DBAL\Schema\SqliteSchemaManager($conn); - } - /** * {@inheritdoc} */ @@ -102,14 +95,4 @@ class Driver implements \Doctrine\DBAL\Driver { return 'pdo_sqlite'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - return isset($params['path']) ? $params['path'] : null; - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php index 93314af0e3..4c04bfb3e7 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php @@ -19,12 +19,14 @@ namespace Doctrine\DBAL\Driver\PDOSqlsrv; +use Doctrine\DBAL\Driver\PDOConnection; + /** * Sqlsrv Connection implementation. * * @since 2.0 */ -class Connection extends \Doctrine\DBAL\Driver\PDOConnection implements \Doctrine\DBAL\Driver\Connection +class Connection extends PDOConnection implements \Doctrine\DBAL\Driver\Connection { /** * @override @@ -33,11 +35,11 @@ class Connection extends \Doctrine\DBAL\Driver\PDOConnection implements \Doctrin { $val = parent::quote($value, $type); - // Fix for a driver version terminating all values with null byte - if (strpos($val, "\0") !== false) { - $val = substr($val, 0, -1); - } + // Fix for a driver version terminating all values with null byte + if (strpos($val, "\0") !== false) { + $val = substr($val, 0, -1); + } - return $val; + return $val; } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php index 4429b44c9d..64b91f194c 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php @@ -19,12 +19,14 @@ namespace Doctrine\DBAL\Driver\PDOSqlsrv; +use Doctrine\DBAL\Driver\AbstractSQLServerDriver; + /** * The PDO-based Sqlsrv driver. * * @since 2.0 */ -class Driver implements \Doctrine\DBAL\Driver +class Driver extends AbstractSQLServerDriver { /** * {@inheritdoc} @@ -58,7 +60,7 @@ class Driver implements \Doctrine\DBAL\Driver $dsn .= ',' . $params['port']; } - if (isset($params['dbname'])) {; + if (isset($params['dbname'])) { $dsn .= ';Database=' . $params['dbname']; } @@ -69,22 +71,6 @@ class Driver implements \Doctrine\DBAL\Driver return $dsn; } - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\SQLServer2008Platform(); - } - /** - * {@inheritdoc} - */ - - public function getSchemaManager(\Doctrine\DBAL\Connection $conn) - { - return new \Doctrine\DBAL\Schema\SQLServerSchemaManager($conn); - } - /** * {@inheritdoc} */ @@ -92,14 +78,4 @@ class Driver implements \Doctrine\DBAL\Driver { return 'pdo_sqlsrv'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - - return $params['dbname']; - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php index 0aee56d5b5..b6a8cb48c5 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php @@ -28,9 +28,9 @@ namespace Doctrine\DBAL\Driver; class PDOStatement extends \PDOStatement implements Statement { /** - * Private constructor. + * Protected constructor. */ - private function __construct() + protected function __construct() { } @@ -43,14 +43,114 @@ class PDOStatement extends \PDOStatement implements Statement // of PDOStatement::setFetchMode(): even if the second and third // parameters are optional, PHP will not let us remove it from this // declaration. - if ($arg2 === null && $arg3 === null) { - return parent::setFetchMode($fetchMode); + try { + if ($arg2 === null && $arg3 === null) { + return parent::setFetchMode($fetchMode); + } + + if ($arg3 === null) { + return parent::setFetchMode($fetchMode, $arg2); + } + + return parent::setFetchMode($fetchMode, $arg2, $arg3); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = \PDO::PARAM_STR) + { + try { + return parent::bindValue($param, $value, $type); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = \PDO::PARAM_STR, $length = null, $driverOptions = null) + { + try { + return parent::bindParam($column, $variable, $type, $length, $driverOptions); + } catch (\PDOException $exception) { + throw new PDOException($exception); } + } - if ($arg3 === null) { - return parent::setFetchMode($fetchMode, $arg2); + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + try { + return parent::execute($params); + } catch (\PDOException $exception) { + throw new PDOException($exception); } + } - return parent::setFetchMode($fetchMode, $arg2, $arg3); + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = null, $cursorOffset = null) + { + try { + if ($fetchMode === null && $cursorOrientation === null && $cursorOffset === null) { + return parent::fetch(); + } + + if ($cursorOrientation === null && $cursorOffset === null) { + return parent::fetch($fetchMode); + } + + if ($cursorOffset === null) { + return parent::fetch($fetchMode, $cursorOrientation); + } + + return parent::fetch($fetchMode, $cursorOrientation, $cursorOffset); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + try { + if ($fetchMode === null && $fetchArgument === null && $ctorArgs === null) { + return parent::fetchAll(); + } + + if ($fetchArgument === null && $ctorArgs === null) { + return parent::fetchAll($fetchMode); + } + + if ($ctorArgs === null) { + return parent::fetchAll($fetchMode, $fetchArgument); + } + + return parent::fetchAll($fetchMode, $fetchArgument, $ctorArgs); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + try { + return parent::fetchColumn($columnIndex); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php new file mode 100644 index 0000000000..8c85a82c83 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php @@ -0,0 +1,39 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +/** + * An interface for connections which support a "native" ping method. + * + * @link www.doctrine-project.org + * @since 2.5 + * @author Till Klampaeckel + * @author Benjamin Eberlei + */ +interface PingableConnection +{ + /** + * Pings the database server to determine if the connection is still + * available. Return true/false based on if that was successful or not. + * + * @return bool + */ + public function ping(); +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ResultStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ResultStatement.php index 551a275031..ad76ddb116 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ResultStatement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ResultStatement.php @@ -45,22 +45,27 @@ interface ResultStatement extends \Traversable /** * Sets the fetch mode to use while iterating this statement. * - * @param integer $fetchMode + * @param integer $fetchMode The fetch mode must be one of the PDO::FETCH_* constants. * @param mixed $arg2 * @param mixed $arg3 * * @return boolean + * + * @see PDO::FETCH_* constants. */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null); /** - * @see Query::HYDRATE_* constants + * Returns the next row of a result set. * * @param integer|null $fetchMode Controls how the next row will be returned to the caller. - * This value must be one of the Query::HYDRATE_* constants, - * defaulting to Query::HYDRATE_BOTH + * The value must be one of the PDO::FETCH_* constants, + * defaulting to PDO::FETCH_BOTH. + * + * @return mixed The return value of this method on success depends on the fetch mode. In all cases, FALSE is + * returned on failure. * - * @return mixed + * @see PDO::FETCH_* constants. */ public function fetch($fetchMode = null); @@ -68,10 +73,12 @@ interface ResultStatement extends \Traversable * Returns an array containing all of the result set rows. * * @param integer|null $fetchMode Controls how the next row will be returned to the caller. - * This value must be one of the Query::HYDRATE_* constants, - * defaulting to Query::HYDRATE_BOTH + * The value must be one of the PDO::FETCH_* constants, + * defaulting to PDO::FETCH_BOTH. * * @return array + * + * @see PDO::FETCH_* constants. */ public function fetchAll($fetchMode = null); diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/Driver.php new file mode 100644 index 0000000000..cb694a32e2 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/Driver.php @@ -0,0 +1,104 @@ +. + */ + +namespace Doctrine\DBAL\Driver\SQLAnywhere; + +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\AbstractSQLAnywhereDriver; + +/** + * A Doctrine DBAL driver for the SAP Sybase SQL Anywhere PHP extension. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class Driver extends AbstractSQLAnywhereDriver +{ + /** + * {@inheritdoc} + * + * @throws \Doctrine\DBAL\DBALException if there was a problem establishing the connection. + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + try { + return new SQLAnywhereConnection( + $this->buildDsn( + isset($params['host']) ? $params['host'] : null, + isset($params['port']) ? $params['port'] : null, + isset($params['server']) ? $params['server'] : null, + isset($params['dbname']) ? $params['dbname'] : null, + $username, + $password, + $driverOptions + ), + isset($params['persistent']) ? $params['persistent'] : false + ); + } catch (SQLAnywhereException $e) { + throw DBALException::driverException($this, $e); + } + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'sqlanywhere'; + } + + /** + * Build the connection string for given connection parameters and driver options. + * + * @param string $host Host address to connect to. + * @param integer $port Port to use for the connection (default to SQL Anywhere standard port 2638). + * @param string $server Database server name on the host to connect to. + * SQL Anywhere allows multiple database server instances on the same host, + * therefore specifying the server instance name to use is mandatory. + * @param string $dbname Name of the database on the server instance to connect to. + * @param string $username User name to use for connection authentication. + * @param string $password Password to use for connection authentication. + * @param array $driverOptions Additional parameters to use for the connection. + * + * @return string + */ + private function buildDsn($host, $port, $server, $dbname, $username = null, $password = null, array $driverOptions = array()) + { + $host = $host ?: 'localhost'; + $port = $port ?: 2638; + + if (! empty($server)) { + $server = ';ServerName=' . $server; + } + + return + 'HOST=' . $host . ':' . $port . + $server . + ';DBN=' . $dbname . + ';UID=' . $username . + ';PWD=' . $password . + ';' . implode( + ';', + array_map(function ($key, $value) { + return $key . '=' . $value; + }, array_keys($driverOptions), $driverOptions) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php new file mode 100644 index 0000000000..79fbb363ce --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php @@ -0,0 +1,223 @@ +. + */ + +namespace Doctrine\DBAL\Driver\SQLAnywhere; + +use Doctrine\DBAL\Driver\Connection; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; + +/** + * SAP Sybase SQL Anywhere implementation of the Connection interface. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection +{ + /** + * @var resource The SQL Anywhere connection resource. + */ + private $connection; + + /** + * Constructor. + * + * Connects to database with given connection string. + * + * @param string $dsn The connection string. + * @param boolean $persistent Whether or not to establish a persistent connection. + * + * @throws SQLAnywhereException + */ + public function __construct($dsn, $persistent = false) + { + $this->connection = $persistent ? @sasql_pconnect($dsn) : @sasql_connect($dsn); + + if ( ! is_resource($this->connection) || get_resource_type($this->connection) !== 'SQLAnywhere connection') { + throw SQLAnywhereException::fromSQLAnywhereError(); + } + + // Disable PHP warnings on error. + if ( ! sasql_set_option($this->connection, 'verbose_errors', false)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + // Enable auto committing by default. + if ( ! sasql_set_option($this->connection, 'auto_commit', 'on')) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + // Enable exact, non-approximated row count retrieval. + if ( ! sasql_set_option($this->connection, 'row_counts', true)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function beginTransaction() + { + if ( ! sasql_set_option($this->connection, 'auto_commit', 'off')) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + return true; + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function commit() + { + if ( ! sasql_commit($this->connection)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + $this->endTransaction(); + + return true; + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return sasql_errorcode($this->connection); + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return sasql_error($this->connection); + } + + /** + * {@inheritdoc} + */ + public function exec($statement) + { + $stmt = $this->prepare($statement); + + $stmt->execute(); + + return $stmt->rowCount(); + } + + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + return $this->query("SELECT PROPERTY('ProductVersion')")->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function lastInsertId($name = null) + { + if (null === $name) { + return sasql_insert_id($this->connection); + } + + return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function prepare($prepareString) + { + return new SQLAnywhereStatement($this->connection, $prepareString); + } + + /** + * {@inheritdoc} + */ + public function query() + { + $args = func_get_args(); + $stmt = $this->prepare($args[0]); + + $stmt->execute(); + + return $stmt; + } + + /** + * {@inheritdoc} + */ + public function quote($input, $type = \PDO::PARAM_STR) + { + if (is_int($input) || is_float($input)) { + return $input; + } + + return "'" . sasql_escape_string($this->connection, $input) . "'"; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return true; + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function rollBack() + { + if ( ! sasql_rollback($this->connection)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + $this->endTransaction(); + + return true; + } + + /** + * Ends transactional mode and enables auto commit again. + * + * @throws SQLAnywhereException + * + * @return boolean Whether or not ending transactional mode succeeded. + */ + private function endTransaction() + { + if ( ! sasql_set_option($this->connection, 'auto_commit', 'on')) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php new file mode 100644 index 0000000000..b68777da11 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php @@ -0,0 +1,94 @@ +. + */ + +namespace Doctrine\DBAL\Driver\SQLAnywhere; + +use Doctrine\DBAL\Driver\AbstractDriverException; + +/** + * SAP Sybase SQL Anywhere driver exception. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class SQLAnywhereException extends AbstractDriverException +{ + /** + * Helper method to turn SQL Anywhere error into exception. + * + * @param resource|null $conn The SQL Anywhere connection resource to retrieve the last error from. + * @param resource|null $stmt The SQL Anywhere statement resource to retrieve the last error from. + * + * @return SQLAnywhereException + * + * @throws \InvalidArgumentException + */ + public static function fromSQLAnywhereError($conn = null, $stmt = null) + { + if (null !== $conn && ! (is_resource($conn) && get_resource_type($conn) === 'SQLAnywhere connection')) { + throw new \InvalidArgumentException('Invalid SQL Anywhere connection resource given: ' . $conn); + } + + if (null !== $stmt && ! (is_resource($stmt) && get_resource_type($stmt) === 'SQLAnywhere statement')) { + throw new \InvalidArgumentException('Invalid SQL Anywhere statement resource given: ' . $stmt); + } + + $state = $conn ? sasql_sqlstate($conn) : sasql_sqlstate(); + $code = null; + $message = null; + + /** + * Try retrieving the last error from statement resource if given + */ + if ($stmt) { + $code = sasql_stmt_errno($stmt); + $message = sasql_stmt_error($stmt); + } + + /** + * Try retrieving the last error from the connection resource + * if either the statement resource is not given or the statement + * resource is given but the last error could not be retrieved from it (fallback). + * Depending on the type of error, it is sometimes necessary to retrieve + * it from the connection resource even though it occurred during + * a prepared statement. + */ + if ($conn && ! $code) { + $code = sasql_errorcode($conn); + $message = sasql_error($conn); + } + + /** + * Fallback mode if either no connection resource is given + * or the last error could not be retrieved from the given + * connection / statement resource. + */ + if ( ! $conn || ! $code) { + $code = sasql_errorcode(); + $message = sasql_error(); + } + + if ($message) { + return new self('SQLSTATE [' . $state . '] [' . $code . '] ' . $message, $state, $code); + } + + return new self('SQL Anywhere error occurred but no error message was retrieved from driver.', $state, $code); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php new file mode 100644 index 0000000000..7a3b120174 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php @@ -0,0 +1,347 @@ +. + */ + +namespace Doctrine\DBAL\Driver\SQLAnywhere; + +use IteratorAggregate; +use PDO; +use Doctrine\DBAL\Driver\Statement; + +/** + * SAP SQL Anywhere implementation of the Statement interface. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class SQLAnywhereStatement implements IteratorAggregate, Statement +{ + /** + * @var resource The connection resource. + */ + private $conn; + + /** + * @var string Name of the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. + */ + private $defaultFetchClass = '\stdClass'; + + /** + * @var string Constructor arguments for the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. + */ + private $defaultFetchClassCtorArgs = array(); + + /** + * @var int Default fetch mode to use. + */ + private $defaultFetchMode = PDO::FETCH_BOTH; + + /** + * @var resource The result set resource to fetch. + */ + private $result; + + /** + * @var resource The prepared SQL statement to execute. + */ + private $stmt; + + /** + * Constructor. + * + * Prepares given statement for given connection. + * + * @param resource $conn The connection resource to use. + * @param string $sql The SQL statement to prepare. + * + * @throws SQLAnywhereException + */ + public function __construct($conn, $sql) + { + if ( ! is_resource($conn) || get_resource_type($conn) !== 'SQLAnywhere connection') { + throw new SQLAnywhereException('Invalid SQL Anywhere connection resource: ' . $conn); + } + + $this->conn = $conn; + $this->stmt = sasql_prepare($conn, $sql); + + if ( ! is_resource($this->stmt) || get_resource_type($this->stmt) !== 'SQLAnywhere statement') { + throw SQLAnywhereException::fromSQLAnywhereError($conn); + } + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function bindParam($column, &$variable, $type = null, $length = null) + { + switch ($type) { + case PDO::PARAM_INT: + case PDO::PARAM_BOOL: + $type = 'i'; + break; + case PDO::PARAM_LOB: + $type = 'b'; + break; + case PDO::PARAM_NULL: + case PDO::PARAM_STR: + $type = 's'; + break; + default: + throw new SQLAnywhereException('Unknown type: ' . $type); + } + + if ( ! sasql_stmt_bind_param_ex($this->stmt, $column - 1, $variable, $type, $variable === null)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = null) + { + return $this->bindParam($param, $value, $type); + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function closeCursor() + { + if ( ! sasql_stmt_free_result($this->stmt)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return sasql_stmt_field_count($this->stmt); + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return sasql_stmt_errno($this->stmt); + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return sasql_stmt_error($this->stmt); + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function execute($params = null) + { + if (is_array($params)) { + $hasZeroIndex = array_key_exists(0, $params); + + foreach ($params as $key => $val) { + $key = ($hasZeroIndex && is_numeric($key)) ? $key + 1 : $key; + + $this->bindValue($key, $val); + } + } + + if ( ! sasql_stmt_execute($this->stmt)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); + } + + $this->result = sasql_stmt_result_metadata($this->stmt); + + return true; + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function fetch($fetchMode = null) + { + if ( ! is_resource($this->result) || get_resource_type($this->result) !== 'SQLAnywhere result') { + return false; + } + + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + switch ($fetchMode) { + case PDO::FETCH_ASSOC: + return sasql_fetch_assoc($this->result); + case PDO::FETCH_BOTH: + return sasql_fetch_array($this->result, SASQL_BOTH); + case PDO::FETCH_CLASS: + $className = $this->defaultFetchClass; + $ctorArgs = $this->defaultFetchClassCtorArgs; + + if (func_num_args() >= 2) { + $args = func_get_args(); + $className = $args[1]; + $ctorArgs = isset($args[2]) ? $args[2] : array(); + } + + $result = sasql_fetch_object($this->result); + + if ($result instanceof \stdClass) { + $result = $this->castObject($result, $className, $ctorArgs); + } + + return $result; + case PDO::FETCH_NUM: + return sasql_fetch_row($this->result); + case PDO::FETCH_OBJ: + return sasql_fetch_object($this->result); + default: + throw new SQLAnywhereException('Fetch mode is not supported: ' . $fetchMode); + } + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null) + { + $rows = array(); + + switch ($fetchMode) { + case PDO::FETCH_CLASS: + while ($row = call_user_func_array(array($this, 'fetch'), func_get_args())) { + $rows[] = $row; + } + break; + case PDO::FETCH_COLUMN: + while ($row = $this->fetchColumn()) { + $rows[] = $row; + } + break; + default: + while ($row = $this->fetch($fetchMode)) { + $rows[] = $row; + } + } + + return $rows; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(PDO::FETCH_NUM); + + if (false === $row) { + return false; + } + + return isset($row[$columnIndex]) ? $row[$columnIndex] : null; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new \ArrayIterator($this->fetchAll()); + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + return sasql_stmt_affected_rows($this->stmt); + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->defaultFetchMode = $fetchMode; + $this->defaultFetchClass = $arg2 ? $arg2 : $this->defaultFetchClass; + $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; + } + + /** + * Casts a stdClass object to the given class name mapping its' properties. + * + * @param \stdClass $sourceObject Object to cast from. + * @param string|object $destinationClass Name of the class or class instance to cast to. + * @param array $ctorArgs Arguments to use for constructing the destination class instance. + * + * @return object + * + * @throws SQLAnywhereException + */ + private function castObject(\stdClass $sourceObject, $destinationClass, array $ctorArgs = array()) + { + if ( ! is_string($destinationClass)) { + if ( ! is_object($destinationClass)) { + throw new SQLAnywhereException(sprintf( + 'Destination class has to be of type string or object, %s given.', gettype($destinationClass) + )); + } + } else { + $destinationClass = new \ReflectionClass($destinationClass); + $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); + } + + $sourceReflection = new \ReflectionObject($sourceObject); + $destinationClassReflection = new \ReflectionObject($destinationClass); + + foreach ($sourceReflection->getProperties() as $sourceProperty) { + $sourceProperty->setAccessible(true); + + $name = $sourceProperty->getName(); + $value = $sourceProperty->getValue($sourceObject); + + if ($destinationClassReflection->hasProperty($name)) { + $destinationProperty = $destinationClassReflection->getProperty($name); + + $destinationProperty->setAccessible(true); + $destinationProperty->setValue($destinationClass, $value); + } else { + $destinationClass->$name = $value; + } + } + + return $destinationClass; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php index cb6297c23e..f9423973e2 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php @@ -19,10 +19,12 @@ namespace Doctrine\DBAL\Driver\SQLSrv; +use Doctrine\DBAL\Driver\AbstractSQLServerDriver; + /** * Driver for ext/sqlsrv. */ -class Driver implements \Doctrine\DBAL\Driver +class Driver extends AbstractSQLServerDriver { /** * {@inheritdoc} @@ -32,15 +34,20 @@ class Driver implements \Doctrine\DBAL\Driver if (!isset($params['host'])) { throw new SQLSrvException("Missing 'host' in configuration for sqlsrv driver."); } - if (!isset($params['dbname'])) { - throw new SQLSrvException("Missing 'dbname' in configuration for sqlsrv driver."); - } $serverName = $params['host']; if (isset($params['port'])) { $serverName .= ', ' . $params['port']; } - $driverOptions['Database'] = $params['dbname']; + + if (isset($params['dbname'])) { + $driverOptions['Database'] = $params['dbname']; + } + + if (isset($params['charset'])) { + $driverOptions['CharacterSet'] = $params['charset']; + } + $driverOptions['UID'] = $username; $driverOptions['PWD'] = $password; @@ -51,22 +58,6 @@ class Driver implements \Doctrine\DBAL\Driver return new SQLSrvConnection($serverName, $driverOptions); } - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new \Doctrine\DBAL\Platforms\SQLServer2008Platform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(\Doctrine\DBAL\Connection $conn) - { - return new \Doctrine\DBAL\Schema\SQLServerSchemaManager($conn); - } - /** * {@inheritdoc} */ @@ -74,13 +65,4 @@ class Driver implements \Doctrine\DBAL\Driver { return 'sqlsrv'; } - - /** - * {@inheritdoc} - */ - public function getDatabase(\Doctrine\DBAL\Connection $conn) - { - $params = $conn->getParams(); - return $params['dbname']; - } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php index 7942f1419c..514ae54fc5 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php @@ -19,13 +19,16 @@ namespace Doctrine\DBAL\Driver\SQLSrv; +use Doctrine\DBAL\Driver\Connection; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; + /** * SQL Server implementation for the Connection interface. * * @since 2.3 * @author Benjamin Eberlei */ -class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection +class SQLSrvConnection implements Connection, ServerInfoAwareConnection { /** * @var resource @@ -56,6 +59,24 @@ class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection $this->lastInsertId = new LastInsertId(); } + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + $serverInfo = sqlsrv_server_info($this->conn); + + return $serverInfo['SQLServerVersion']; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; + } + /** * {@inheritDoc} */ @@ -85,7 +106,7 @@ class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection { if (is_int($value)) { return $value; - } else if (is_float($value)) { + } elseif (is_float($value)) { return sprintf('%F', $value); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php index 3631e65059..50705adabb 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php @@ -19,7 +19,9 @@ namespace Doctrine\DBAL\Driver\SQLSrv; -class SQLSrvException extends \Doctrine\DBAL\DBALException +use Doctrine\DBAL\DBALException; + +class SQLSrvException extends DBALException { /** * Helper method to turn sql server errors into exception. diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php index fc11453c97..ead250c185 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php @@ -70,6 +70,20 @@ class SQLSrvStatement implements IteratorAggregate, Statement PDO::FETCH_NUM => SQLSRV_FETCH_NUMERIC, ); + /** + * The name of the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. + * + * @var string + */ + private $defaultFetchClass = '\stdClass'; + + /** + * The constructor arguments for the default class to instantiate when fetch mode is \PDO::FETCH_CLASS. + * + * @var string + */ + private $defaultFetchClassCtorArgs = array(); + /** * The fetch style. * @@ -92,11 +106,11 @@ class SQLSrvStatement implements IteratorAggregate, Statement const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;'; /** - * @param resource $conn - * @param string $sql - * @param integer|null $lastInsertId + * @param resource $conn + * @param string $sql + * @param \Doctrine\DBAL\Driver\SQLSrv\LastInsertId|null $lastInsertId */ - public function __construct($conn, $sql, $lastInsertId = null) + public function __construct($conn, $sql, LastInsertId $lastInsertId = null) { $this->conn = $conn; $this->sql = $sql; @@ -112,7 +126,7 @@ class SQLSrvStatement implements IteratorAggregate, Statement */ public function bindValue($param, $value, $type = null) { - return $this->bindParam($param, $value, $type,null); + return $this->bindParam($param, $value, $type, null); } /** @@ -191,7 +205,7 @@ class SQLSrvStatement implements IteratorAggregate, Statement if ($this->lastInsertId) { sqlsrv_next_result($this->stmt); sqlsrv_fetch($this->stmt); - $this->lastInsertId->setId( sqlsrv_get_field($this->stmt, 0) ); + $this->lastInsertId->setId(sqlsrv_get_field($this->stmt, 0)); } } @@ -200,7 +214,9 @@ class SQLSrvStatement implements IteratorAggregate, Statement */ public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) { - $this->defaultFetchMode = $fetchMode; + $this->defaultFetchMode = $fetchMode; + $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; + $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; return true; } @@ -220,18 +236,23 @@ class SQLSrvStatement implements IteratorAggregate, Statement */ public function fetch($fetchMode = null) { + $args = func_get_args(); $fetchMode = $fetchMode ?: $this->defaultFetchMode; + if (isset(self::$fetchMap[$fetchMode])) { - return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]); - } else if ($fetchMode == PDO::FETCH_OBJ || $fetchMode == PDO::FETCH_CLASS) { - $className = null; - $ctorArgs = null; - if (func_num_args() >= 2) { - $args = func_get_args(); + return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]) ?: false; + } + + if ($fetchMode == PDO::FETCH_OBJ || $fetchMode == PDO::FETCH_CLASS) { + $className = $this->defaultFetchClass; + $ctorArgs = $this->defaultFetchClassCtorArgs; + + if (count($args) >= 2) { $className = $args[1]; - $ctorArgs = (isset($args[2])) ? $args[2] : array(); + $ctorArgs = (isset($args[2])) ? $args[2] : array(); } - return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs); + + return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs) ?: false; } throw new SQLSrvException("Fetch mode is not supported!"); @@ -242,17 +263,23 @@ class SQLSrvStatement implements IteratorAggregate, Statement */ public function fetchAll($fetchMode = null) { - $className = null; - $ctorArgs = null; - if (func_num_args() >= 2) { - $args = func_get_args(); - $className = $args[1]; - $ctorArgs = (isset($args[2])) ? $args[2] : array(); - } - $rows = array(); - while ($row = $this->fetch($fetchMode, $className, $ctorArgs)) { - $rows[] = $row; + + switch ($fetchMode) { + case PDO::FETCH_CLASS: + while ($row = call_user_func_array(array($this, 'fetch'), func_get_args())) { + $rows[] = $row; + } + break; + case PDO::FETCH_COLUMN: + while ($row = $this->fetchColumn()) { + $rows[] = $row; + } + break; + default: + while ($row = $this->fetch($fetchMode)) { + $rows[] = $row; + } } return $rows; @@ -265,7 +292,11 @@ class SQLSrvStatement implements IteratorAggregate, Statement { $row = $this->fetch(PDO::FETCH_NUM); - return $row[$columnIndex]; + if (false === $row) { + return false; + } + + return isset($row[$columnIndex]) ? $row[$columnIndex] : null; } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php new file mode 100644 index 0000000000..f15ffefcba --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php @@ -0,0 +1,44 @@ +. + */ + +namespace Doctrine\DBAL\Driver; + +/** + * Contract for a connection that is able to provide information about the server it is connected to. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +interface ServerInfoAwareConnection +{ + /** + * Returns the version number of the database server connected to. + * + * @return string + */ + public function getServerVersion(); + + /** + * Checks whether a query is required to retrieve the database server version. + * + * @return boolean True if a query is required to retrieve the database server version, false otherwise. + */ + public function requiresQueryForServerVersion(); +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Statement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Statement.php index f545cd1e76..aedf47b8a9 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Statement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Statement.php @@ -33,9 +33,12 @@ namespace Doctrine\DBAL\Driver; interface Statement extends ResultStatement { /** - * Binds a value to a corresponding named or positional + * Binds a value to a corresponding named (not supported by mysqli driver, see comment below) or positional * placeholder in the SQL statement that was used to prepare the statement. * + * As mentioned above, the named parameters are not natively supported by the mysqli driver, use executeQuery(), + * fetchAll(), fetchArray(), fetchColumn(), fetchAssoc() methods to have the named parameter emulated by doctrine. + * * @param mixed $param Parameter identifier. For a prepared statement using named placeholders, * this will be a parameter name of the form :name. For a prepared statement * using question mark placeholders, this will be the 1-indexed position of the parameter. @@ -46,12 +49,16 @@ interface Statement extends ResultStatement */ function bindValue($param, $value, $type = null); + /** - * Binds a PHP variable to a corresponding named or question mark placeholder in the - * SQL statement that was use to prepare the statement. Unlike PDOStatement->bindValue(), + * Binds a PHP variable to a corresponding named (not supported by mysqli driver, see comment below) or question + * mark placeholder in the SQL statement that was use to prepare the statement. Unlike PDOStatement->bindValue(), * the variable is bound as a reference and will only be evaluated at the time * that PDOStatement->execute() is called. * + * As mentioned above, the named parameters are not natively supported by the mysqli driver, use executeQuery(), + * fetchAll(), fetchArray(), fetchColumn(), fetchAssoc() methods to have the named parameter emulated by doctrine. + * * Most parameters are input parameters, that is, parameters that are * used in a read-only fashion to build up the query. Some drivers support the invocation * of stored procedures that return data as output parameters, and some also as input/output diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php index 295c4c6945..75004a4071 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php @@ -38,18 +38,33 @@ final class DriverManager * @var array */ private static $_driverMap = array( - 'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver', - 'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver', - 'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver', - 'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver', - 'oci8' => 'Doctrine\DBAL\Driver\OCI8\Driver', - 'ibm_db2' => 'Doctrine\DBAL\Driver\IBMDB2\DB2Driver', - 'pdo_ibm' => 'Doctrine\DBAL\Driver\PDOIbm\Driver', - 'pdo_sqlsrv' => 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver', - 'mysqli' => 'Doctrine\DBAL\Driver\Mysqli\Driver', - 'drizzle_pdo_mysql' => 'Doctrine\DBAL\Driver\DrizzlePDOMySql\Driver', - 'sqlsrv' => 'Doctrine\DBAL\Driver\SQLSrv\Driver', - ); + 'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver', + 'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver', + 'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver', + 'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver', + 'oci8' => 'Doctrine\DBAL\Driver\OCI8\Driver', + 'ibm_db2' => 'Doctrine\DBAL\Driver\IBMDB2\DB2Driver', + 'pdo_sqlsrv' => 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver', + 'mysqli' => 'Doctrine\DBAL\Driver\Mysqli\Driver', + 'drizzle_pdo_mysql' => 'Doctrine\DBAL\Driver\DrizzlePDOMySql\Driver', + 'sqlanywhere' => 'Doctrine\DBAL\Driver\SQLAnywhere\Driver', + 'sqlsrv' => 'Doctrine\DBAL\Driver\SQLSrv\Driver', + ); + + /** + * List of URL schemes from a database URL and their mappings to driver. + */ + private static $driverSchemeAliases = array( + 'db2' => 'ibm_db2', + 'mssql' => 'pdo_sqlsrv', + 'mysql' => 'pdo_mysql', + 'mysql2' => 'pdo_mysql', // Amazon RDS, for some weird reason + 'postgres' => 'pdo_pgsql', + 'postgresql' => 'pdo_pgsql', + 'pgsql' => 'pdo_pgsql', + 'sqlite' => 'pdo_sqlite', + 'sqlite3' => 'pdo_sqlite', + ); /** * Private constructor. This class cannot be instantiated. @@ -72,9 +87,9 @@ final class DriverManager * pdo_pgsql * pdo_oci (unstable) * pdo_sqlsrv - * pdo_ibm (unstable) * pdo_sqlsrv * mysqli + * sqlanywhere * sqlsrv * ibm_db2 (unstable) * drizzle_pdo_mysql @@ -126,10 +141,12 @@ final class DriverManager $eventManager = new EventManager(); } + $params = self::parseDatabaseUrl($params); + // check for existing pdo object if (isset($params['pdo']) && ! $params['pdo'] instanceof \PDO) { throw DBALException::invalidPdoInstance(); - } else if (isset($params['pdo'])) { + } elseif (isset($params['pdo'])) { $params['pdo']->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $params['driver'] = 'pdo_' . $params['pdo']->getAttribute(\PDO::ATTR_DRIVER_NAME); } else { @@ -155,6 +172,16 @@ final class DriverManager return new $wrapperClass($params, $driver, $config, $eventManager); } + /** + * Returns the list of supported drivers. + * + * @return array + */ + public static function getAvailableDrivers() + { + return array_keys(self::$_driverMap); + } + /** * Checks the list of parameters. * @@ -176,7 +203,7 @@ final class DriverManager // check validity of parameters // driver - if ( isset($params['driver']) && ! isset(self::$_driverMap[$params['driver']])) { + if (isset($params['driver']) && ! isset(self::$_driverMap[$params['driver']])) { throw DBALException::unknownDriver($params['driver'], array_keys(self::$_driverMap)); } @@ -184,4 +211,66 @@ final class DriverManager throw DBALException::invalidDriverClass($params['driverClass']); } } + + /** + * Extracts parts from a database URL, if present, and returns an + * updated list of parameters. + * + * @param array $params The list of parameters. + * + * @param array A modified list of parameters with info from a database + * URL extracted into indidivual parameter parts. + * + */ + private static function parseDatabaseUrl(array $params) + { + if (!isset($params['url'])) { + return $params; + } + + // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid + $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $params['url']); + + $url = parse_url($url); + + if ($url === false) { + throw new DBALException('Malformed parameter "url".'); + } + + if (isset($url['scheme'])) { + $params['driver'] = str_replace('-', '_', $url['scheme']); // URL schemes must not contain underscores, but dashes are ok + if (isset(self::$driverSchemeAliases[$params['driver']])) { + $params['driver'] = self::$driverSchemeAliases[$params['driver']]; // use alias like "postgres", else we just let checkParams decide later if the driver exists (for literal "pdo-pgsql" etc) + } + } + + if (isset($url['host'])) { + $params['host'] = $url['host']; + } + if (isset($url['port'])) { + $params['port'] = $url['port']; + } + if (isset($url['user'])) { + $params['user'] = $url['user']; + } + if (isset($url['pass'])) { + $params['password'] = $url['pass']; + } + + if (isset($url['path'])) { + if (!isset($url['scheme']) || (strpos($url['scheme'], 'sqlite') !== false && $url['path'] == ':memory:')) { + $params['dbname'] = $url['path']; // if the URL was just "sqlite::memory:", which parses to scheme and path only + } else { + $params['dbname'] = substr($url['path'], 1); // strip the leading slash from the URL + } + } + + if (isset($url['query'])) { + $query = array(); + parse_str($url['query'], $query); // simply ingest query as extra params, e.g. charset or sslmode + $params = array_merge($params, $query); // parse_str wipes existing array elements + } + + return $params; + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php index d21488e86c..6ffb6442c0 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php @@ -55,7 +55,7 @@ class SchemaDropTableEventArgs extends SchemaEventArgs public function __construct($table, AbstractPlatform $platform) { if ( ! $table instanceof Table && !is_string($table)) { - throw new \InvalidArgumentException('SchemaCreateTableEventArgs expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + throw new \InvalidArgumentException('SchemaDropTableEventArgs expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } $this->_table = $table; diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConnectionException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConnectionException.php new file mode 100644 index 0000000000..8d976dcb32 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConnectionException.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Base class for all connection related errors detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class ConnectionException extends DriverException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConstraintViolationException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConstraintViolationException.php new file mode 100644 index 0000000000..8dd1cb6945 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConstraintViolationException.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Base class for all constraint violation related errors detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class ConstraintViolationException extends ServerException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectExistsException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectExistsException.php new file mode 100644 index 0000000000..279aae9a5a --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectExistsException.php @@ -0,0 +1,35 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Base class for all already existing database object related errors detected in the driver. + * + * A database object is considered any asset that can be created in a database + * such as schemas, tables, views, sequences, triggers, constraints, indexes, + * functions, stored procedures etc. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class DatabaseObjectExistsException extends ServerException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectNotFoundException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectNotFoundException.php new file mode 100644 index 0000000000..fbca22d994 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectNotFoundException.php @@ -0,0 +1,35 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Base class for all unknown database object related errors detected in the driver. + * + * A database object is considered any asset that can be created in a database + * such as schemas, tables, views, sequences, triggers, constraints, indexes, + * functions, stored procedures etc. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class DatabaseObjectNotFoundException extends ServerException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DriverException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DriverException.php new file mode 100644 index 0000000000..17c9f3a845 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DriverException.php @@ -0,0 +1,82 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +use Doctrine\DBAL\DBALException; + +/** + * Base class for all errors detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class DriverException extends DBALException +{ + /** + * The previous DBAL driver exception. + * + * @var \Doctrine\DBAL\Driver\DriverException + */ + private $driverException; + + /** + * Constructor. + * + * @param string $message The exception message. + * @param \Doctrine\DBAL\Driver\DriverException $driverException The DBAL driver exception to chain. + */ + public function __construct($message, \Doctrine\DBAL\Driver\DriverException $driverException) + { + $exception = null; + + if ($driverException instanceof \Exception) { + $exception = $driverException; + } + + parent::__construct($message, 0, $exception); + + $this->driverException = $driverException; + } + + /** + * Returns the driver specific error code if given. + * + * Returns null if no error code was given by the driver. + * + * @return integer|string|null + */ + public function getErrorCode() + { + return $this->driverException->getErrorCode(); + } + + /** + * Returns the SQLSTATE the driver was in at the time the error occurred, if given. + * + * Returns null if no SQLSTATE was given by the driver. + * + * @return string|null + */ + public function getSQLState() + { + return $this->driverException->getSQLState(); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php new file mode 100644 index 0000000000..d244855a16 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Exception for a foreign key constraint violation detected in the driver. + * + * @author Benjamin Eberlei + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class ForeignKeyConstraintViolationException extends ConstraintViolationException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidArgumentException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000..5b811227bd --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidArgumentException.php @@ -0,0 +1,40 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +use Doctrine\DBAL\DBALException; + +/** + * Exception to be thrown when invalid arguments are passed to any DBAL API + * + * @author Marco Pivetta + * @link www.doctrine-project.org + * @since 2.5 + */ +class InvalidArgumentException extends DBALException +{ + /** + * @return self + */ + public static function fromEmptyCriteria() + { + return new self('Empty criteria was used, expected non-empty criteria'); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidFieldNameException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidFieldNameException.php new file mode 100644 index 0000000000..e0b1013fe4 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidFieldNameException.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Exception for an invalid specified field name in a statement detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class InvalidFieldNameException extends ServerException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NonUniqueFieldNameException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NonUniqueFieldNameException.php new file mode 100644 index 0000000000..7b214e3b94 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NonUniqueFieldNameException.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Exception for a non-unique/ambiguous specified field name in a statement detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class NonUniqueFieldNameException extends ServerException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NotNullConstraintViolationException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NotNullConstraintViolationException.php new file mode 100644 index 0000000000..a1f45b92a4 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NotNullConstraintViolationException.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Exception for a NOT NULL constraint violation detected in the driver. + * + * @author Benjamin Eberlei + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class NotNullConstraintViolationException extends ConstraintViolationException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ReadOnlyException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ReadOnlyException.php new file mode 100644 index 0000000000..0345e88fce --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ReadOnlyException.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Exception for a write operation attempt on a read-only database element detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class ReadOnlyException extends ServerException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ServerException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ServerException.php new file mode 100644 index 0000000000..36460ee0d6 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ServerException.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Base class for all server related errors detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class ServerException extends DriverException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/SyntaxErrorException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/SyntaxErrorException.php new file mode 100644 index 0000000000..97b8fd25f3 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/SyntaxErrorException.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Exception for a syntax error in a statement detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class SyntaxErrorException extends ServerException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableExistsException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableExistsException.php new file mode 100644 index 0000000000..c90bfb476c --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableExistsException.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Exception for an already existing table referenced in a statement detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class TableExistsException extends DatabaseObjectExistsException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableNotFoundException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableNotFoundException.php new file mode 100644 index 0000000000..90793b909d --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableNotFoundException.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Exception for an unknown table referenced in a statement detected in the driver. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class TableNotFoundException extends DatabaseObjectNotFoundException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/UniqueConstraintViolationException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/UniqueConstraintViolationException.php new file mode 100644 index 0000000000..cd117738dd --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/UniqueConstraintViolationException.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\DBAL\Exception; + +/** + * Exception for a unique constraint violation detected in the driver. + * + * @author Benjamin Eberlei + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class UniqueConstraintViolationException extends ConstraintViolationException +{ +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGenerator.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGenerator.php index 090227a8ba..62d6fcb8ef 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGenerator.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGenerator.php @@ -155,7 +155,7 @@ class TableGenerator $this->conn->commit(); - } catch(\Exception $e) { + } catch (\Exception $e) { $this->conn->rollback(); throw new \Doctrine\DBAL\DBALException("Error occurred while generating ID with TableGenerator, aborted generation: " . $e->getMessage(), 0, $e); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php index b1fedf1da1..8ed04788fd 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php @@ -36,11 +36,11 @@ class EchoSQLLogger implements SQLLogger */ public function startQuery($sql, array $params = null, array $types = null) { - echo $sql . PHP_EOL; + echo $sql . PHP_EOL; if ($params) { var_dump($params); - } + } if ($types) { var_dump($types); diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index c2d91d82bf..f0ace993ea 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -21,6 +21,7 @@ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Types; use Doctrine\DBAL\Schema\Constraint; use Doctrine\DBAL\Schema\Sequence; @@ -68,6 +69,46 @@ abstract class AbstractPlatform */ const CREATE_FOREIGNKEYS = 2; + /** + * @var string + */ + const DATE_INTERVAL_UNIT_SECOND = 'SECOND'; + + /** + * @var string + */ + const DATE_INTERVAL_UNIT_MINUTE = 'MINUTE'; + + /** + * @var string + */ + const DATE_INTERVAL_UNIT_HOUR = 'HOUR'; + + /** + * @var string + */ + const DATE_INTERVAL_UNIT_DAY = 'DAY'; + + /** + * @var string + */ + const DATE_INTERVAL_UNIT_WEEK = 'WEEK'; + + /** + * @var string + */ + const DATE_INTERVAL_UNIT_MONTH = 'MONTH'; + + /** + * @var string + */ + const DATE_INTERVAL_UNIT_QUARTER = 'QUARTER'; + + /** + * @var string + */ + const DATE_INTERVAL_UNIT_YEAR = 'YEAR'; + /** * @var integer */ @@ -123,7 +164,7 @@ abstract class AbstractPlatform /** * Sets the EventManager used by the Platform. * - * @param \Doctrine\Common\EventManager + * @param \Doctrine\Common\EventManager $eventManager */ public function setEventManager(EventManager $eventManager) { @@ -231,10 +272,32 @@ abstract class AbstractPlatform return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed); } + /** + * Returns the SQL snippet used to declare a BINARY/VARBINARY column type. + * + * @param array $field The column definition. + * + * @return string + */ + public function getBinaryTypeDeclarationSQL(array $field) + { + if ( ! isset($field['length'])) { + $field['length'] = $this->getBinaryDefaultLength(); + } + + $fixed = isset($field['fixed']) ? $field['fixed'] : false; + + if ($field['length'] > $this->getBinaryMaxLength()) { + return $this->getBlobTypeDeclarationSQL($field); + } + + return $this->getBinaryTypeDeclarationSQLSnippet($field['length'], $fixed); + } + /** * Returns the SQL snippet to declare a GUID/UUID field. * - * By default this maps directly to a VARCHAR and only maps to more + * By default this maps directly to a CHAR(36) and only maps to more * special datatypes when the underlying databases support this datatype. * * @param array $field @@ -243,9 +306,27 @@ abstract class AbstractPlatform */ public function getGuidTypeDeclarationSQL(array $field) { + $field['length'] = 36; + $field['fixed'] = true; + return $this->getVarcharTypeDeclarationSQL($field); } + /** + * Returns the SQL snippet to declare a JSON field. + * + * By default this maps directly to a CLOB and only maps to more + * special datatypes when the underlying databases support this datatype. + * + * @param array $field + * + * @return string + */ + public function getJsonTypeDeclarationSQL(array $field) + { + return $this->getClobTypeDeclarationSQL($field); + } + /** * @param integer $length * @param boolean $fixed @@ -259,6 +340,21 @@ abstract class AbstractPlatform throw DBALException::notSupported('VARCHARs not supported by Platform.'); } + /** + * Returns the SQL snippet used to declare a BINARY/VARBINARY column type. + * + * @param integer $length The length of the column. + * @param boolean $fixed Whether the column length is fixed. + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + throw DBALException::notSupported('BINARY/VARBINARY column types are not supported by this platform.'); + } + /** * Returns the SQL snippet used to declare a CLOB column type. * @@ -478,6 +574,26 @@ abstract class AbstractPlatform return 255; } + /** + * Gets the maximum length of a binary field. + * + * @return integer + */ + public function getBinaryMaxLength() + { + return 4000; + } + + /** + * Gets the default length of a binary field. + * + * @return integer + */ + public function getBinaryDefaultLength() + { + return 255; + } + /** * Gets all SQL wildcard characters of the platform. * @@ -651,24 +767,31 @@ abstract class AbstractPlatform */ public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) { - $posStr = ''; - $trimChar = ($char != false) ? $char . ' FROM ' : ''; + $expression = ''; switch ($pos) { case self::TRIM_LEADING: - $posStr = 'LEADING '.$trimChar; + $expression = 'LEADING '; break; case self::TRIM_TRAILING: - $posStr = 'TRAILING '.$trimChar; + $expression = 'TRAILING '; break; case self::TRIM_BOTH: - $posStr = 'BOTH '.$trimChar; + $expression = 'BOTH '; break; } - return 'TRIM(' . $posStr . $str . ')'; + if (false !== $char) { + $expression .= $char . ' '; + } + + if ($pos || false !== $char) { + $expression .= 'FROM '; + } + + return 'TRIM(' . $expression . $str . ')'; } /** @@ -778,7 +901,7 @@ abstract class AbstractPlatform */ public function getConcatExpression() { - return join(' || ' , func_get_args()); + return join(' || ', func_get_args()); } /** @@ -801,37 +924,6 @@ abstract class AbstractPlatform return 'NOT(' . $expression . ')'; } - /** - * Returns the SQL to check if a value is one in a set of given values. - * - * Accepts an arbitrary number of parameters. The first parameter - * must always specify the value that should be matched against. Successive - * must contain a logical expression or an array with logical expressions. - * These expressions will be matched against the first parameter. - * - * @param string $column The value that should be matched against. - * @param string|string[] $values The values that will be matched against $column. - * - * @return string The logical expression. - * - * @throws \InvalidArgumentException - */ - public function getInExpression($column, $values) - { - if ( ! is_array($values)) { - $values = array($values); - } - - // TODO: fix this code: the method does not exist - $values = $this->getIdentifiers($values); - - if (count($values) == 0) { - throw new \InvalidArgumentException('Values must not be empty.'); - } - - return $column . ' IN (' . implode(', ', $values) . ')'; - } - /** * Returns the SQL that checks if an expression is null. * @@ -939,6 +1031,96 @@ abstract class AbstractPlatform throw DBALException::notSupported(__METHOD__); } + /** + * Returns the SQL to add the number of given seconds to a date. + * + * @param string $date + * @param integer $seconds + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateAddSecondsExpression($date, $seconds) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $seconds, self::DATE_INTERVAL_UNIT_SECOND); + } + + /** + * Returns the SQL to subtract the number of given seconds from a date. + * + * @param string $date + * @param integer $seconds + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateSubSecondsExpression($date, $seconds) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $seconds, self::DATE_INTERVAL_UNIT_SECOND); + } + + /** + * Returns the SQL to add the number of given minutes to a date. + * + * @param string $date + * @param integer $minutes + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateAddMinutesExpression($date, $minutes) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $minutes, self::DATE_INTERVAL_UNIT_MINUTE); + } + + /** + * Returns the SQL to subtract the number of given minutes from a date. + * + * @param string $date + * @param integer $minutes + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateSubMinutesExpression($date, $minutes) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $minutes, self::DATE_INTERVAL_UNIT_MINUTE); + } + + /** + * Returns the SQL to add the number of given hours to a date. + * + * @param string $date + * @param integer $hours + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateAddHourExpression($date, $hours) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $hours, self::DATE_INTERVAL_UNIT_HOUR); + } + + /** + * Returns the SQL to subtract the number of given hours to a date. + * + * @param string $date + * @param integer $hours + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateSubHourExpression($date, $hours) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $hours, self::DATE_INTERVAL_UNIT_HOUR); + } + /** * Returns the SQL to add the number of given days to a date. * @@ -951,7 +1133,7 @@ abstract class AbstractPlatform */ public function getDateAddDaysExpression($date, $days) { - throw DBALException::notSupported(__METHOD__); + return $this->getDateArithmeticIntervalExpression($date, '+', $days, self::DATE_INTERVAL_UNIT_DAY); } /** @@ -966,7 +1148,37 @@ abstract class AbstractPlatform */ public function getDateSubDaysExpression($date, $days) { - throw DBALException::notSupported(__METHOD__); + return $this->getDateArithmeticIntervalExpression($date, '-', $days, self::DATE_INTERVAL_UNIT_DAY); + } + + /** + * Returns the SQL to add the number of given weeks to a date. + * + * @param string $date + * @param integer $weeks + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateAddWeeksExpression($date, $weeks) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $weeks, self::DATE_INTERVAL_UNIT_WEEK); + } + + /** + * Returns the SQL to subtract the number of given weeks from a date. + * + * @param string $date + * @param integer $weeks + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateSubWeeksExpression($date, $weeks) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $weeks, self::DATE_INTERVAL_UNIT_WEEK); } /** @@ -981,7 +1193,7 @@ abstract class AbstractPlatform */ public function getDateAddMonthExpression($date, $months) { - throw DBALException::notSupported(__METHOD__); + return $this->getDateArithmeticIntervalExpression($date, '+', $months, self::DATE_INTERVAL_UNIT_MONTH); } /** @@ -995,6 +1207,84 @@ abstract class AbstractPlatform * @throws \Doctrine\DBAL\DBALException If not supported on this platform. */ public function getDateSubMonthExpression($date, $months) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $months, self::DATE_INTERVAL_UNIT_MONTH); + } + + /** + * Returns the SQL to add the number of given quarters to a date. + * + * @param string $date + * @param integer $quarters + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateAddQuartersExpression($date, $quarters) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $quarters, self::DATE_INTERVAL_UNIT_QUARTER); + } + + /** + * Returns the SQL to subtract the number of given quarters from a date. + * + * @param string $date + * @param integer $quarters + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateSubQuartersExpression($date, $quarters) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $quarters, self::DATE_INTERVAL_UNIT_QUARTER); + } + + /** + * Returns the SQL to add the number of given years to a date. + * + * @param string $date + * @param integer $years + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateAddYearsExpression($date, $years) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $years, self::DATE_INTERVAL_UNIT_YEAR); + } + + /** + * Returns the SQL to subtract the number of given years from a date. + * + * @param string $date + * @param integer $years + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDateSubYearsExpression($date, $years) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $years, self::DATE_INTERVAL_UNIT_YEAR); + } + + /** + * Returns the SQL for a date arithmetic expression. + * + * @param string $date The column or literal representing a date to perform the arithmetic operation on. + * @param string $operator The arithmetic operator (+ or -). + * @param integer $interval The interval that shall be calculated into the date. + * @param string $unit The unit of the interval that shall be calculated into the date. + * One of the DATE_INTERVAL_UNIT_* constants. + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { throw DBALException::notSupported(__METHOD__); } @@ -1027,7 +1317,7 @@ abstract class AbstractPlatform /** * Returns the FOR UPDATE expression. - * + * * @return string */ public function getForUpdateSQL() @@ -1101,7 +1391,7 @@ abstract class AbstractPlatform if ($table instanceof Table) { $table = $table->getQuotedName($this); - } else if(!is_string($table)) { + } elseif (!is_string($table)) { throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } @@ -1143,7 +1433,7 @@ abstract class AbstractPlatform { if ($index instanceof Index) { $index = $index->getQuotedName($this); - } else if(!is_string($index)) { + } elseif (!is_string($index)) { throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); } @@ -1173,7 +1463,7 @@ abstract class AbstractPlatform /** * Returns the SQL to drop a foreign key. - * + * * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint|string $foreignKey * @param \Doctrine\DBAL\Schema\Table|string $table * @@ -1284,8 +1574,10 @@ abstract class AbstractPlatform $sql = $this->_getCreateTableSQL($tableName, $columns, $options); if ($this->supportsCommentOnStatement()) { foreach ($table->getColumns() as $column) { - if ($this->getColumnComment($column)) { - $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $this->getColumnComment($column)); + $comment = $this->getColumnComment($column); + + if (null !== $comment && '' !== $comment) { + $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $comment); } } } @@ -1302,7 +1594,12 @@ abstract class AbstractPlatform */ public function getCommentOnColumnSQL($tableName, $columnName, $comment) { - return "COMMENT ON COLUMN " . $tableName . "." . $columnName . " IS '" . $comment . "'"; + $tableName = new Identifier($tableName); + $columnName = new Identifier($columnName); + $comment = $this->quoteStringLiteral($comment); + + return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) . + " IS " . $comment; } /** @@ -1329,7 +1626,7 @@ abstract class AbstractPlatform } if (isset($options['indexes']) && ! empty($options['indexes'])) { - foreach($options['indexes'] as $index => $definition) { + foreach ($options['indexes'] as $index => $definition) { $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition); } } @@ -1411,7 +1708,7 @@ abstract class AbstractPlatform $referencesClause = ''; if ($constraint instanceof Index) { - if($constraint->isPrimary()) { + if ($constraint->isPrimary()) { $query .= ' PRIMARY KEY'; } elseif ($constraint->isUnique()) { $query .= ' UNIQUE'; @@ -1420,7 +1717,7 @@ abstract class AbstractPlatform 'Can only create primary or unique constraints, no common indexes with getCreateConstraintSQL().' ); } - } else if ($constraint instanceof ForeignKeyConstraint) { + } elseif ($constraint instanceof ForeignKeyConstraint) { $query .= ' FOREIGN KEY'; $referencesClause = ' REFERENCES ' . $constraint->getQuotedForeignTableName($this) . @@ -1458,11 +1755,27 @@ abstract class AbstractPlatform } $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table; - $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')'; + $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')' . $this->getPartialIndexSQL($index); return $query; } + /** + * Adds condition for partial index. + * + * @param \Doctrine\DBAL\Schema\Index $index + * + * @return string + */ + protected function getPartialIndexSQL(Index $index) + { + if ($this->supportsPartialIndexes() && $index->hasOption('where')) { + return ' WHERE ' . $index->getOption('where'); + } + + return ''; + } + /** * Adds additional flags for index generation. * @@ -1488,6 +1801,19 @@ abstract class AbstractPlatform return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')'; } + /** + * Returns the SQL to create a named schema. + * + * @param string $schemaName + * + * @return string + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getCreateSchemaSQL($schemaName) + { + throw DBALException::notSupported(__METHOD__); + } + /** * Quotes a string so that it can be safely used as a table or column name, * even if it is a reserved word of the platform. This also detects identifier @@ -1504,7 +1830,7 @@ abstract class AbstractPlatform public function quoteIdentifier($str) { if (strpos($str, ".") !== false) { - $parts = array_map(array($this, "quoteIdentifier"), explode(".", $str)); + $parts = array_map(array($this, "quoteSingleIdentifier"), explode(".", $str)); return implode(".", $parts); } @@ -1693,7 +2019,7 @@ abstract class AbstractPlatform */ protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) { - $tableName = $diff->name; + $tableName = $diff->getName($this)->getQuotedName($this); $sql = array(); if ($this->supportsForeignKeyConstraints()) { @@ -1722,13 +2048,17 @@ abstract class AbstractPlatform */ protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) { - $tableName = false !== $diff->newName ? $diff->newName : $diff->name; + $tableName = (false !== $diff->newName) + ? $diff->getNewName()->getQuotedName($this) + : $diff->getName($this)->getQuotedName($this); $sql = array(); + if ($this->supportsForeignKeyConstraints()) { foreach ($diff->addedForeignKeys as $foreignKey) { $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); } + foreach ($diff->changedForeignKeys as $foreignKey) { $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); } @@ -1737,13 +2067,39 @@ abstract class AbstractPlatform foreach ($diff->addedIndexes as $index) { $sql[] = $this->getCreateIndexSQL($index, $tableName); } + foreach ($diff->changedIndexes as $index) { $sql[] = $this->getCreateIndexSQL($index, $tableName); } + foreach ($diff->renamedIndexes as $oldIndexName => $index) { + $oldIndexName = new Identifier($oldIndexName); + $sql = array_merge( + $sql, + $this->getRenameIndexSQL($oldIndexName->getQuotedName($this), $index, $tableName) + ); + } + return $sql; } + /** + * Returns the SQL for renaming an index on a table. + * + * @param string $oldIndexName The name of the index to rename from. + * @param \Doctrine\DBAL\Schema\Index $index The definition of the index to rename to. + * @param string $tableName The table to rename the given index on. + * + * @return array The sequence of SQL statements for renaming the given index. + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + return array( + $this->getDropIndexSQL($oldIndexName, $tableName), + $this->getCreateIndexSQL($index, $tableName) + ); + } + /** * Common code for alter table statement generation that updates the changed Index and Foreign Key definitions. * @@ -1854,8 +2210,8 @@ abstract class AbstractPlatform $columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation; } - if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment']) { - $columnDef .= " COMMENT '" . $field['comment'] . "'"; + if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment'] !== '') { + $columnDef .= " COMMENT " . $this->quoteStringLiteral($field['comment']); } return $name . ' ' . $columnDef; @@ -1893,15 +2249,15 @@ abstract class AbstractPlatform if (isset($field['default'])) { $default = " DEFAULT '".$field['default']."'"; if (isset($field['type'])) { - if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) { + if (in_array((string) $field['type'], array("Integer", "BigInt", "SmallInt"))) { $default = " DEFAULT ".$field['default']; - } else if ((string)$field['type'] == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL()) { + } elseif (in_array((string) $field['type'], array('DateTime', 'DateTimeTz')) && $field['default'] == $this->getCurrentTimestampSQL()) { $default = " DEFAULT ".$this->getCurrentTimestampSQL(); - } else if ((string)$field['type'] == 'Time' && $field['default'] == $this->getCurrentTimeSQL()) { + } elseif ((string) $field['type'] == 'Time' && $field['default'] == $this->getCurrentTimeSQL()) { $default = " DEFAULT ".$this->getCurrentTimeSQL(); - } else if ((string)$field['type'] == 'Date' && $field['default'] == $this->getCurrentDateSQL()) { + } elseif ((string) $field['type'] == 'Date' && $field['default'] == $this->getCurrentDateSQL()) { $default = " DEFAULT ".$this->getCurrentDateSQL(); - } else if ((string) $field['type'] == 'Boolean') { + } elseif ((string) $field['type'] == 'Boolean') { $default = " DEFAULT '" . $this->convertBooleans($field['default']) . "'"; } } @@ -1942,8 +2298,8 @@ abstract class AbstractPlatform * Obtains DBMS specific SQL code portion needed to set a unique * constraint declaration to be used in statements like CREATE TABLE. * - * @param string $name The name of the unique constraint. - * @param \Doctrine\DBAL\Schema\Index $index The index definition. + * @param string $name The name of the unique constraint. + * @param \Doctrine\DBAL\Schema\Index $index The index definition. * * @return string DBMS specific SQL code portion needed to set a constraint. * @@ -1952,22 +2308,23 @@ abstract class AbstractPlatform public function getUniqueConstraintDeclarationSQL($name, Index $index) { $columns = $index->getQuotedColumns($this); + $name = new Identifier($name); if (count($columns) === 0) { throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); } - return 'CONSTRAINT ' . $name . ' UNIQUE (' + return 'CONSTRAINT ' . $name->getQuotedName($this) . ' UNIQUE (' . $this->getIndexFieldDeclarationListSQL($columns) - . ')'; + . ')' . $this->getPartialIndexSQL($index); } /** * Obtains DBMS specific SQL code portion needed to set an index * declaration to be used in statements like CREATE TABLE. * - * @param string $name The name of the index. - * @param \Doctrine\DBAL\Schema\Index $index The index definition. + * @param string $name The name of the index. + * @param \Doctrine\DBAL\Schema\Index $index The index definition. * * @return string DBMS specific SQL code portion needed to set an index. * @@ -1976,14 +2333,15 @@ abstract class AbstractPlatform public function getIndexDeclarationSQL($name, Index $index) { $columns = $index->getQuotedColumns($this); + $name = new Identifier($name); if (count($columns) === 0) { throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); } - return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' (' - . $this->getIndexFieldDeclarationListSQL($columns) - . ')'; + return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name->getQuotedName($this) . ' (' + . $this->getIndexFieldDeclarationListSQL($columns) + . ')' . $this->getPartialIndexSQL($index); } /** @@ -2189,7 +2547,7 @@ abstract class AbstractPlatform */ public function getColumnCollationDeclarationSQL($collation) { - return ''; + return $this->supportsColumnCollation() ? 'COLLATE ' . $collation : ''; } /** @@ -2215,12 +2573,17 @@ abstract class AbstractPlatform } /** + * Some platforms need the boolean values to be converted. + * + * The default conversion in this implementation converts to integers (false => 0, true => 1). + * * Note: if the input is not a boolean the original input might be returned. * * There are two contexts when converting booleans: Literals and Prepared Statements. * This method should handle the literal case * * @param mixed $item A boolean or an array of them. + * * @return mixed A boolean database value or an array of them. */ public function convertBooleans($item) @@ -2238,7 +2601,6 @@ abstract class AbstractPlatform return $item; } - /** * Some platforms have boolean literals that needs to be correctly converted * @@ -2250,7 +2612,7 @@ abstract class AbstractPlatform */ public function convertFromBoolean($item) { - return null === $item ? null : (bool)$item; + return null === $item ? null: (bool) $item ; } /** @@ -2260,6 +2622,7 @@ abstract class AbstractPlatform * Note: if the input is not a boolean the original input might be returned. * * @param mixed $item A boolean or an array of them. + * * @return mixed A boolean database value or an array of them. */ public function convertBooleansToDatabaseValue($item) @@ -2332,6 +2695,18 @@ abstract class AbstractPlatform throw DBALException::notSupported(__METHOD__); } + /** + * Returns the SQL statement for retrieving the namespaces defined in the database. + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getListNamespacesSQL() + { + throw DBALException::notSupported(__METHOD__); + } + /** * @param string $database * @@ -2465,7 +2840,7 @@ abstract class AbstractPlatform /** * Returns the SQL snippet to drop an existing sequence. * - * @param \Doctrine\DBAL\Schema\Sequence $sequence + * @param Sequence|string $sequence * * @return string * @@ -2621,6 +2996,37 @@ abstract class AbstractPlatform return false; } + /** + * Whether the platform emulates identity columns through sequences. + * + * Some platforms that do not support identity columns natively + * but support sequences can emulate identity columns by using + * sequences. + * + * @return boolean + */ + public function usesSequenceEmulatedIdentityColumns() + { + return false; + } + + /** + * Returns the name of the sequence for a particular identity column in a particular table. + * + * @param string $tableName The name of the table to return the sequence name for. + * @param string $columnName The name of the identity column in the table to return the sequence name for. + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + * + * @see usesSequenceEmulatedIdentityColumns + */ + public function getIdentitySequenceName($tableName, $columnName) + { + throw DBALException::notSupported(__METHOD__); + } + /** * Whether the platform supports indexes. * @@ -2631,6 +3037,16 @@ abstract class AbstractPlatform return true; } + /** + * Whether the platform supports partial indexes. + * + * @return boolean + */ + public function supportsPartialIndexes() + { + return false; + } + /** * Whether the platform supports altering tables. * @@ -2725,6 +3141,18 @@ abstract class AbstractPlatform return false; } + /** + * Returns the default schema name. + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException If not supported on this platform. + */ + public function getDefaultSchemaName() + { + throw DBALException::notSupported(__METHOD__); + } + /** * Whether this platform supports create database. * @@ -2777,6 +3205,16 @@ abstract class AbstractPlatform return false; } + /** + * Does this platform have native JSON type. + * + * @return boolean + */ + public function hasNativeJsonType() + { + return false; + } + /** * @deprecated * @todo Remove in 3.0 @@ -2796,6 +3234,16 @@ abstract class AbstractPlatform return true; } + /** + * Does this platform support column collation? + * + * @return boolean + */ + public function supportsColumnCollation() + { + return false; + } + /** * Gets the format string, as accepted by the date() function, that describes * the format of a stored datetime value of this platform. @@ -2854,11 +3302,11 @@ abstract class AbstractPlatform final public function modifyLimitQuery($query, $limit, $offset = null) { if ($limit !== null) { - $limit = (int)$limit; + $limit = (int) $limit; } if ($offset !== null) { - $offset = (int)$offset; + $offset = (int) $offset; if ($offset < 0) { throw new DBALException("LIMIT argument offset=$offset is not valid"); @@ -2874,7 +3322,7 @@ abstract class AbstractPlatform /** * Adds an driver-specific LIMIT clause to the query. * - * @param string $query + * @param string $query * @param integer|null $limit * @param integer|null $offset * @@ -3050,4 +3498,31 @@ abstract class AbstractPlatform { throw DBALException::notSupported(__METHOD__); } + + /** + * Quotes a literal string. + * This method is NOT meant to fix SQL injections! + * It is only meant to escape this platform's string literal + * quote character inside the given literal string. + * + * @param string $str The literal string to be quoted. + * + * @return string The quoted literal string. + */ + public function quoteStringLiteral($str) + { + $c = $this->getStringLiteralQuoteCharacter(); + + return $c . str_replace($c, $c . $c, $str) . $c; + } + + /** + * Gets the character used for string literal quoting. + * + * @return string + */ + public function getStringLiteralQuoteCharacter() + { + return "'"; + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php index 6dc832da7b..9cc794d16a 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php @@ -20,17 +20,38 @@ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Schema\Column; +use Doctrine\DBAL\Schema\ColumnDiff; +use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; class DB2Platform extends AbstractPlatform { + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 32704; + } + + /** + * {@inheritdoc} + */ + public function getBinaryDefaultLength() + { + return 1; + } + /** * {@inheritDoc} */ public function getBlobTypeDeclarationSQL(array $field) { - throw DBALException::notSupported(__METHOD__); + // todo blob(n) with $field['length']; + return 'BLOB(1M)'; } /** @@ -46,7 +67,10 @@ class DB2Platform extends AbstractPlatform 'date' => 'date', 'varchar' => 'string', 'character' => 'string', + 'varbinary' => 'binary', + 'binary' => 'binary', 'clob' => 'text', + 'blob' => 'blob', 'decimal' => 'decimal', 'double' => 'float', 'real' => 'float', @@ -63,6 +87,14 @@ class DB2Platform extends AbstractPlatform : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); } + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; + } + /** * {@inheritDoc} */ @@ -126,59 +158,87 @@ class DB2Platform extends AbstractPlatform } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + public function getBitAndComparisonExpression($value1, $value2) { - if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) { - return "TIMESTAMP(0) WITH DEFAULT"; + return 'BITAND(' . $value1 . ', ' . $value2 . ')'; + } + + /** + * {@inheritdoc} + */ + public function getBitOrComparisonExpression($value1, $value2) + { + return 'BITOR(' . $value1 . ', ' . $value2 . ')'; + } + + /** + * {@inheritdoc} + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + { + switch ($unit) { + case self::DATE_INTERVAL_UNIT_WEEK: + $interval *= 7; + $unit = self::DATE_INTERVAL_UNIT_DAY; + break; + + case self::DATE_INTERVAL_UNIT_QUARTER: + $interval *= 3; + $unit = self::DATE_INTERVAL_UNIT_MONTH; + break; } - return 'TIMESTAMP(0)'; + return $date . ' ' . $operator . ' ' . $interval . ' ' . $unit; } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) + public function getDateDiffExpression($date1, $date2) { - return 'DATE'; + return 'DAYS(' . $date1 . ') - DAYS(' . $date2 . ')'; } /** * {@inheritDoc} */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) { - return 'TIME'; + if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) { + return "TIMESTAMP(0) WITH DEFAULT"; + } + + return 'TIMESTAMP(0)'; } /** * {@inheritDoc} */ - public function getListDatabasesSQL() + public function getDateTypeDeclarationSQL(array $fieldDeclaration) { - throw DBALException::notSupported(__METHOD__); + return 'DATE'; } /** * {@inheritDoc} */ - public function getListSequencesSQL($database) + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) { - throw DBALException::notSupported(__METHOD__); + return 'TIME'; } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getListTableConstraintsSQL($table) + public function getTruncateTableSQL($tableName, $cascade = false) { - throw DBALException::notSupported(__METHOD__); + return 'TRUNCATE ' . $tableName . ' IMMEDIATE'; } /** - * This code fragment is originally from the Zend_Db_Adapter_Db2 class. + * This code fragment is originally from the Zend_Db_Adapter_Db2 class, but has been edited. * * @license New BSD License * @@ -189,18 +249,47 @@ class DB2Platform extends AbstractPlatform */ public function getListTableColumnsSQL($table, $database = null) { - return "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno, - c.typename, c.default, c.nulls, c.length, c.scale, - c.identity, tc.type AS tabconsttype, k.colseq - FROM syscat.columns c - LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc - ON (k.tabschema = tc.tabschema - AND k.tabname = tc.tabname - AND tc.type = 'P')) - ON (c.tabschema = k.tabschema - AND c.tabname = k.tabname - AND c.colname = k.colname) - WHERE UPPER(c.tabname) = UPPER('" . $table . "') ORDER BY c.colno"; + // We do the funky subquery and join syscat.columns.default this crazy way because + // as of db2 v10, the column is CLOB(64k) and the distinct operator won't allow a CLOB, + // it wants shorter stuff like a varchar. + return " + SELECT + cols.default, + subq.* + FROM ( + SELECT DISTINCT + c.tabschema, + c.tabname, + c.colname, + c.colno, + c.typename, + c.nulls, + c.length, + c.scale, + c.identity, + tc.type AS tabconsttype, + k.colseq, + CASE + WHEN c.generated = 'D' THEN 1 + ELSE 0 + END AS autoincrement + FROM syscat.columns c + LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc + ON (k.tabschema = tc.tabschema + AND k.tabname = tc.tabname + AND tc.type = 'P')) + ON (c.tabschema = k.tabschema + AND c.tabname = k.tabname + AND c.colname = k.colname) + WHERE UPPER(c.tabname) = UPPER('" . $table . "') + ORDER BY c.colno + ) subq + JOIN syscat.columns cols + ON subq.tabschema = cols.tabschema + AND subq.tabname = cols.tabname + AND subq.colno = cols.colno + ORDER BY subq.colno + "; } /** @@ -211,14 +300,6 @@ class DB2Platform extends AbstractPlatform return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'"; } - /** - * {@inheritDoc} - */ - public function getListUsersSQL() - { - throw DBALException::notSupported(__METHOD__); - } - /** * {@inheritDoc} */ @@ -232,7 +313,21 @@ class DB2Platform extends AbstractPlatform */ public function getListTableIndexesSQL($table, $currentDatabase = null) { - return "SELECT NAME, COLNAMES, UNIQUERULE FROM SYSIBM.SYSINDEXES WHERE TBNAME = UPPER('" . $table . "')"; + return "SELECT idx.INDNAME AS key_name, + idxcol.COLNAME AS column_name, + CASE + WHEN idx.UNIQUERULE = 'P' THEN 1 + ELSE 0 + END AS primary, + CASE + WHEN idx.UNIQUERULE = 'D' THEN 1 + ELSE 0 + END AS non_unique + FROM SYSCAT.INDEXES AS idx + JOIN SYSCAT.INDEXCOLUSE AS idxcol + ON idx.INDSCHEMA = idxcol.INDSCHEMA AND idx.INDNAME = idxcol.INDNAME + WHERE idx.TABNAME = UPPER('" . $table . "') + ORDER BY idxcol.COLSEQ ASC"; } /** @@ -240,8 +335,31 @@ class DB2Platform extends AbstractPlatform */ public function getListTableForeignKeysSQL($table) { - return "SELECT TBNAME, RELNAME, REFTBNAME, DELETERULE, UPDATERULE, FKCOLNAMES, PKCOLNAMES ". - "FROM SYSIBM.SYSRELS WHERE TBNAME = UPPER('".$table."')"; + return "SELECT fkcol.COLNAME AS local_column, + fk.REFTABNAME AS foreign_table, + pkcol.COLNAME AS foreign_column, + fk.CONSTNAME AS index_name, + CASE + WHEN fk.UPDATERULE = 'R' THEN 'RESTRICT' + ELSE NULL + END AS on_update, + CASE + WHEN fk.DELETERULE = 'C' THEN 'CASCADE' + WHEN fk.DELETERULE = 'N' THEN 'SET NULL' + WHEN fk.DELETERULE = 'R' THEN 'RESTRICT' + ELSE NULL + END AS on_delete + FROM SYSCAT.REFERENCES AS fk + JOIN SYSCAT.KEYCOLUSE AS fkcol + ON fk.CONSTNAME = fkcol.CONSTNAME + AND fk.TABSCHEMA = fkcol.TABSCHEMA + AND fk.TABNAME = fkcol.TABNAME + JOIN SYSCAT.KEYCOLUSE AS pkcol + ON fk.REFKEYNAME = pkcol.CONSTNAME + AND fk.REFTABSCHEMA = pkcol.TABSCHEMA + AND fk.REFTABNAME = pkcol.TABNAME + WHERE fk.TABNAME = UPPER('" . $table . "') + ORDER BY fkcol.COLSEQ ASC"; } /** @@ -260,22 +378,6 @@ class DB2Platform extends AbstractPlatform return "DROP VIEW ".$name; } - /** - * {@inheritDoc} - */ - public function getDropSequenceSQL($sequence) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * {@inheritDoc} - */ - public function getSequenceNextValSQL($sequenceName) - { - throw DBALException::notSupported(__METHOD__); - } - /** * {@inheritDoc} */ @@ -289,7 +391,7 @@ class DB2Platform extends AbstractPlatform */ public function getDropDatabaseSQL($database) { - return "DROP DATABASE ".$database.";"; + return "DROP DATABASE " . $database; } /** @@ -313,7 +415,7 @@ class DB2Platform extends AbstractPlatform */ public function getCurrentDateSQL() { - return 'VALUES CURRENT DATE'; + return 'CURRENT DATE'; } /** @@ -321,7 +423,7 @@ class DB2Platform extends AbstractPlatform */ public function getCurrentTimeSQL() { - return 'VALUES CURRENT TIME'; + return 'CURRENT TIME'; } /** @@ -329,7 +431,7 @@ class DB2Platform extends AbstractPlatform */ public function getCurrentTimestampSQL() { - return "VALUES CURRENT TIMESTAMP"; + return "CURRENT TIMESTAMP"; } /** @@ -337,7 +439,8 @@ class DB2Platform extends AbstractPlatform */ public function getIndexDeclarationSQL($name, Index $index) { - return $this->getUniqueConstraintDeclarationSQL($name, $index); + // Index declaration in statements like CREATE TABLE is not supported. + throw DBALException::notSupported(__METHOD__); } /** @@ -366,6 +469,7 @@ class DB2Platform extends AbstractPlatform { $sql = array(); $columnSql = array(); + $commentsSQL = array(); $queryParts = array(); foreach ($diff->addedColumns as $column) { @@ -373,7 +477,28 @@ class DB2Platform extends AbstractPlatform continue; } - $queryParts[] = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + $columnDef = $column->toArray(); + $queryPart = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); + + // Adding non-nullable columns to a table requires a default value to be specified. + if ( ! empty($columnDef['notnull']) && + ! isset($columnDef['default']) && + empty($columnDef['autoincrement']) + ) { + $queryPart .= ' WITH DEFAULT'; + } + + $queryParts[] = $queryPart; + + $comment = $this->getColumnComment($column); + + if (null !== $comment && '' !== $comment) { + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $comment + ); + } } foreach ($diff->removedColumns as $column) { @@ -389,10 +514,19 @@ class DB2Platform extends AbstractPlatform continue; } - /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ - $column = $columnDiff->column; - $queryParts[] = 'ALTER ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' - . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + if ($columnDiff->hasChanged('comment')) { + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $columnDiff->column->getQuotedName($this), + $this->getColumnComment($columnDiff->column) + ); + + if (count($columnDiff->changedProperties) === 1) { + continue; + } + } + + $this->gatherAlterColumnSQL($diff->fromTable, $columnDiff, $sql, $queryParts); } foreach ($diff->renamedColumns as $oldColumnName => $column) { @@ -400,48 +534,176 @@ class DB2Platform extends AbstractPlatform continue; } - $queryParts[] = 'RENAME ' . $oldColumnName . ' TO ' . $column->getQuotedName($this); + $oldColumnName = new Identifier($oldColumnName); + + $queryParts[] = 'RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . + ' TO ' . $column->getQuotedName($this); } $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if (count($queryParts) > 0) { - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(" ", $queryParts); + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(" ", $queryParts); + } + + // Some table alteration operations require a table reorganization. + if ( ! empty($diff->removedColumns) || ! empty($diff->changedColumns)) { + $sql[] = "CALL SYSPROC.ADMIN_CMD ('REORG TABLE " . $diff->getName($this)->getQuotedName($this) . "')"; } - $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff)); + $sql = array_merge($sql, $commentsSQL); if ($diff->newName !== false) { - $sql[] = 'RENAME TABLE TO ' . $diff->newName; + $sql[] = 'RENAME TABLE ' . $diff->getName($this)->getQuotedName($this) . ' TO ' . $diff->getNewName()->getQuotedName($this); } + + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); } return array_merge($sql, $tableSql, $columnSql); } /** - * {@inheritDoc} + * Gathers the table alteration SQL for a given column diff. + * + * @param Table $table The table to gather the SQL for. + * @param ColumnDiff $columnDiff The column diff to evaluate. + * @param array $sql The sequence of table alteration statements to fill. + * @param array $queryParts The sequence of column alteration clauses to fill. */ - public function getDefaultValueDeclarationSQL($field) + private function gatherAlterColumnSQL(Table $table, ColumnDiff $columnDiff, array &$sql, array &$queryParts) { - if (isset($field['notnull']) && $field['notnull'] && !isset($field['default'])) { - if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) { - $field['default'] = 0; - } else if((string)$field['type'] == "DateTime") { - $field['default'] = "00-00-00 00:00:00"; - } else if ((string)$field['type'] == "Date") { - $field['default'] = "00-00-00"; - } else if((string)$field['type'] == "Time") { - $field['default'] = "00:00:00"; + $alterColumnClauses = $this->getAlterColumnClausesSQL($columnDiff); + + if (empty($alterColumnClauses)) { + return; + } + + // If we have a single column alteration, we can append the clause to the main query. + if (count($alterColumnClauses) === 1) { + $queryParts[] = current($alterColumnClauses); + + return; + } + + // We have multiple alterations for the same column, + // so we need to trigger a complete ALTER TABLE statement + // for each ALTER COLUMN clause. + foreach ($alterColumnClauses as $alterColumnClause) { + $sql[] = 'ALTER TABLE ' . $table->getQuotedName($this) . ' ' . $alterColumnClause; + } + } + + /** + * Returns the ALTER COLUMN SQL clauses for altering a column described by the given column diff. + * + * @param ColumnDiff $columnDiff The column diff to evaluate. + * + * @return array + */ + private function getAlterColumnClausesSQL(ColumnDiff $columnDiff) + { + $column = $columnDiff->column->toArray(); + + $alterClause = 'ALTER COLUMN ' . $columnDiff->column->getQuotedName($this); + + if ($column['columnDefinition']) { + return array($alterClause . ' ' . $column['columnDefinition']); + } + + $clauses = array(); + + if ($columnDiff->hasChanged('type') || + $columnDiff->hasChanged('length') || + $columnDiff->hasChanged('precision') || + $columnDiff->hasChanged('scale') || + $columnDiff->hasChanged('fixed') + ) { + $clauses[] = $alterClause . ' SET DATA TYPE ' . $column['type']->getSQLDeclaration($column, $this); + } + + if ($columnDiff->hasChanged('notnull')) { + $clauses[] = $column['notnull'] ? $alterClause . ' SET NOT NULL' : $alterClause . ' DROP NOT NULL'; + } + + if ($columnDiff->hasChanged('default')) { + if (isset($column['default'])) { + $defaultClause = $this->getDefaultValueDeclarationSQL($column); + + if ($defaultClause) { + $clauses[] = $alterClause . ' SET' . $defaultClause; + } } else { - $field['default'] = ''; + $clauses[] = $alterClause . ' DROP DEFAULT'; + } + } + + return $clauses; + } + + /** + * {@inheritDoc} + */ + protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) + { + $sql = array(); + $table = $diff->getName($this)->getQuotedName($this); + + foreach ($diff->removedIndexes as $remKey => $remIndex) { + foreach ($diff->addedIndexes as $addKey => $addIndex) { + if ($remIndex->getColumns() == $addIndex->getColumns()) { + if ($remIndex->isPrimary()) { + $sql[] = 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; + } elseif ($remIndex->isUnique()) { + $sql[] = 'ALTER TABLE ' . $table . ' DROP UNIQUE ' . $remIndex->getQuotedName($this); + } else { + $sql[] = $this->getDropIndexSQL($remIndex, $table); + } + + $sql[] = $this->getCreateIndexSQL($addIndex, $table); + + unset($diff->removedIndexes[$remKey]); + unset($diff->addedIndexes[$addKey]); + + break; + } } } - unset($field['default']); // @todo this needs fixing + $sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff)); + + return $sql; + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + if (strpos($tableName, '.') !== false) { + list($schema) = explode('.', $tableName); + $oldIndexName = $schema . '.' . $oldIndexName; + } + + return array('RENAME INDEX ' . $oldIndexName . ' TO ' . $index->getQuotedName($this)); + } + + /** + * {@inheritDoc} + */ + public function getDefaultValueDeclarationSQL($field) + { + if ( ! empty($field['autoincrement'])) { + return ''; + } + if (isset($field['version']) && $field['version']) { - if ((string)$field['type'] != "DateTime") { + if ((string) $field['type'] != "DateTime") { $field['default'] = "1"; } } @@ -482,8 +744,8 @@ class DB2Platform extends AbstractPlatform return $query; } - $limit = (int)$limit; - $offset = (int)(($offset)?:0); + $limit = (int) $limit; + $offset = (int) (($offset)?:0); // Todo OVER() needs ORDER BY data! $sql = 'SELECT db22.* FROM (SELECT ROW_NUMBER() OVER() AS DC_ROWNUM, db21.* '. diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php index 3520f36431..08f053b08c 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php @@ -19,10 +19,11 @@ namespace Doctrine\DBAL\Platforms; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Types\BinaryType; /** * Drizzle platform @@ -58,43 +59,21 @@ class DrizzlePlatform extends AbstractPlatform } /** - * {@inheritDoc} - */ - public function getDateDiffExpression($date1, $date2) - { - return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; - } - - /** - * {@inheritDoc} - */ - public function getDateAddDaysExpression($date, $days) - { - return 'DATE_ADD(' . $date . ', INTERVAL ' . $days . ' DAY)'; - } - - /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getDateSubDaysExpression($date, $days) + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { - return 'DATE_SUB(' . $date . ', INTERVAL ' . $days . ' DAY)'; - } + $function = '+' === $operator ? 'DATE_ADD' : 'DATE_SUB'; - /** - * {@inheritDoc} - */ - public function getDateAddMonthExpression($date, $months) - { - return 'DATE_ADD(' . $date . ', INTERVAL ' . $months . ' MONTH)'; + return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')'; } /** * {@inheritDoc} */ - public function getDateSubMonthExpression($date, $months) + public function getDateDiffExpression($date1, $date2) { - return 'DATE_SUB(' . $date . ', INTERVAL ' . $months . ' MONTH)'; + return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; } /** @@ -122,6 +101,7 @@ class DrizzlePlatform extends AbstractPlatform if ( ! empty($columnDef['autoincrement'])) { $autoinc = ' AUTO_INCREMENT'; } + return $autoinc; } @@ -149,6 +129,14 @@ class DrizzlePlatform extends AbstractPlatform return $length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'; } + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return 'VARBINARY(' . ($length ?: 255) . ')'; + } + /** * {@inheritDoc} */ @@ -157,8 +145,9 @@ class DrizzlePlatform extends AbstractPlatform $this->doctrineTypeMapping = array( 'boolean' => 'boolean', 'varchar' => 'string', + 'varbinary' => 'binary', 'integer' => 'integer', - 'blob' => 'text', + 'blob' => 'blob', 'decimal' => 'decimal', 'datetime' => 'datetime', 'date' => 'date', @@ -202,6 +191,116 @@ class DrizzlePlatform extends AbstractPlatform return 'DROP DATABASE ' . $name; } + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) + { + $queryFields = $this->getColumnDeclarationListSQL($columns); + + if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { + foreach ($options['uniqueConstraints'] as $index => $definition) { + $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($index, $definition); + } + } + + // add all indexes + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach ($options['indexes'] as $index => $definition) { + $queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition); + } + } + + // attach all primary keys + if (isset($options['primary']) && ! empty($options['primary'])) { + $keyColumns = array_unique(array_values($options['primary'])); + $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; + } + + $query = 'CREATE '; + + if (!empty($options['temporary'])) { + $query .= 'TEMPORARY '; + } + + $query .= 'TABLE ' . $tableName . ' (' . $queryFields . ') '; + $query .= $this->buildTableOptions($options); + $query .= $this->buildPartitionOptions($options); + + $sql[] = $query; + + if (isset($options['foreignKeys'])) { + foreach ((array) $options['foreignKeys'] as $definition) { + $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); + } + } + + return $sql; + } + + /** + * Build SQL for table options + * + * @param array $options + * + * @return string + */ + private function buildTableOptions(array $options) + { + if (isset($options['table_options'])) { + return $options['table_options']; + } + + $tableOptions = array(); + + // Collate + if ( ! isset($options['collate'])) { + $options['collate'] = 'utf8_unicode_ci'; + } + + $tableOptions[] = sprintf('COLLATE %s', $options['collate']); + + // Engine + if ( ! isset($options['engine'])) { + $options['engine'] = 'InnoDB'; + } + + $tableOptions[] = sprintf('ENGINE = %s', $options['engine']); + + // Auto increment + if (isset($options['auto_increment'])) { + $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']); + } + + // Comment + if (isset($options['comment'])) { + $comment = trim($options['comment'], " '"); + + $tableOptions[] = sprintf("COMMENT = %s ", $this->quoteStringLiteral($comment)); + } + + // Row format + if (isset($options['row_format'])) { + $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']); + } + + return implode(' ', $tableOptions); + } + + /** + * Build SQL for partition options. + * + * @param array $options + * + * @return string + */ + private function buildPartitionOptions(array $options) + { + return (isset($options['partition_options'])) + ? ' ' . $options['partition_options'] + : ''; + } + /** * {@inheritDoc} */ @@ -238,7 +337,7 @@ class DrizzlePlatform extends AbstractPlatform } return "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT," . - " NUMERIC_PRECISION, NUMERIC_SCALE" . + " NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME" . " FROM DATA_DICTIONARY.COLUMNS" . " WHERE TABLE_SCHEMA=" . $database . " AND TABLE_NAME = '" . $table . "'"; } @@ -307,6 +406,14 @@ class DrizzlePlatform extends AbstractPlatform return false; } + /** + * {@inheritdoc} + */ + public function supportsColumnCollation() + { + return true; + } + /** * {@inheritDoc} */ @@ -314,7 +421,7 @@ class DrizzlePlatform extends AbstractPlatform { if ($index instanceof Index) { $indexName = $index->getQuotedName($this); - } else if (is_string($index)) { + } elseif (is_string($index)) { $indexName = $index; } else { throw new \InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); @@ -322,7 +429,7 @@ class DrizzlePlatform extends AbstractPlatform if ($table instanceof Table) { $table = $table->getQuotedName($this); - } else if(!is_string($table)) { + } elseif (!is_string($table)) { throw new \InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } @@ -380,7 +487,7 @@ class DrizzlePlatform extends AbstractPlatform $queryParts = array(); if ($diff->newName !== false) { - $queryParts[] = 'RENAME TO ' . $diff->newName; + $queryParts[] = 'RENAME TO ' . $diff->getNewName()->getQuotedName($this); } foreach ($diff->addedColumns as $column) { @@ -409,6 +516,17 @@ class DrizzlePlatform extends AbstractPlatform /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ $column = $columnDiff->column; $columnArray = $column->toArray(); + + // Do not generate column alteration clause if type is binary and only fixed property has changed. + // Drizzle only supports binary type columns with variable length. + // Avoids unnecessary table alteration statements. + if ($columnArray['type'] instanceof BinaryType && + $columnDiff->hasChanged('fixed') && + count($columnDiff->changedProperties) === 1 + ) { + continue; + } + $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); @@ -419,9 +537,11 @@ class DrizzlePlatform extends AbstractPlatform continue; } + $oldColumnName = new Identifier($oldColumnName); + $columnArray = $column->toArray(); $columnArray['comment'] = $this->getColumnComment($column); - $queryParts[] = 'CHANGE ' . $oldColumnName . ' ' + $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } @@ -430,7 +550,7 @@ class DrizzlePlatform extends AbstractPlatform if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if (count($queryParts) > 0) { - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts); + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(", ", $queryParts); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), @@ -449,7 +569,7 @@ class DrizzlePlatform extends AbstractPlatform { if ($table instanceof Table) { $table = $table->getQuotedName($this); - } else if(!is_string($table)) { + } elseif (!is_string($table)) { throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } @@ -467,7 +587,7 @@ class DrizzlePlatform extends AbstractPlatform $item[$key] = ($value) ? 'true' : 'false'; } } - } else if (is_bool($item) || is_numeric($item)) { + } elseif (is_bool($item) || is_numeric($item)) { $item = ($item) ? 'true' : 'false'; } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php index b7db0fac39..21d59d8c58 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php @@ -22,7 +22,7 @@ namespace Doctrine\DBAL\Platforms\Keywords; /** * Drizzle Keywordlist. * - * @author Kim Hemsø Rasmussen + * @author Kim Hemsø Rasmussen */ class DrizzleKeywords extends KeywordList { diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MySQL57Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MySQL57Keywords.php new file mode 100644 index 0000000000..7d7b202087 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MySQL57Keywords.php @@ -0,0 +1,281 @@ +. + */ + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * MySQL 5.7 reserved keywords list. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class MySQL57Keywords extends MySQLKeywords +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'MySQL57'; + } + + /** + * {@inheritdoc} + * + * @link http://dev.mysql.com/doc/mysqld-version-reference/en/mysqld-version-reference-reservedwords-5-7.html + */ + protected function getKeywords() + { + return array( + 'ACCESSIBLE', + 'ADD', + 'ALL', + 'ALTER', + 'ANALYZE', + 'AND', + 'AS', + 'ASC', + 'ASENSITIVE', + 'BEFORE', + 'BETWEEN', + 'BIGINT', + 'BINARY', + 'BLOB', + 'BOTH', + 'BY', + 'CALL', + 'CASCADE', + 'CASE', + 'CHANGE', + 'CHAR', + 'CHARACTER', + 'CHECK', + 'COLLATE', + 'COLUMN', + 'CONDITION', + 'CONSTRAINT', + 'CONTINUE', + 'CONVERT', + 'CREATE', + 'CROSS', + 'CURRENT_DATE', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'CURRENT_USER', + 'CURSOR', + 'DATABASE', + 'DATABASES', + 'DAY_HOUR', + 'DAY_MICROSECOND', + 'DAY_MINUTE', + 'DAY_SECOND', + 'DEC', + 'DECIMAL', + 'DECLARE', + 'DEFAULT', + 'DELAYED', + 'DELETE', + 'DESC', + 'DESCRIBE', + 'DETERMINISTIC', + 'DISTINCT', + 'DISTINCTROW', + 'DIV', + 'DOUBLE', + 'DROP', + 'DUAL', + 'EACH', + 'ELSE', + 'ELSEIF', + 'ENCLOSED', + 'ESCAPED', + 'EXISTS', + 'EXIT', + 'EXPLAIN', + 'FALSE', + 'FETCH', + 'FLOAT', + 'FLOAT4', + 'FLOAT8', + 'FOR', + 'FORCE', + 'FOREIGN', + 'FROM', + 'FULLTEXT', + 'GET', + 'GRANT', + 'GROUP', + 'HAVING', + 'HIGH_PRIORITY', + 'HOUR_MICROSECOND', + 'HOUR_MINUTE', + 'HOUR_SECOND', + 'IF', + 'IGNORE', + 'IN', + 'INDEX', + 'INFILE', + 'INNER', + 'INOUT', + 'INSENSITIVE', + 'INSERT', + 'INT', + 'INT1', + 'INT2', + 'INT3', + 'INT4', + 'INT8', + 'INTEGER', + 'INTERVAL', + 'INTO', + 'IO_AFTER_GTIDS', + 'IO_BEFORE_GTIDS', + 'IS', + 'ITERATE', + 'JOIN', + 'KEY', + 'KEYS', + 'KILL', + 'LEADING', + 'LEAVE', + 'LEFT', + 'LIKE', + 'LIMIT', + 'LINEAR', + 'LINES', + 'LOAD', + 'LOCALTIME', + 'LOCALTIMESTAMP', + 'LOCK', + 'LONG', + 'LONGBLOB', + 'LONGTEXT', + 'LOOP', + 'LOW_PRIORITY', + 'MASTER_BIND', + 'MASTER_SSL_VERIFY_SERVER_CERT', + 'MATCH', + 'MAXVALUE', + 'MEDIUMBLOB', + 'MEDIUMINT', + 'MEDIUMTEXT', + 'MIDDLEINT', + 'MINUTE_MICROSECOND', + 'MINUTE_SECOND', + 'MOD', + 'MODIFIES', + 'NATURAL', + 'NO_WRITE_TO_BINLOG', + 'NONBLOCKING', + 'NOT', + 'NULL', + 'NUMERIC', + 'ON', + 'OPTIMIZE', + 'OPTION', + 'OPTIONALLY', + 'OR', + 'ORDER', + 'OUT', + 'OUTER', + 'OUTFILE', + 'PARTITION', + 'PRECISION', + 'PRIMARY', + 'PROCEDURE', + 'PURGE', + 'RANGE', + 'READ', + 'READ_WRITE', + 'READS', + 'REAL', + 'REFERENCES', + 'REGEXP', + 'RELEASE', + 'RENAME', + 'REPEAT', + 'REPLACE', + 'REQUIRE', + 'RESIGNAL', + 'RESTRICT', + 'RETURN', + 'REVOKE', + 'RIGHT', + 'RLIKE', + 'SCHEMA', + 'SCHEMAS', + 'SECOND_MICROSECOND', + 'SELECT', + 'SENSITIVE', + 'SEPARATOR', + 'SET', + 'SHOW', + 'SIGNAL', + 'SMALLINT', + 'SPATIAL', + 'SPECIFIC', + 'SQL', + 'SQL_BIG_RESULT', + 'SQL_CALC_FOUND_ROWS', + 'SQL_SMALL_RESULT', + 'SQLEXCEPTION', + 'SQLSTATE', + 'SQLWARNING', + 'SSL', + 'STARTING', + 'STRAIGHT_JOIN', + 'TABLE', + 'TERMINATED', + 'THEN', + 'TINYBLOB', + 'TINYINT', + 'TINYTEXT', + 'TO', + 'TRAILING', + 'TRIGGER', + 'TRUE', + 'UNDO', + 'UNION', + 'UNIQUE', + 'UNLOCK', + 'UNSIGNED', + 'UPDATE', + 'USAGE', + 'USE', + 'USING', + 'UTC_DATE', + 'UTC_TIME', + 'UTC_TIMESTAMP', + 'VALUES', + 'VARBINARY', + 'VARCHAR', + 'VARCHARACTER', + 'VARYING', + 'WHEN', + 'WHERE', + 'WHILE', + 'WITH', + 'WRITE', + 'XOR', + 'YEAR_MONTH', + 'ZEROFILL', + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL91Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL91Keywords.php new file mode 100644 index 0000000000..4e5c632d35 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL91Keywords.php @@ -0,0 +1,148 @@ +. + */ + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * PostgreSQL 9.1 reserved keywords list. + * + * @author Martin Hasoň + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class PostgreSQL91Keywords extends PostgreSQLKeywords +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'PostgreSQL91'; + } + + /** + * {@inheritdoc} + * + * @link http://www.postgresql.org/docs/9.1/static/sql-keywords-appendix.html + */ + protected function getKeywords() + { + return array( + 'ALL', + 'ANALYSE', + 'ANALYZE', + 'AND', + 'ANY', + 'ARRAY', + 'AS', + 'ASC', + 'ASYMMETRIC', + 'AUTHORIZATION', + 'BINARY', + 'BOTH', + 'CASE', + 'CAST', + 'CHECK', + 'COLLATE', + 'COLUMN', + 'CONCURRENTLY', + 'CONSTRAINT', + 'CREATE', + 'CROSS', + 'CURRENT_CATALOG', + 'CURRENT_DATE', + 'CURRENT_ROLE', + 'CURRENT_SCHEMA', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'CURRENT_USER', + 'DEFAULT', + 'DEFERRABLE', + 'DESC', + 'DISTINCT', + 'DO', + 'ELSE', + 'END', + 'EXCEPT', + 'FALSE', + 'FETCH', + 'FOR', + 'FOREIGN', + 'FREEZE', + 'FROM', + 'FULL', + 'GRANT', + 'GROUP', + 'HAVING', + 'ILIKE', + 'IN', + 'INITIALLY', + 'INNER', + 'INTERSECT', + 'INTO', + 'IS', + 'ISNULL', + 'JOIN', + 'LEADING', + 'LEFT', + 'LIKE', + 'LIMIT', + 'LOCALTIME', + 'LOCALTIMESTAMP', + 'NATURAL', + 'NOT', + 'NOTNULL', + 'NULL', + 'OFFSET', + 'ON', + 'ONLY', + 'OR', + 'ORDER', + 'OUTER', + 'OVER', + 'OVERLAPS', + 'PLACING', + 'PRIMARY', + 'REFERENCES', + 'RETURNING', + 'RIGHT', + 'SELECT', + 'SESSION_USER', + 'SIMILAR', + 'SOME', + 'SYMMETRIC', + 'TABLE', + 'THEN', + 'TO', + 'TRAILING', + 'TRUE', + 'UNION', + 'UNIQUE', + 'USER', + 'USING', + 'VARIADIC', + 'VERBOSE', + 'WHEN', + 'WHERE', + 'WINDOW', + 'WITH', + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL92Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL92Keywords.php new file mode 100644 index 0000000000..7180dfd983 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL92Keywords.php @@ -0,0 +1,50 @@ +. + */ + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * PostgreSQL 9.2 reserved keywords list. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class PostgreSQL92Keywords extends PostgreSQL91Keywords +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'PostgreSQL92'; + } + + /** + * {@inheritdoc} + * + * @link http://www.postgresql.org/docs/9.2/static/sql-keywords-appendix.html + */ + protected function getKeywords() + { + return array_merge(parent::getKeywords(), array( + 'COLLATION', + )); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php index 248f26b134..e1fdd492d8 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php @@ -72,6 +72,7 @@ class ReservedKeywordsValidator implements Visitor $keywordLists[] = $keywordList->getName(); } } + return $keywordLists; } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php new file mode 100644 index 0000000000..12eacbf9b9 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php @@ -0,0 +1,55 @@ +. + */ + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * SAP Sybase SQL Anywhere 11 reserved keywords list. + * + * @author Steve Müller + */ +class SQLAnywhere11Keywords extends SQLAnywhereKeywords +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'SQLAnywhere11'; + } + + /** + * {@inheritdoc} + * + * @link http://dcx.sybase.com/1100/en/dbreference_en11/alhakeywords.html + */ + protected function getKeywords() + { + return array_merge( + array_diff( + parent::getKeywords(), + array('IQ') + ), + array( + 'MERGE', + 'OPENSTRING' + ) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere12Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere12Keywords.php new file mode 100644 index 0000000000..22e04893e9 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere12Keywords.php @@ -0,0 +1,64 @@ +. + */ + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * SAP Sybase SQL Anywhere 12 reserved keywords list. + * + * @author Steve Müller + */ +class SQLAnywhere12Keywords extends SQLAnywhere11Keywords +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'SQLAnywhere12'; + } + + /** + * {@inheritdoc} + * + * @link http://dcx.sybase.com/1200/en/dbreference/alhakeywords.html + */ + protected function getKeywords() + { + return array_merge( + array_diff( + parent::getKeywords(), + array( + 'INDEX_LPAREN', + 'SYNTAX_ERROR', + 'WITH_CUBE', + 'WITH_LPAREN', + 'WITH_ROLLUP' + ) + ), + array( + 'DATETIMEOFFSET', + 'LIMIT', + 'OPENXML', + 'SPATIAL', + 'TREAT' + ) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere16Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere16Keywords.php new file mode 100644 index 0000000000..4d78b84109 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere16Keywords.php @@ -0,0 +1,56 @@ +. + */ + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * SAP Sybase SQL Anywhere 16 reserved keywords list. + * + * @author Steve Müller + */ +class SQLAnywhere16Keywords extends SQLAnywhere12Keywords +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'SQLAnywhere16'; + } + + /** + * {@inheritdoc} + * + * @link http://dcx.sybase.com/index.html#sa160/en/dbreference/alhakeywords.html + */ + protected function getKeywords() + { + return array_merge( + parent::getKeywords(), + array( + 'ARRAY', + 'JSON', + 'ROW', + 'ROWTYPE', + 'UNNEST', + 'VARRAY' + ) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhereKeywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhereKeywords.php new file mode 100644 index 0000000000..cabf1e4491 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhereKeywords.php @@ -0,0 +1,281 @@ +. + */ + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * SAP Sybase SQL Anywhere 10 reserved keywords list. + * + * @author Steve Müller + */ +class SQLAnywhereKeywords extends KeywordList +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'SQLAnywhere'; + } + + /** + * {@inheritdoc} + * + * @link http://infocenter.sybase.com/help/topic/com.sybase.dbrfen10/pdf/dbrfen10.pdf?noframes=true + */ + protected function getKeywords() + { + return array( + 'ADD', + 'ALL', + 'ALTER', + 'AND', + 'ANY', + 'AS', + 'ASC', + 'ATTACH', + 'BACKUP', + 'BEGIN', + 'BETWEEN', + 'BIGINT', + 'BINARY', + 'BIT', + 'BOTTOM', + 'BREAK', + 'BY', + 'CALL', + 'CAPABILITY', + 'CASCADE', + 'CASE', + 'CAST', + 'CHAR', + 'CHAR_CONVERT', + 'CHARACTER', + 'CHECK', + 'CHECKPOINT', + 'CLOSE', + 'COMMENT', + 'COMMIT', + 'COMPRESSED', + 'CONFLICT', + 'CONNECT', + 'CONSTRAINT', + 'CONTAINS', + 'CONTINUE', + 'CONVERT', + 'CREATE', + 'CROSS', + 'CUBE', + 'CURRENT', + 'CURRENT_TIMESTAMP', + 'CURRENT_USER', + 'CURSOR', + 'DATE', + 'DBSPACE', + 'DEALLOCATE', + 'DEC', + 'DECIMAL', + 'DECLARE', + 'DEFAULT', + 'DELETE', + 'DELETING', + 'DESC', + 'DETACH', + 'DISTINCT', + 'DO', + 'DOUBLE', + 'DROP', + 'DYNAMIC', + 'ELSE', + 'ELSEIF', + 'ENCRYPTED', + 'END', + 'ENDIF', + 'ESCAPE', + 'EXCEPT', + 'EXCEPTION', + 'EXEC', + 'EXECUTE', + 'EXISTING', + 'EXISTS', + 'EXTERNLOGIN', + 'FETCH', + 'FIRST', + 'FLOAT', + 'FOR', + 'FORCE', + 'FOREIGN', + 'FORWARD', + 'FROM', + 'FULL', + 'GOTO', + 'GRANT', + 'GROUP', + 'HAVING', + 'HOLDLOCK', + 'IDENTIFIED', + 'IF', + 'IN', + 'INDEX', + 'INDEX_LPAREN', + 'INNER', + 'INOUT', + 'INSENSITIVE', + 'INSERT', + 'INSERTING', + 'INSTALL', + 'INSTEAD', + 'INT', + 'INTEGER', + 'INTEGRATED', + 'INTERSECT', + 'INTO', + 'IQ', + 'IS', + 'ISOLATION', + 'JOIN', + 'KERBEROS', + 'KEY', + 'LATERAL', + 'LEFT', + 'LIKE', + 'LOCK', + 'LOGIN', + 'LONG', + 'MATCH', + 'MEMBERSHIP', + 'MESSAGE', + 'MODE', + 'MODIFY', + 'NATURAL', + 'NCHAR', + 'NEW', + 'NO', + 'NOHOLDLOCK', + 'NOT', + 'NOTIFY', + 'NULL', + 'NUMERIC', + 'NVARCHAR', + 'OF', + 'OFF', + 'ON', + 'OPEN', + 'OPTION', + 'OPTIONS', + 'OR', + 'ORDER', + 'OTHERS', + 'OUT', + 'OUTER', + 'OVER', + 'PASSTHROUGH', + 'PRECISION', + 'PREPARE', + 'PRIMARY', + 'PRINT', + 'PRIVILEGES', + 'PROC', + 'PROCEDURE', + 'PUBLICATION', + 'RAISERROR', + 'READTEXT', + 'REAL', + 'REFERENCE', + 'REFERENCES', + 'REFRESH', + 'RELEASE', + 'REMOTE', + 'REMOVE', + 'RENAME', + 'REORGANIZE', + 'RESOURCE', + 'RESTORE', + 'RESTRICT', + 'RETURN', + 'REVOKE', + 'RIGHT', + 'ROLLBACK', + 'ROLLUP', + 'SAVE', + 'SAVEPOINT', + 'SCROLL', + 'SELECT', + 'SENSITIVE', + 'SESSION', + 'SET', + 'SETUSER', + 'SHARE', + 'SMALLINT', + 'SOME', + 'SQLCODE', + 'SQLSTATE', + 'START', + 'STOP', + 'SUBTRANS', + 'SUBTRANSACTION', + 'SYNCHRONIZE', + 'SYNTAX_ERROR', + 'TABLE', + 'TEMPORARY', + 'THEN', + 'TIME', + 'TIMESTAMP', + 'TINYINT', + 'TO', + 'TOP', + 'TRAN', + 'TRIGGER', + 'TRUNCATE', + 'TSEQUAL', + 'UNBOUNDED', + 'UNION', + 'UNIQUE', + 'UNIQUEIDENTIFIER', + 'UNKNOWN', + 'UNSIGNED', + 'UPDATE', + 'UPDATING', + 'USER', + 'USING', + 'VALIDATE', + 'VALUES', + 'VARBINARY', + 'VARBIT', + 'VARCHAR', + 'VARIABLE', + 'VARYING', + 'VIEW', + 'WAIT', + 'WAITFOR', + 'WHEN', + 'WHERE', + 'WHILE', + 'WINDOW', + 'WITH', + 'WITH_CUBE', + 'WITH_LPAREN', + 'WITH_ROLLUP', + 'WITHIN', + 'WORK', + 'WRITETEXT', + 'XML' + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php new file mode 100644 index 0000000000..36b525e206 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php @@ -0,0 +1,67 @@ +. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\TableDiff; + +/** + * Provides the behavior, features and SQL dialect of the MySQL 5.7 database platform. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class MySQL57Platform extends MySqlPlatform +{ + /** + * {@inheritdoc} + */ + protected function getPreAlterTableRenameIndexForeignKeySQL(TableDiff $diff) + { + return array(); + } + + /** + * {@inheritdoc} + */ + protected function getPostAlterTableRenameIndexForeignKeySQL(TableDiff $diff) + { + return array(); + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + return array( + 'ALTER TABLE ' . $tableName . ' RENAME INDEX ' . $oldIndexName . ' TO ' . $index->getQuotedName($this) + ); + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\MySQL57Keywords'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php index 1230c9b794..e22851b95a 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php @@ -19,10 +19,12 @@ namespace Doctrine\DBAL\Platforms; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Types\BlobType; +use Doctrine\DBAL\Types\TextType; /** * The MySqlPlatform provides the behavior, features and SQL dialect of the @@ -104,63 +106,26 @@ class MySqlPlatform extends AbstractPlatform public function getConcatExpression() { $args = func_get_args(); - return 'CONCAT(' . join(', ', (array) $args) . ')'; - } - - /** - * {@inheritDoc} - */ - public function getDateDiffExpression($date1, $date2) - { - return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; - } - - /** - * {@inheritDoc} - */ - public function getDateAddHourExpression($date, $hours) - { - return 'DATE_ADD(' . $date . ', INTERVAL ' . $hours . ' HOUR)'; - } - - /** - * {@inheritDoc} - */ - public function getDateSubHourExpression($date, $hours) - { - return 'DATE_SUB(' . $date . ', INTERVAL ' . $hours . ' HOUR)'; - } - /** - * {@inheritDoc} - */ - public function getDateAddDaysExpression($date, $days) - { - return 'DATE_ADD(' . $date . ', INTERVAL ' . $days . ' DAY)'; + return 'CONCAT(' . join(', ', (array) $args) . ')'; } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getDateSubDaysExpression($date, $days) + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { - return 'DATE_SUB(' . $date . ', INTERVAL ' . $days . ' DAY)'; - } + $function = '+' === $operator ? 'DATE_ADD' : 'DATE_SUB'; - /** - * {@inheritDoc} - */ - public function getDateAddMonthExpression($date, $months) - { - return 'DATE_ADD(' . $date . ', INTERVAL ' . $months . ' MONTH)'; + return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')'; } /** * {@inheritDoc} */ - public function getDateSubMonthExpression($date, $months) + public function getDateDiffExpression($date1, $date2) { - return 'DATE_SUB(' . $date . ', INTERVAL ' . $months . ' MONTH)'; + return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; } /** @@ -252,6 +217,14 @@ class MySqlPlatform extends AbstractPlatform : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); } + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; + } + /** * Gets the SQL snippet used to declare a CLOB column type. * TINYTEXT : 2 ^ 8 - 1 = 255 @@ -324,14 +297,16 @@ class MySqlPlatform extends AbstractPlatform * Obtain DBMS specific SQL code portion needed to set the COLLATION * of a field declaration to be used in statements like CREATE TABLE. * - * @param string $collation name of the collation + * @deprecated Deprecated since version 2.5, Use {@link self::getColumnCollationDeclarationSQL()} instead. + * + * @param string $collation name of the collation * * @return string DBMS specific SQL code portion needed to set the COLLATION * of a field declaration. */ public function getCollationFieldDeclaration($collation) { - return 'COLLATE ' . $collation; + return $this->getColumnCollationDeclarationSQL($collation); } /** @@ -366,6 +341,11 @@ class MySqlPlatform extends AbstractPlatform /** * {@inheritDoc} */ + public function supportsColumnCollation() + { + return true; + } + public function getListTablesSQL() { return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"; @@ -377,13 +357,15 @@ class MySqlPlatform extends AbstractPlatform public function getListTableColumnsSQL($table, $database = null) { if ($database) { - return "SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ". - "COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, " . - "CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS CollactionName ". - "FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '" . $database . "' AND TABLE_NAME = '" . $table . "'"; + $database = "'" . $database . "'"; + } else { + $database = 'DATABASE()'; } - return 'DESCRIBE ' . $table; + return "SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ". + "COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, " . + "CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS Collation ". + "FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = " . $database . " AND TABLE_NAME = '" . $table . "'"; } /** @@ -417,7 +399,7 @@ class MySqlPlatform extends AbstractPlatform // add all indexes if (isset($options['indexes']) && ! empty($options['indexes'])) { - foreach($options['indexes'] as $index => $definition) { + foreach ($options['indexes'] as $index => $definition) { $queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition); } } @@ -438,9 +420,15 @@ class MySqlPlatform extends AbstractPlatform $query .= $this->buildTableOptions($options); $query .= $this->buildPartitionOptions($options); - $sql[] = $query; + $sql[] = $query; + $engine = 'INNODB'; + + if (isset($options['engine'])) { + $engine = strtoupper(trim($options['engine'])); + } - if (isset($options['foreignKeys'])) { + // Propagate foreign key constraints only for InnoDB. + if (isset($options['foreignKeys']) && $engine === 'INNODB') { foreach ((array) $options['foreignKeys'] as $definition) { $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); } @@ -449,6 +437,19 @@ class MySqlPlatform extends AbstractPlatform return $sql; } + /** + * {@inheritdoc} + */ + public function getDefaultValueDeclarationSQL($field) + { + // Unset the default value if the given field definition does not allow default values. + if ($field['type'] instanceof TextType || $field['type'] instanceof BlobType) { + $field['default'] = null; + } + + return parent::getDefaultValueDeclarationSQL($field); + } + /** * Build SQL for table options * @@ -494,7 +495,7 @@ class MySqlPlatform extends AbstractPlatform if (isset($options['comment'])) { $comment = trim($options['comment'], " '"); - $tableOptions[] = sprintf("COMMENT = '%s' ", str_replace("'", "''", $comment)); + $tableOptions[] = sprintf("COMMENT = %s ", $this->quoteStringLiteral($comment)); } // Row format @@ -527,7 +528,7 @@ class MySqlPlatform extends AbstractPlatform $columnSql = array(); $queryParts = array(); if ($diff->newName !== false) { - $queryParts[] = 'RENAME TO ' . $diff->newName; + $queryParts[] = 'RENAME TO ' . $diff->getNewName()->getQuotedName($this); } foreach ($diff->addedColumns as $column) { @@ -556,6 +557,15 @@ class MySqlPlatform extends AbstractPlatform /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ $column = $columnDiff->column; $columnArray = $column->toArray(); + + // Don't propagate default value changes for unsupported column types. + if ($columnDiff->hasChanged('default') && + count($columnDiff->changedProperties) === 1 && + ($columnArray['type'] instanceof TextType || $columnArray['type'] instanceof BlobType) + ) { + continue; + } + $columnArray['comment'] = $this->getColumnComment($column); $queryParts[] = 'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); @@ -566,9 +576,10 @@ class MySqlPlatform extends AbstractPlatform continue; } + $oldColumnName = new Identifier($oldColumnName); $columnArray = $column->toArray(); $columnArray['comment'] = $this->getColumnComment($column); - $queryParts[] = 'CHANGE ' . $oldColumnName . ' ' + $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); } @@ -583,7 +594,7 @@ class MySqlPlatform extends AbstractPlatform if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if (count($queryParts) > 0) { - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts); + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(", ", $queryParts); } $sql = array_merge( $this->getPreAlterTableIndexForeignKeySQL($diff), @@ -601,7 +612,7 @@ class MySqlPlatform extends AbstractPlatform protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) { $sql = array(); - $table = $diff->name; + $table = $diff->getName($this)->getQuotedName($this); foreach ($diff->removedIndexes as $remKey => $remIndex) { // Dropping primary keys requires to unset autoincrement attribute on the particular column first. @@ -614,6 +625,9 @@ class MySqlPlatform extends AbstractPlatform $sql[] = 'ALTER TABLE ' . $table . ' MODIFY ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + + // original autoincrement information might be needed later on by other parts of the table alteration + $column->setAutoincrement(true); } } } @@ -643,7 +657,148 @@ class MySqlPlatform extends AbstractPlatform } } - $sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff)); + $engine = 'INNODB'; + + if ($diff->fromTable instanceof Table && $diff->fromTable->hasOption('engine')) { + $engine = strtoupper(trim($diff->fromTable->getOption('engine'))); + } + + // Suppress foreign key constraint propagation on non-supporting engines. + if ('INNODB' !== $engine) { + $diff->addedForeignKeys = array(); + $diff->changedForeignKeys = array(); + $diff->removedForeignKeys = array(); + } + + $sql = array_merge( + $sql, + $this->getPreAlterTableAlterIndexForeignKeySQL($diff), + parent::getPreAlterTableIndexForeignKeySQL($diff), + $this->getPreAlterTableRenameIndexForeignKeySQL($diff) + ); + + return $sql; + } + + /** + * @param TableDiff $diff The table diff to gather the SQL for. + * + * @return array + */ + private function getPreAlterTableAlterIndexForeignKeySQL(TableDiff $diff) + { + $sql = array(); + $table = $diff->getName($this)->getQuotedName($this); + + foreach ($diff->changedIndexes as $changedIndex) { + // Changed primary key + if ($changedIndex->isPrimary() && $diff->fromTable instanceof Table) { + foreach ($diff->fromTable->getPrimaryKeyColumns() as $columnName) { + $column = $diff->fromTable->getColumn($columnName); + + // Check if an autoincrement column was dropped from the primary key. + if ($column->getAutoincrement() && ! in_array($columnName, $changedIndex->getColumns())) { + // The autoincrement attribute needs to be removed from the dropped column + // before we can drop and recreate the primary key. + $column->setAutoincrement(false); + + $sql[] = 'ALTER TABLE ' . $table . ' MODIFY ' . + $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + + // Restore the autoincrement attribute as it might be needed later on + // by other parts of the table alteration. + $column->setAutoincrement(true); + } + } + } + } + + return $sql; + } + + /** + * @param TableDiff $diff The table diff to gather the SQL for. + * + * @return array + */ + protected function getPreAlterTableRenameIndexForeignKeySQL(TableDiff $diff) + { + $sql = array(); + $tableName = $diff->getName($this)->getQuotedName($this); + + foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) { + if (! in_array($foreignKey, $diff->changedForeignKeys, true)) { + $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); + } + } + + return $sql; + } + + /** + * Returns the remaining foreign key constraints that require one of the renamed indexes. + * + * "Remaining" here refers to the diff between the foreign keys currently defined in the associated + * table and the foreign keys to be removed. + * + * @param TableDiff $diff The table diff to evaluate. + * + * @return array + */ + private function getRemainingForeignKeyConstraintsRequiringRenamedIndexes(TableDiff $diff) + { + if (empty($diff->renamedIndexes) || ! $diff->fromTable instanceof Table) { + return array(); + } + + $foreignKeys = array(); + /** @var \Doctrine\DBAL\Schema\ForeignKeyConstraint[] $remainingForeignKeys */ + $remainingForeignKeys = array_diff_key( + $diff->fromTable->getForeignKeys(), + $diff->removedForeignKeys + ); + + foreach ($remainingForeignKeys as $foreignKey) { + foreach ($diff->renamedIndexes as $index) { + if ($foreignKey->intersectsIndexColumns($index)) { + $foreignKeys[] = $foreignKey; + + break; + } + } + } + + return $foreignKeys; + } + + /** + * {@inheritdoc} + */ + protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) + { + return array_merge( + parent::getPostAlterTableIndexForeignKeySQL($diff), + $this->getPostAlterTableRenameIndexForeignKeySQL($diff) + ); + } + + /** + * @param TableDiff $diff The table diff to gather the SQL for. + * + * @return array + */ + protected function getPostAlterTableRenameIndexForeignKeySQL(TableDiff $diff) + { + $sql = array(); + $tableName = (false !== $diff->newName) + ? $diff->getNewName()->getQuotedName($this) + : $diff->getName($this)->getQuotedName($this); + + foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) { + if (! in_array($foreignKey, $diff->changedForeignKeys, true)) { + $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); + } + } return $sql; } @@ -656,8 +811,10 @@ class MySqlPlatform extends AbstractPlatform $type = ''; if ($index->isUnique()) { $type .= 'UNIQUE '; - } else if ($index->hasFlag('fulltext')) { + } elseif ($index->hasFlag('fulltext')) { $type .= 'FULLTEXT '; + } elseif ($index->hasFlag('spatial')) { + $type .= 'SPATIAL '; } return $type; @@ -711,6 +868,7 @@ class MySqlPlatform extends AbstractPlatform $query .= ' MATCH ' . $foreignKey->getOption('match'); } $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); + return $query; } @@ -721,7 +879,7 @@ class MySqlPlatform extends AbstractPlatform { if ($index instanceof Index) { $indexName = $index->getQuotedName($this); - } else if(is_string($index)) { + } elseif (is_string($index)) { $indexName = $index; } else { throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); @@ -729,7 +887,7 @@ class MySqlPlatform extends AbstractPlatform if ($table instanceof Table) { $table = $table->getQuotedName($this); - } else if(!is_string($table)) { + } elseif (!is_string($table)) { throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } @@ -809,8 +967,8 @@ class MySqlPlatform extends AbstractPlatform 'blob' => 'blob', 'mediumblob' => 'blob', 'tinyblob' => 'blob', - 'binary' => 'blob', - 'varbinary' => 'blob', + 'binary' => 'binary', + 'varbinary' => 'binary', 'set' => 'simple_array', ); } @@ -823,6 +981,14 @@ class MySqlPlatform extends AbstractPlatform return 65535; } + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 65535; + } + /** * {@inheritDoc} */ @@ -841,7 +1007,7 @@ class MySqlPlatform extends AbstractPlatform { if ($table instanceof Table) { $table = $table->getQuotedName($this); - } else if(!is_string($table)) { + } elseif (!is_string($table)) { throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php index c532d082b5..a58c747e92 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php @@ -20,11 +20,13 @@ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Schema\ForeignKeyConstraint; +use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Types\BinaryType; /** * OraclePlatform. @@ -99,47 +101,61 @@ class OraclePlatform extends AbstractPlatform } /** - * {@inheritDoc} - * - * Note: Since Oracle timestamp differences are calculated down to the microsecond we have to truncate - * them to the difference in days. This is obviously a restriction of the original functionality, but we - * need to make this a portable function. + * {@inheritdoc} */ - public function getDateDiffExpression($date1, $date2) + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { - return "TRUNC(TO_NUMBER(SUBSTR((" . $date1 . "-" . $date2 . "), 1, INSTR(" . $date1 . "-" . $date2 .", ' '))))"; - } + switch ($unit) { + case self::DATE_INTERVAL_UNIT_MONTH: + case self::DATE_INTERVAL_UNIT_QUARTER: + case self::DATE_INTERVAL_UNIT_YEAR: + switch ($unit) { + case self::DATE_INTERVAL_UNIT_QUARTER: + $interval *= 3; + break; - /** - * {@inheritDoc} - */ - public function getDateAddDaysExpression($date, $days) - { - return '(' . $date . '+' . $days . ')'; - } + case self::DATE_INTERVAL_UNIT_YEAR: + $interval *= 12; + break; + } - /** - * {@inheritDoc} - */ - public function getDateSubDaysExpression($date, $days) - { - return '(' . $date . '-' . $days . ')'; - } + return 'ADD_MONTHS(' . $date . ', ' . $operator . $interval . ')'; - /** - * {@inheritDoc} - */ - public function getDateAddMonthExpression($date, $months) - { - return "ADD_MONTHS(" . $date . ", " . $months . ")"; + default: + $calculationClause = ''; + + switch ($unit) { + case self::DATE_INTERVAL_UNIT_SECOND: + $calculationClause = '/24/60/60'; + break; + + case self::DATE_INTERVAL_UNIT_MINUTE: + $calculationClause = '/24/60'; + break; + + case self::DATE_INTERVAL_UNIT_HOUR: + $calculationClause = '/24'; + break; + + case self::DATE_INTERVAL_UNIT_WEEK: + $calculationClause = '*7'; + break; + } + + return '(' . $date . $operator . $interval . $calculationClause . ')'; + } } /** * {@inheritDoc} + * + * Note: Since Oracle timestamp differences are calculated down to the microsecond we have to truncate + * them to the difference in days. This is obviously a restriction of the original functionality, but we + * need to make this a portable function. */ - public function getDateSubMonthExpression($date, $months) + public function getDateDiffExpression($date1, $date2) { - return "ADD_MONTHS(" . $date . ", -" . $months . ")"; + return "TRUNC(TO_NUMBER(SUBSTR((" . $date1 . "-" . $date2 . "), 1, INSTR(" . $date1 . "-" . $date2 .", ' '))))"; } /** @@ -172,16 +188,38 @@ class OraclePlatform extends AbstractPlatform return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . ' START WITH ' . $sequence->getInitialValue() . ' MINVALUE ' . $sequence->getInitialValue() . - ' INCREMENT BY ' . $sequence->getAllocationSize(); + ' INCREMENT BY ' . $sequence->getAllocationSize() . + $this->getSequenceCacheSQL($sequence); } /** * {@inheritDoc} */ - public function getAlterSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence) + public function getAlterSequenceSQL(Sequence $sequence) { return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . - ' INCREMENT BY ' . $sequence->getAllocationSize(); + ' INCREMENT BY ' . $sequence->getAllocationSize() + . $this->getSequenceCacheSQL($sequence); + } + + /** + * Cache definition for sequences + * + * @param Sequence $sequence + * + * @return string + */ + private function getSequenceCacheSQL(Sequence $sequence) + { + if ($sequence->getCache() === 0) { + return ' NOCACHE'; + } else if ($sequence->getCache() === 1) { + return ' NOCACHE'; + } else if ($sequence->getCache() > 1) { + return ' CACHE ' . $sequence->getCache(); + } + + return ''; } /** @@ -299,6 +337,22 @@ class OraclePlatform extends AbstractPlatform : ($length ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)'); } + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return 'RAW(' . ($length ?: $this->getBinaryMaxLength()) . ')'; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 2000; + } + /** * {@inheritDoc} */ @@ -320,8 +374,10 @@ class OraclePlatform extends AbstractPlatform */ public function getListSequencesSQL($database) { + $database = $this->normalizeIdentifier($database); + return "SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ". - "WHERE SEQUENCE_OWNER = '".strtoupper($database)."'"; + "WHERE SEQUENCE_OWNER = '" . $database->getName() . "'"; } /** @@ -361,7 +417,7 @@ class OraclePlatform extends AbstractPlatform */ public function getListTableIndexesSQL($table, $currentDatabase = null) { - $table = strtoupper($table); + $table = $this->normalizeIdentifier($table); return "SELECT uind.index_name AS name, " . " uind.index_type AS type, " . @@ -370,7 +426,8 @@ class OraclePlatform extends AbstractPlatform " uind_col.column_position AS column_pos, " . " (SELECT ucon.constraint_type FROM user_constraints ucon WHERE ucon.constraint_name = uind.index_name) AS is_primary ". "FROM user_indexes uind, user_ind_columns uind_col " . - "WHERE uind.index_name = uind_col.index_name AND uind_col.table_name = '$table' ORDER BY uind_col.column_position ASC"; + "WHERE uind.index_name = uind_col.index_name AND uind_col.table_name = '" . $table->getName() . "' " . + "ORDER BY uind_col.column_position ASC"; } /** @@ -414,45 +471,52 @@ class OraclePlatform extends AbstractPlatform */ public function getCreateAutoincrementSql($name, $table, $start = 1) { - $table = strtoupper($table); - $name = strtoupper($name); + $tableIdentifier = $this->normalizeIdentifier($table); + $quotedTableName = $tableIdentifier->getQuotedName($this); + $unquotedTableName = $tableIdentifier->getName(); - $sql = array(); + $nameIdentifier = $this->normalizeIdentifier($name); + $quotedName = $nameIdentifier->getQuotedName($this); + $unquotedName = $nameIdentifier->getName(); + + $sql = array(); - $indexName = $table . '_AI_PK'; + $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($tableIdentifier); - $idx = new Index($indexName, array($name), true, true); + $idx = new Index($autoincrementIdentifierName, array($quotedName), true, true); $sql[] = 'DECLARE constraints_Count NUMBER; BEGIN - SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \''.$table.'\' AND CONSTRAINT_TYPE = \'P\'; + SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \'' . $unquotedTableName . '\' AND CONSTRAINT_TYPE = \'P\'; IF constraints_Count = 0 OR constraints_Count = \'\' THEN - EXECUTE IMMEDIATE \''.$this->getCreateConstraintSQL($idx, $table).'\'; + EXECUTE IMMEDIATE \''.$this->getCreateConstraintSQL($idx, $quotedTableName).'\'; END IF; END;'; - $sequenceName = $table . '_' . $name . '_SEQ'; + $sequenceName = $this->getIdentitySequenceName( + $tableIdentifier->isQuoted() ? $quotedTableName : $unquotedTableName, + $nameIdentifier->isQuoted() ? $quotedName : $unquotedName + ); $sequence = new Sequence($sequenceName, $start); $sql[] = $this->getCreateSequenceSQL($sequence); - $triggerName = $table . '_AI_PK'; - $sql[] = 'CREATE TRIGGER ' . $triggerName . ' + $sql[] = 'CREATE TRIGGER ' . $autoincrementIdentifierName . ' BEFORE INSERT - ON ' . $table . ' + ON ' . $quotedTableName . ' FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN - SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL; - IF (:NEW.' . $name . ' IS NULL OR :NEW.'.$name.' = 0) THEN - SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL; + SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL; + IF (:NEW.' . $quotedName . ' IS NULL OR :NEW.'.$quotedName.' = 0) THEN + SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL; ELSE SELECT NVL(Last_Number, 0) INTO last_Sequence FROM User_Sequences - WHERE Sequence_Name = \'' . $sequenceName . '\'; - SELECT :NEW.' . $name . ' INTO last_InsertID FROM DUAL; + WHERE Sequence_Name = \'' . $sequence->getName() . '\'; + SELECT :NEW.' . $quotedName . ' INTO last_InsertID FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP SELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL; END LOOP; @@ -463,22 +527,62 @@ END;'; } /** - * @param string $table + * Returns the SQL statements to drop the autoincrement for the given table name. + * + * @param string $table The table name to drop the autoincrement for. * * @return array */ public function getDropAutoincrementSql($table) { - $table = strtoupper($table); - $trigger = $table . '_AI_PK'; + $table = $this->normalizeIdentifier($table); + $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($table); + $identitySequenceName = $this->getIdentitySequenceName( + $table->isQuoted() ? $table->getQuotedName($this) : $table->getName(), + '' + ); - $sql[] = 'DROP TRIGGER ' . $trigger; - $sql[] = $this->getDropSequenceSQL($table.'_SEQ'); + return array( + 'DROP TRIGGER ' . $autoincrementIdentifierName, + $this->getDropSequenceSQL($identitySequenceName), + $this->getDropConstraintSQL($autoincrementIdentifierName, $table->getQuotedName($this)), + ); + } - $indexName = $table . '_AI_PK'; - $sql[] = $this->getDropConstraintSQL($indexName, $table); + /** + * Normalizes the given identifier. + * + * Uppercases the given identifier if it is not quoted by intention + * to reflect Oracle's internal auto uppercasing strategy of unquoted identifiers. + * + * @param string $name The identifier to normalize. + * + * @return Identifier The normalized identifier. + */ + private function normalizeIdentifier($name) + { + $identifier = new Identifier($name); - return $sql; + return $identifier->isQuoted() ? $identifier : new Identifier(strtoupper($name)); + } + + /** + * Returns the autoincrement primary key identifier name for the given table identifier. + * + * Quotes the autoincrement primary key identifier name + * if the given table name is quoted by intention. + * + * @param Identifier $table The table identifier to return the autoincrement primary key identifier name for. + * + * @return string + */ + private function getAutoincrementIdentifierName(Identifier $table) + { + $identifierName = $table->getName() . '_AI_PK'; + + return $table->isQuoted() + ? $this->quoteSingleIdentifier($identifierName) + : $identifierName; } /** @@ -486,7 +590,7 @@ END;'; */ public function getListTableForeignKeysSQL($table) { - $table = strtoupper($table); + $table = $table = $this->normalizeIdentifier($table); return "SELECT alc.constraint_name, alc.DELETE_RULE, @@ -505,7 +609,7 @@ LEFT JOIN user_cons_columns r_cols AND cols.position = r_cols.position WHERE alc.constraint_name = cols.constraint_name AND alc.constraint_type = 'R' - AND alc.table_name = '".$table."' + AND alc.table_name = '" . $table->getName() . "' ORDER BY alc.constraint_name ASC, cols.position ASC"; } @@ -514,8 +618,9 @@ LEFT JOIN user_cons_columns r_cols */ public function getListTableConstraintsSQL($table) { - $table = strtoupper($table); - return 'SELECT * FROM user_constraints WHERE table_name = \'' . $table . '\''; + $table = $this->normalizeIdentifier($table); + + return "SELECT * FROM user_constraints WHERE table_name = '" . $table->getName() . "'"; } /** @@ -523,20 +628,22 @@ LEFT JOIN user_cons_columns r_cols */ public function getListTableColumnsSQL($table, $database = null) { - $table = strtoupper($table); + $table = $this->normalizeIdentifier($table); $tabColumnsTableName = "user_tab_columns"; + $colCommentsTableName = "user_col_comments"; $ownerCondition = ''; - if (null !== $database){ - $database = strtoupper($database); + if (null !== $database) { + $database = $this->normalizeIdentifier($database); $tabColumnsTableName = "all_tab_columns"; - $ownerCondition = "AND c.owner = '".$database."'"; + $colCommentsTableName = "all_col_comments"; + $ownerCondition = "AND c.owner = '" . $database->getName() . "'"; } return "SELECT c.*, d.comments FROM $tabColumnsTableName c ". - "INNER JOIN user_col_comments d ON d.TABLE_NAME = c.TABLE_NAME AND d.COLUMN_NAME = c.COLUMN_NAME ". - "WHERE c.table_name = '" . $table . "' ".$ownerCondition." ORDER BY c.column_name"; + "INNER JOIN " . $colCommentsTableName . " d ON d.TABLE_NAME = c.TABLE_NAME AND d.COLUMN_NAME = c.COLUMN_NAME ". + "WHERE c.table_name = '" . $table->getName() . "' ".$ownerCondition." ORDER BY c.column_name"; } /** @@ -631,12 +738,16 @@ LEFT JOIN user_cons_columns r_cols $fields[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); if ($comment = $this->getColumnComment($column)) { - $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $comment + ); } } if (count($fields)) { - $sql[] = 'ALTER TABLE ' . $diff->name . ' ADD (' . implode(', ', $fields) . ')'; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ADD (' . implode(', ', $fields) . ')'; } $fields = array(); @@ -645,7 +756,19 @@ LEFT JOIN user_cons_columns r_cols continue; } + /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ $column = $columnDiff->column; + + // Do not generate column alteration clause if type is binary and only fixed property has changed. + // Oracle only supports binary type columns with variable length. + // Avoids unnecessary table alteration statements. + if ($column->getType() instanceof BinaryType && + $columnDiff->hasChanged('fixed') && + count($columnDiff->changedProperties) === 1 + ) { + continue; + } + $columnHasChangedComment = $columnDiff->hasChanged('comment'); /** @@ -655,23 +778,23 @@ LEFT JOIN user_cons_columns r_cols $columnInfo = $column->toArray(); if ( ! $columnDiff->hasChanged('notnull')) { - $columnInfo['notnull'] = false; + unset($columnInfo['notnull']); } - $fields[] = $column->getQuotedName($this) . ' ' . $this->getColumnDeclarationSQL('', $columnInfo); + $fields[] = $column->getQuotedName($this) . $this->getColumnDeclarationSQL('', $columnInfo); } if ($columnHasChangedComment) { $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->name, - $column->getName(), + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), $this->getColumnComment($column) ); } } if (count($fields)) { - $sql[] = 'ALTER TABLE ' . $diff->name . ' MODIFY (' . implode(', ', $fields) . ')'; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' MODIFY (' . implode(', ', $fields) . ')'; } foreach ($diff->renamedColumns as $oldColumnName => $column) { @@ -679,7 +802,10 @@ LEFT JOIN user_cons_columns r_cols continue; } - $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName .' TO ' . $column->getQuotedName($this); + $oldColumnName = new Identifier($oldColumnName); + + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . + ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) .' TO ' . $column->getQuotedName($this); } $fields = array(); @@ -692,22 +818,70 @@ LEFT JOIN user_cons_columns r_cols } if (count($fields)) { - $sql[] = 'ALTER TABLE ' . $diff->name . ' DROP (' . implode(', ', $fields).')'; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' DROP (' . implode(', ', $fields).')'; } $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { + $sql = array_merge($sql, $commentsSQL); + if ($diff->newName !== false) { - $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' RENAME TO ' . $diff->getNewName()->getQuotedName($this); } - $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSQL); + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); } return array_merge($sql, $tableSql, $columnSql); } + /** + * {@inheritdoc} + */ + public function getColumnDeclarationSQL($name, array $field) + { + if (isset($field['columnDefinition'])) { + $columnDef = $this->getCustomTypeDeclarationSQL($field); + } else { + $default = $this->getDefaultValueDeclarationSQL($field); + + $notnull = ''; + + if (isset($field['notnull'])) { + $notnull = $field['notnull'] ? ' NOT NULL' : ' NULL'; + } + + $unique = (isset($field['unique']) && $field['unique']) ? + ' ' . $this->getUniqueFieldDeclarationSQL() : ''; + + $check = (isset($field['check']) && $field['check']) ? + ' ' . $field['check'] : ''; + + $typeDecl = $field['type']->getSqlDeclaration($field, $this); + $columnDef = $typeDecl . $default . $notnull . $unique . $check; + } + + return $name . ' ' . $columnDef; + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + if (strpos($tableName, '.') !== false) { + list($schema) = explode('.', $tableName); + $oldIndexName = $schema . '.' . $oldIndexName; + } + + return array('ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)); + } + /** * {@inheritDoc} */ @@ -716,6 +890,33 @@ LEFT JOIN user_cons_columns r_cols return true; } + /** + * {@inheritdoc} + */ + public function usesSequenceEmulatedIdentityColumns() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getIdentitySequenceName($tableName, $columnName) + { + $table = new Identifier($tableName); + + // No usage of column name to preserve BC compatibility with <2.5 + $identitySequenceName = $table->getName() . '_SEQ'; + + if ($table->isQuoted()) { + $identitySequenceName = '"' . $identitySequenceName . '"'; + } + + $identitySequenceIdentifier = $this->normalizeIdentifier($identitySequenceName); + + return $identitySequenceIdentifier->getQuotedName($this); + } + /** * {@inheritDoc} */ @@ -883,11 +1084,13 @@ LEFT JOIN user_cons_columns r_cols 'timestamp' => 'datetime', 'timestamptz' => 'datetimetz', 'float' => 'float', + 'binary_float' => 'float', + 'binary_double' => 'float', 'long' => 'string', 'clob' => 'text', 'nclob' => 'text', - 'raw' => 'text', - 'long raw' => 'text', + 'raw' => 'binary', + 'long raw' => 'blob', 'rowid' => 'string', 'urowid' => 'string', 'blob' => 'blob', diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php new file mode 100644 index 0000000000..b14aa7301e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php @@ -0,0 +1,65 @@ +. + */ + +namespace Doctrine\DBAL\Platforms; + +/** + * Provides the behavior, features and SQL dialect of the PostgreSQL 9.1 database platform. + * + * @author Martin Hasoň + * @link www.doctrine-project.org + * @since 2.5 + */ +class PostgreSQL91Platform extends PostgreSqlPlatform +{ + /** + * {@inheritDoc} + */ + public function supportsColumnCollation() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL91Keywords'; + } + + /** + * {@inheritDoc} + */ + public function getColumnCollationDeclarationSQL($collation) + { + return 'COLLATE ' . $this->quoteSingleIdentifier($collation); + } + + /** + * {@inheritDoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + $sql = parent::getListTableColumnsSQL($table, $database); + $parts = explode('AS complete_type,', $sql, 2); + + return $parts[0].'AS complete_type, (SELECT tc.collcollate FROM pg_catalog.pg_collation tc WHERE tc.oid = a.attcollation) AS collation,'.$parts[1]; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php new file mode 100644 index 0000000000..19cf803563 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php @@ -0,0 +1,83 @@ +. + */ + +namespace Doctrine\DBAL\Platforms; + +/** + * Provides the behavior, features and SQL dialect of the PostgreSQL 9.2 database platform. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class PostgreSQL92Platform extends PostgreSQL91Platform +{ + /** + * {@inheritdoc} + */ + public function getJsonTypeDeclarationSQL(array $field) + { + return 'JSON'; + } + + /** + * {@inheritdoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + if ( ! empty($field['autoincrement'])) { + return 'SMALLSERIAL'; + } + + return parent::getSmallIntTypeDeclarationSQL($field); + } + + /** + * {@inheritdoc} + */ + public function hasNativeJsonType() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL92Keywords'; + } + + /** + * {@inheritdoc} + */ + protected function initializeDoctrineTypeMappings() + { + parent::initializeDoctrineTypeMappings(); + $this->doctrineTypeMapping['json'] = 'json_array'; + } + + /** + * {@inheritdoc} + */ + public function getCloseActiveDatabaseConnectionsSQL($database) + { + return "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$database'"; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php index a30dd2309c..681eb59f0d 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php @@ -19,7 +19,14 @@ namespace Doctrine\DBAL\Platforms; +use Doctrine\DBAL\Schema\Column; +use Doctrine\DBAL\Schema\ColumnDiff; +use Doctrine\DBAL\Schema\Identifier; +use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\TableDiff; +use Doctrine\DBAL\Types\BinaryType; +use Doctrine\DBAL\Types\BlobType; /** * PostgreSqlPlatform. @@ -37,24 +44,11 @@ class PostgreSqlPlatform extends AbstractPlatform */ private $useBooleanTrueFalseStrings = true; - /** - * PostgreSQL has different behavior with some drivers - * with regard to how booleans have to be handled. - * - * Enables use of 'true'/'false' or otherwise 1 and 0 instead. - * - * @param bool $flag - */ - public function setUseBooleanTrueFalseStrings($flag) - { - $this->useBooleanTrueFalseStrings = (bool)$flag; - } - /** * @var array PostgreSQL booleans literals */ private $booleanLiterals = array( - 'true' => array( + 'true' => array( 't', 'true', 'y', @@ -72,6 +66,19 @@ class PostgreSqlPlatform extends AbstractPlatform ) ); + /** + * PostgreSQL has different behavior with some drivers + * with regard to how booleans have to be handled. + * + * Enables use of 'true'/'false' or otherwise 1 and 0 instead. + * + * @param bool $flag + */ + public function setUseBooleanTrueFalseStrings($flag) + { + $this->useBooleanTrueFalseStrings = (bool) $flag; + } + /** * {@inheritDoc} */ @@ -114,6 +121,19 @@ class PostgreSqlPlatform extends AbstractPlatform return 'POSITION('.$substr.' IN '.$str.')'; } + /** + * {@inheritdoc} + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + { + if (self::DATE_INTERVAL_UNIT_QUARTER === $unit) { + $interval *= 3; + $unit = self::DATE_INTERVAL_UNIT_MONTH; + } + + return "(" . $date ." " . $operator . " (" . $interval . " || ' " . $unit . "')::interval)"; + } + /** * {@inheritDoc} */ @@ -125,57 +145,57 @@ class PostgreSqlPlatform extends AbstractPlatform /** * {@inheritDoc} */ - public function getDateAddDaysExpression($date, $days) + public function supportsSequences() { - return "(" . $date ." + (" . $days . " || ' day')::interval)"; + return true; } /** * {@inheritDoc} */ - public function getDateSubDaysExpression($date, $days) + public function supportsSchemas() { - return "(" . $date ." - (" . $days . " || ' day')::interval)"; + return true; } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getDateAddMonthExpression($date, $months) + public function getDefaultSchemaName() { - return "(" . $date ." + (" . $months . " || ' month')::interval)"; + return 'public'; } /** * {@inheritDoc} */ - public function getDateSubMonthExpression($date, $months) + public function supportsIdentityColumns() { - return "(" . $date ." - (" . $months . " || ' month')::interval)"; + return true; } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function supportsSequences() + public function supportsPartialIndexes() { return true; } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function supportsSchemas() + public function usesSequenceEmulatedIdentityColumns() { return true; } /** - * {@inheritDoc} + * {@inheritdoc} */ - public function supportsIdentityColumns() + public function getIdentitySequenceName($tableName, $columnName) { - return true; + return $tableName . '_' . $columnName . '_seq'; } /** @@ -210,17 +230,27 @@ class PostgreSqlPlatform extends AbstractPlatform return 'SELECT datname FROM pg_database'; } + /** + * {@inheritDoc} + */ + public function getListNamespacesSQL() + { + return "SELECT schema_name AS nspname + FROM information_schema.schemata + WHERE schema_name NOT LIKE 'pg_%' + AND schema_name != 'information_schema'"; + } + /** * {@inheritDoc} */ public function getListSequencesSQL($database) { - return "SELECT - c.relname, n.nspname AS schemaname - FROM - pg_class c, pg_namespace n - WHERE relkind = 'S' AND n.oid = c.relnamespace AND - (n.nspname NOT LIKE 'pg_%' AND n.nspname != 'information_schema')"; + return "SELECT sequence_name AS relname, + sequence_schema AS schemaname + FROM information_schema.sequences + WHERE sequence_schema NOT LIKE 'pg_%' + AND sequence_schema != 'information_schema'"; } /** @@ -228,8 +258,14 @@ class PostgreSqlPlatform extends AbstractPlatform */ public function getListTablesSQL() { - return "SELECT tablename AS table_name, schemaname AS schema_name - FROM pg_tables WHERE schemaname NOT LIKE 'pg_%' AND schemaname != 'information_schema' AND tablename != 'geometry_columns' AND tablename != 'spatial_ref_sys'"; + return "SELECT quote_ident(table_name) AS table_name, + table_schema AS schema_name + FROM information_schema.tables + WHERE table_schema NOT LIKE 'pg_%' + AND table_schema != 'information_schema' + AND table_name != 'geometry_columns' + AND table_name != 'spatial_ref_sys' + AND table_type != 'VIEW'"; } /** @@ -237,7 +273,11 @@ class PostgreSqlPlatform extends AbstractPlatform */ public function getListViewsSQL($database) { - return 'SELECT viewname, definition FROM pg_views'; + return 'SELECT quote_ident(table_name) AS viewname, + table_schema AS schemaname, + view_definition AS definition + FROM information_schema.views + WHERE view_definition IS NOT NULL'; } /** @@ -245,7 +285,7 @@ class PostgreSqlPlatform extends AbstractPlatform */ public function getListTableForeignKeysSQL($table, $database = null) { - return "SELECT r.conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef + return "SELECT quote_ident(r.conname) as conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r WHERE r.conrelid = ( @@ -277,8 +317,11 @@ class PostgreSqlPlatform extends AbstractPlatform */ public function getListTableConstraintsSQL($table) { + $table = new Identifier($table); + $table = $table->getName(); + return "SELECT - relname + quote_ident(relname) as relname FROM pg_class WHERE oid IN ( @@ -298,8 +341,9 @@ class PostgreSqlPlatform extends AbstractPlatform */ public function getListTableIndexesSQL($table, $currentDatabase = null) { - return "SELECT relname, pg_index.indisunique, pg_index.indisprimary, - pg_index.indkey, pg_index.indrelid + return "SELECT quote_ident(relname) as relname, pg_index.indisunique, pg_index.indisprimary, + pg_index.indkey, pg_index.indrelid, + pg_get_expr(indpred, indrelid) AS where FROM pg_class, pg_index WHERE oid IN ( SELECT indexrelid @@ -324,7 +368,9 @@ class PostgreSqlPlatform extends AbstractPlatform } else { $schema = "ANY(string_to_array((select replace(replace(setting,'\"\$user\"',user),' ','') from pg_catalog.pg_settings where name = 'search_path'),','))"; } - $whereClause .= "$classAlias.relname = '" . $table . "' AND $namespaceAlias.nspname = $schema"; + + $table = new Identifier($table); + $whereClause .= "$classAlias.relname = '" . $table->getName() . "' AND $namespaceAlias.nspname = $schema"; return $whereClause; } @@ -336,7 +382,7 @@ class PostgreSqlPlatform extends AbstractPlatform { return "SELECT a.attnum, - a.attname AS field, + quote_ident(a.attname) AS field, t.typname AS type, format_type(a.atttypid, a.atttypmod) AS complete_type, (SELECT t1.typname FROM pg_catalog.pg_type t1 WHERE t1.oid = t.typbasetype) AS domain_type, @@ -349,7 +395,7 @@ class PostgreSqlPlatform extends AbstractPlatform AND pg_index.indkey[0] = a.attnum AND pg_index.indisprimary = 't' ) AS pri, - (SELECT pg_attrdef.adsrc + (SELECT pg_get_expr(adbin, adrelid) FROM pg_attrdef WHERE c.oid = pg_attrdef.adrelid AND pg_attrdef.adnum=a.attnum @@ -374,6 +420,34 @@ class PostgreSqlPlatform extends AbstractPlatform return 'CREATE DATABASE ' . $name; } + /** + * Returns the SQL statement for disallowing new connections on the given database. + * + * This is useful to force DROP DATABASE operations which could fail because of active connections. + * + * @param string $database The name of the database to disallow new connections for. + * + * @return string + */ + public function getDisallowDatabaseConnectionsSQL($database) + { + return "UPDATE pg_database SET datallowconn = 'false' WHERE datname = '$database'"; + } + + /** + * Returns the SQL statement for closing currently active connections on the given database. + * + * This is useful to force DROP DATABASE operations which could fail because of active connections. + * + * @param string $database The name of the database to close currently active connections for. + * + * @return string + */ + public function getCloseActiveDatabaseConnectionsSQL($database) + { + return "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname = '$database'"; + } + /** * {@inheritDoc} */ @@ -419,9 +493,16 @@ class PostgreSqlPlatform extends AbstractPlatform } $query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; - if ($comment = $this->getColumnComment($column)) { - $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; + + $comment = $this->getColumnComment($column); + + if (null !== $comment && '' !== $comment) { + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $comment + ); } } @@ -431,7 +512,7 @@ class PostgreSqlPlatform extends AbstractPlatform } $query = 'DROP ' . $column->getQuotedName($this); - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } foreach ($diff->changedColumns as $columnDiff) { @@ -440,6 +521,10 @@ class PostgreSqlPlatform extends AbstractPlatform continue; } + if ($this->isUnchangedBinaryColumn($columnDiff)) { + continue; + } + $oldColumnName = $columnDiff->getOldColumnName()->getQuotedName($this); $column = $columnDiff->column; @@ -448,49 +533,49 @@ class PostgreSqlPlatform extends AbstractPlatform // here was a server version check before, but DBAL API does not support this anymore. $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSqlDeclaration($column->toArray(), $this); - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } - if ($columnDiff->hasChanged('default')) { + if ($columnDiff->hasChanged('default') || $columnDiff->hasChanged('type')) { $defaultClause = null === $column->getDefault() ? ' DROP DEFAULT' : ' SET' . $this->getDefaultValueDeclarationSQL($column->toArray()); $query = 'ALTER ' . $oldColumnName . $defaultClause; - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } if ($columnDiff->hasChanged('notnull')) { $query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotNull() ? 'SET' : 'DROP') . ' NOT NULL'; - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } if ($columnDiff->hasChanged('autoincrement')) { if ($column->getAutoincrement()) { // add autoincrement - $seqName = $diff->name . '_' . $oldColumnName . '_seq'; + $seqName = $this->getIdentitySequenceName($diff->name, $oldColumnName); $sql[] = "CREATE SEQUENCE " . $seqName; - $sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->name . "))"; + $sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->getName($this)->getQuotedName($this) . "))"; $query = "ALTER " . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')"; - $sql[] = "ALTER TABLE " . $diff->name . " " . $query; + $sql[] = "ALTER TABLE " . $diff->getName($this)->getQuotedName($this) . " " . $query; } else { // Drop autoincrement, but do NOT drop the sequence. It might be re-used by other tables or have $query = "ALTER " . $oldColumnName . " " . "DROP DEFAULT"; - $sql[] = "ALTER TABLE " . $diff->name . " " . $query; + $sql[] = "ALTER TABLE " . $diff->getName($this)->getQuotedName($this) . " " . $query; } } if ($columnDiff->hasChanged('comment')) { $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->name, - $column->getName(), + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), $this->getColumnComment($column) ); } if ($columnDiff->hasChanged('length')) { - $query = 'ALTER ' . $column->getName() . ' TYPE ' . $column->getType()->getSqlDeclaration($column->toArray(), $this); - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $column->getType()->getSqlDeclaration($column->toArray(), $this); + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } } @@ -499,50 +584,134 @@ class PostgreSqlPlatform extends AbstractPlatform continue; } - $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName . ' TO ' . $column->getQuotedName($this); + $oldColumnName = new Identifier($oldColumnName); + + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . + ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); } $tableSql = array(); if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { + $sql = array_merge($sql, $commentsSQL); + if ($diff->newName !== false) { - $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' RENAME TO ' . $diff->getNewName()->getQuotedName($this); } - $sql = array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $sql, $this->getPostAlterTableIndexForeignKeySQL($diff), $commentsSQL); + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); } return array_merge($sql, $tableSql, $columnSql); } + /** + * Checks whether a given column diff is a logically unchanged binary type column. + * + * Used to determine whether a column alteration for a binary type column can be skipped. + * Doctrine's {@link \Doctrine\DBAL\Types\BinaryType} and {@link \Doctrine\DBAL\Types\BlobType} + * are mapped to the same database column type on this platform as this platform + * does not have a native VARBINARY/BINARY column type. Therefore the {@link \Doctrine\DBAL\Schema\Comparator} + * might detect differences for binary type columns which do not have to be propagated + * to database as there actually is no difference at database level. + * + * @param ColumnDiff $columnDiff The column diff to check against. + * + * @return boolean True if the given column diff is an unchanged binary type column, false otherwise. + */ + private function isUnchangedBinaryColumn(ColumnDiff $columnDiff) + { + $columnType = $columnDiff->column->getType(); + + if ( ! $columnType instanceof BinaryType && ! $columnType instanceof BlobType) { + return false; + } + + $fromColumn = $columnDiff->fromColumn instanceof Column ? $columnDiff->fromColumn : null; + + if ($fromColumn) { + $fromColumnType = $fromColumn->getType(); + + if ( ! $fromColumnType instanceof BinaryType && ! $fromColumnType instanceof BlobType) { + return false; + } + + return count(array_diff($columnDiff->changedProperties, array('type', 'length', 'fixed'))) === 0; + } + + if ($columnDiff->hasChanged('type')) { + return false; + } + + return count(array_diff($columnDiff->changedProperties, array('length', 'fixed'))) === 0; + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + if (strpos($tableName, '.') !== false) { + list($schema) = explode('.', $tableName); + $oldIndexName = $schema . '.' . $oldIndexName; + } + + return array('ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)); + } + /** * {@inheritdoc} */ public function getCommentOnColumnSQL($tableName, $columnName, $comment) { - $comment = $comment === null ? 'NULL' : "'$comment'"; + $tableName = new Identifier($tableName); + $columnName = new Identifier($columnName); + $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); - return "COMMENT ON COLUMN $tableName.$columnName IS $comment"; + return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . "." . $columnName->getQuotedName($this) . + " IS $comment"; } /** * {@inheritDoc} */ - public function getCreateSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence) + public function getCreateSequenceSQL(Sequence $sequence) { return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . ' INCREMENT BY ' . $sequence->getAllocationSize() . ' MINVALUE ' . $sequence->getInitialValue() . - ' START ' . $sequence->getInitialValue(); + ' START ' . $sequence->getInitialValue() . + $this->getSequenceCacheSQL($sequence); } /** * {@inheritDoc} */ - public function getAlterSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence) + public function getAlterSequenceSQL(Sequence $sequence) { return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . - ' INCREMENT BY ' . $sequence->getAllocationSize(); + ' INCREMENT BY ' . $sequence->getAllocationSize() . + $this->getSequenceCacheSQL($sequence); + } + + /** + * Cache definition for sequences + * + * @param Sequence $sequence + * + * @return string + */ + private function getSequenceCacheSQL(Sequence $sequence) + { + if ($sequence->getCache() > 1) { + return ' CACHE ' . $sequence->getCache(); + } + + return ''; } /** @@ -550,12 +719,21 @@ class PostgreSqlPlatform extends AbstractPlatform */ public function getDropSequenceSQL($sequence) { - if ($sequence instanceof \Doctrine\DBAL\Schema\Sequence) { + if ($sequence instanceof Sequence) { $sequence = $sequence->getQuotedName($this); } + return 'DROP SEQUENCE ' . $sequence . ' CASCADE'; } + /** + * {@inheritDoc} + */ + public function getCreateSchemaSQL($schemaName) + { + return 'CREATE SCHEMA ' . $schemaName; + } + /** * {@inheritDoc} */ @@ -606,11 +784,12 @@ class PostgreSqlPlatform extends AbstractPlatform * @param callable $callback The callback function to use for converting the real boolean value. * * @return mixed + * @throws \UnexpectedValueException */ private function convertSingleBooleanValue($value, $callback) { if (null === $value) { - return $callback(false); + return $callback(null); } if (is_bool($value) || is_numeric($value)) { @@ -674,6 +853,10 @@ class PostgreSqlPlatform extends AbstractPlatform return $this->doConvertBooleans( $item, function ($boolean) { + if (null === $boolean) { + return 'NULL'; + } + return true === $boolean ? 'true' : 'false'; } ); @@ -691,7 +874,7 @@ class PostgreSqlPlatform extends AbstractPlatform return $this->doConvertBooleans( $item, function ($boolean) { - return (int) $boolean; + return null === $boolean ? null : (int) $boolean; } ); } @@ -753,6 +936,7 @@ class PostgreSqlPlatform extends AbstractPlatform if ( ! empty($field['autoincrement'])) { return 'BIGSERIAL'; } + return 'BIGINT'; } @@ -829,6 +1013,14 @@ class PostgreSqlPlatform extends AbstractPlatform : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); } + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return 'BYTEA'; + } + /** * {@inheritDoc} */ @@ -942,6 +1134,22 @@ class PostgreSqlPlatform extends AbstractPlatform return 65535; } + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function getBinaryDefaultLength() + { + return 0; + } + /** * {@inheritDoc} */ diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php new file mode 100644 index 0000000000..44ba707b61 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php @@ -0,0 +1,47 @@ +. + */ + +namespace Doctrine\DBAL\Platforms; + +/** + * The SQLAnywhere11Platform provides the behavior, features and SQL dialect of the + * SAP Sybase SQL Anywhere 11 database platform. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class SQLAnywhere11Platform extends SQLAnywherePlatform +{ + /** + * {@inheritdoc} + */ + public function getRegexpExpression() + { + return 'REGEXP'; + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere11Keywords'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php new file mode 100644 index 0000000000..17b413eccb --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php @@ -0,0 +1,135 @@ +. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\Sequence; + +/** + * The SQLAnywhere12Platform provides the behavior, features and SQL dialect of the + * SAP Sybase SQL Anywhere 12 database platform. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class SQLAnywhere12Platform extends SQLAnywhere11Platform +{ + /** + * {@inheritdoc} + */ + public function getCreateSequenceSQL(Sequence $sequence) + { + return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize() . + ' START WITH ' . $sequence->getInitialValue() . + ' MINVALUE ' . $sequence->getInitialValue(); + } + + /** + * {@inheritdoc} + */ + public function getAlterSequenceSQL(Sequence $sequence) + { + return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize(); + } + + /** + * {@inheritdoc} + */ + public function getDateTimeTzFormatString() + { + return 'Y-m-d H:i:s.uP'; + } + + /** + * {@inheritdoc} + */ + public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP WITH TIME ZONE'; + } + + /** + * {@inheritdoc} + */ + public function getDropSequenceSQL($sequence) + { + if ($sequence instanceof Sequence) { + $sequence = $sequence->getQuotedName($this); + } + + return 'DROP SEQUENCE ' . $sequence; + } + + /** + * {@inheritdoc} + */ + public function getListSequencesSQL($database) + { + return 'SELECT sequence_name, increment_by, start_with, min_value FROM SYS.SYSSEQUENCE'; + } + + /** + * {@inheritdoc} + */ + public function getSequenceNextValSQL($sequenceName) + { + return 'SELECT ' . $sequenceName . '.NEXTVAL'; + } + + /** + * {@inheritdoc} + */ + public function supportsSequences() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function getAdvancedIndexOptionsSQL(Index $index) + { + if ( ! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_not_distinct')) { + return ' WITH NULLS NOT DISTINCT' . parent::getAdvancedIndexOptionsSQL($index); + } + + return parent::getAdvancedIndexOptionsSQL($index); + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere12Keywords'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + parent::initializeDoctrineTypeMappings(); + $this->doctrineTypeMapping['timestamp with time zone'] = 'datetime'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php new file mode 100644 index 0000000000..6808d7301a --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php @@ -0,0 +1,60 @@ +. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\Common\Proxy\Exception\UnexpectedValueException; +use Doctrine\DBAL\Schema\Index; + +/** + * The SQLAnywhere16Platform provides the behavior, features and SQL dialect of the + * SAP Sybase SQL Anywhere 16 database platform. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class SQLAnywhere16Platform extends SQLAnywhere12Platform +{ + /** + * {@inheritdoc} + */ + protected function getAdvancedIndexOptionsSQL(Index $index) + { + if ($index->hasFlag('with_nulls_distinct') && $index->hasFlag('with_nulls_not_distinct')) { + throw new UnexpectedValueException( + 'An Index can either have a "with_nulls_distinct" or "with_nulls_not_distinct" flag but not both.' + ); + } + + if ( ! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_distinct')) { + return ' WITH NULLS DISTINCT' . parent::getAdvancedIndexOptionsSQL($index); + } + + return parent::getAdvancedIndexOptionsSQL($index); + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere16Keywords'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php new file mode 100644 index 0000000000..36debc390e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php @@ -0,0 +1,1480 @@ +. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\LockMode; +use Doctrine\DBAL\Schema\Column; +use Doctrine\DBAL\Schema\ColumnDiff; +use Doctrine\DBAL\Schema\Constraint; +use Doctrine\DBAL\Schema\ForeignKeyConstraint; +use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\Identifier; +use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Schema\TableDiff; + +/** + * The SQLAnywherePlatform provides the behavior, features and SQL dialect of the + * SAP Sybase SQL Anywhere 10 database platform. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class SQLAnywherePlatform extends AbstractPlatform +{ + /** + * @var integer + */ + const FOREIGN_KEY_MATCH_SIMPLE = 1; + /** + * @var integer + */ + const FOREIGN_KEY_MATCH_FULL = 2; + /** + * @var integer + */ + const FOREIGN_KEY_MATCH_SIMPLE_UNIQUE = 129; + /** + * @var integer + */ + const FOREIGN_KEY_MATCH_FULL_UNIQUE = 130; + + /** + * {@inheritdoc} + */ + public function appendLockHint($fromClause, $lockMode) + { + switch (true) { + case $lockMode === LockMode::NONE: + return $fromClause . ' WITH (NOLOCK)'; + + case $lockMode === LockMode::PESSIMISTIC_READ: + return $fromClause . ' WITH (UPDLOCK)'; + + case $lockMode === LockMode::PESSIMISTIC_WRITE: + return $fromClause . ' WITH (XLOCK)'; + + default: + return $fromClause; + } + } + + /** + * {@inheritdoc} + * + * SQL Anywhere supports a maximum length of 128 bytes for identifiers. + */ + public function fixSchemaElementName($schemaElementName) + { + $maxIdentifierLength = $this->getMaxIdentifierLength(); + + if (strlen($schemaElementName) > $maxIdentifierLength) { + return substr($schemaElementName, 0, $maxIdentifierLength); + } + + return $schemaElementName; + } + + /** + * {@inheritdoc} + */ + public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) + { + $query = ''; + + if ($foreignKey->hasOption('match')) { + $query = ' MATCH ' . $this->getForeignKeyMatchClauseSQL($foreignKey->getOption('match')); + } + + $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); + + if ($foreignKey->hasOption('check_on_commit') && (boolean) $foreignKey->getOption('check_on_commit')) { + $query .= ' CHECK ON COMMIT'; + } + + if ($foreignKey->hasOption('clustered') && (boolean) $foreignKey->getOption('clustered')) { + $query .= ' CLUSTERED'; + } + + if ($foreignKey->hasOption('for_olap_workload') && (boolean) $foreignKey->getOption('for_olap_workload')) { + $query .= ' FOR OLAP WORKLOAD'; + } + + return $query; + } + + /** + * {@inheritdoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $sql = array(); + $columnSql = array(); + $commentsSQL = array(); + $tableSql = array(); + $alterClauses = array(); + + /** @var \Doctrine\DBAL\Schema\Column $column */ + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $alterClauses[] = $this->getAlterTableAddColumnClause($column); + + $comment = $this->getColumnComment($column); + + if (null !== $comment && '' !== $comment) { + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $comment + ); + } + } + + /** @var \Doctrine\DBAL\Schema\Column $column */ + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $alterClauses[] = $this->getAlterTableRemoveColumnClause($column); + } + + /** @var \Doctrine\DBAL\Schema\ColumnDiff $columnDiff */ + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + $alterClause = $this->getAlterTableChangeColumnClause($columnDiff); + + if (null !== $alterClause) { + $alterClauses[] = $alterClause; + } + + if ($columnDiff->hasChanged('comment')) { + $column = $columnDiff->column; + + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $this->getColumnComment($column) + ); + } + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . + $this->getAlterTableRenameColumnClause($oldColumnName, $column); + } + + if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { + if ( ! empty($alterClauses)) { + $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . implode(", ", $alterClauses); + } + + $sql = array_merge($sql, $commentsSQL); + + if ($diff->newName !== false) { + $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . + $this->getAlterTableRenameTableClause($diff->getNewName()); + } + + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * Returns the SQL clause for creating a column in a table alteration. + * + * @param Column $column The column to add. + * + * @return string + */ + protected function getAlterTableAddColumnClause(Column $column) + { + return 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + } + + /** + * Returns the SQL clause for altering a table. + * + * @param Identifier $tableName The quoted name of the table to alter. + * + * @return string + */ + protected function getAlterTableClause(Identifier $tableName) + { + return 'ALTER TABLE ' . $tableName->getQuotedName($this); + } + + /** + * Returns the SQL clause for dropping a column in a table alteration. + * + * @param Column $column The column to drop. + * + * @return string + */ + protected function getAlterTableRemoveColumnClause(Column $column) + { + return 'DROP ' . $column->getQuotedName($this); + } + + /** + * Returns the SQL clause for renaming a column in a table alteration. + * + * @param string $oldColumnName The quoted name of the column to rename. + * @param Column $column The column to rename to. + * + * @return string + */ + protected function getAlterTableRenameColumnClause($oldColumnName, Column $column) + { + $oldColumnName = new Identifier($oldColumnName); + + return 'RENAME ' . $oldColumnName->getQuotedName($this) .' TO ' . $column->getQuotedName($this); + } + + /** + * Returns the SQL clause for renaming a table in a table alteration. + * + * @param Identifier $newTableName The quoted name of the table to rename to. + * + * @return string + */ + protected function getAlterTableRenameTableClause(Identifier $newTableName) + { + return 'RENAME ' . $newTableName->getQuotedName($this); + } + + /** + * Returns the SQL clause for altering a column in a table alteration. + * + * This method returns null in case that only the column comment has changed. + * Changes in column comments have to be handled differently. + * + * @param ColumnDiff $columnDiff The diff of the column to alter. + * + * @return string|null + */ + protected function getAlterTableChangeColumnClause(ColumnDiff $columnDiff) + { + $column = $columnDiff->column; + + // Do not return alter clause if only comment has changed. + if ( ! ($columnDiff->hasChanged('comment') && count($columnDiff->changedProperties) === 1)) { + $columnAlterationClause = 'ALTER ' . + $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + + if ($columnDiff->hasChanged('default') && null === $column->getDefault()) { + $columnAlterationClause .= ', ALTER ' . $column->getQuotedName($this) . ' DROP DEFAULT'; + } + + return $columnAlterationClause; + } + } + + /** + * {@inheritdoc} + */ + public function getBigIntTypeDeclarationSQL(array $columnDef) + { + $columnDef['integer_type'] = 'BIGINT'; + + return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritdoc} + */ + public function getBinaryDefaultLength() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 32767; + } + + /** + * {@inheritdoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'LONG BINARY'; + } + + /** + * {@inheritdoc} + * + * BIT type columns require an explicit NULL declaration + * in SQL Anywhere if they shall be nullable. + * Otherwise by just omitting the NOT NULL clause, + * SQL Anywhere will declare them NOT NULL nonetheless. + */ + public function getBooleanTypeDeclarationSQL(array $columnDef) + { + $nullClause = isset($columnDef['notnull']) && (boolean) $columnDef['notnull'] === false ? ' NULL' : ''; + + return 'BIT' . $nullClause; + } + + /** + * {@inheritdoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'TEXT'; + } + + /** + * {@inheritdoc} + */ + public function getCommentOnColumnSQL($tableName, $columnName, $comment) + { + $tableName = new Identifier($tableName); + $columnName = new Identifier($columnName); + $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); + + return "COMMENT ON COLUMN " . $tableName->getQuotedName($this) . '.' . $columnName->getQuotedName($this) . + " IS $comment"; + } + + /** + * {@inheritdoc} + */ + public function getConcatExpression() + { + return 'STRING(' . implode(', ', (array) func_get_args()) . ')'; + } + + /** + * {@inheritdoc} + */ + public function getCreateConstraintSQL(Constraint $constraint, $table) + { + if ($constraint instanceof ForeignKeyConstraint) { + return $this->getCreateForeignKeySQL($constraint, $table); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . + ' ADD ' . $this->getTableConstraintDeclarationSQL($constraint, $constraint->getQuotedName($this)); + } + + /** + * {@inheritdoc} + */ + public function getCreateDatabaseSQL($database) + { + $database = new Identifier($database); + + return "CREATE DATABASE '" . $database->getName() . "'"; + } + + /** + * {@inheritdoc} + * + * Appends SQL Anywhere specific flags if given. + */ + public function getCreateIndexSQL(Index $index, $table) + { + return parent::getCreateIndexSQL($index, $table). $this->getAdvancedIndexOptionsSQL($index); + } + + /** + * {@inheritdoc} + */ + public function getCreatePrimaryKeySQL(Index $index, $table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . ' ADD ' . $this->getPrimaryKeyDeclarationSQL($index); + } + + /** + * {@inheritdoc} + */ + public function getCreateTemporaryTableSnippetSQL() + { + return 'CREATE ' . $this->getTemporaryTableSQL() . ' TABLE'; + } + + /** + * {@inheritdoc} + */ + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + /** + * {@inheritdoc} + */ + public function getCurrentDateSQL() + { + return 'CURRENT DATE'; + } + + /** + * {@inheritdoc} + */ + public function getCurrentTimeSQL() + { + return 'CURRENT TIME'; + } + + /** + * {@inheritdoc} + */ + public function getCurrentTimestampSQL() + { + return 'CURRENT TIMESTAMP'; + } + + /** + * {@inheritdoc} + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + { + $factorClause = ''; + + if ('-' === $operator) { + $factorClause = '-1 * '; + } + + return 'DATEADD(' . $unit . ', ' . $factorClause . $interval . ', ' . $date . ')'; + } + + /** + * {@inheritdoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return 'DATEDIFF(day, ' . $date2 . ', ' . $date1 . ')'; + } + + /** + * {@inheritdoc} + */ + public function getDateTimeFormatString() + { + return 'Y-m-d H:i:s.u'; + } + + /** + * {@inheritdoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritdoc} + */ + public function getDateTimeTzFormatString() + { + return $this->getDateTimeFormatString(); + } + + /** + * {@inheritdoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritdoc} + */ + public function getDefaultTransactionIsolationLevel() + { + return Connection::TRANSACTION_READ_UNCOMMITTED; + } + + /** + * {@inheritdoc} + */ + public function getDropDatabaseSQL($database) + { + $database = new Identifier($database); + + return "DROP DATABASE '" . $database->getName() . "'"; + } + + /** + * {@inheritdoc} + */ + public function getDropIndexSQL($index, $table = null) + { + if ($index instanceof Index) { + $index = $index->getQuotedName($this); + } + + if ( ! is_string($index)) { + throw new \InvalidArgumentException( + 'SQLAnywherePlatform::getDropIndexSQL() expects $index parameter to be string or ' . + '\Doctrine\DBAL\Schema\Index.' + ); + } + + if ( ! isset($table)) { + return 'DROP INDEX ' . $index; + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + if ( ! is_string($table)) { + throw new \InvalidArgumentException( + 'SQLAnywherePlatform::getDropIndexSQL() expects $table parameter to be string or ' . + '\Doctrine\DBAL\Schema\Table.' + ); + } + + return 'DROP INDEX ' . $table . '.' . $index; + } + + /** + * {@inheritdoc} + */ + public function getDropViewSQL($name) + { + return 'DROP VIEW ' . $name; + } + + /** + * {@inheritdoc} + */ + public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey) + { + $sql = ''; + $foreignKeyName = $foreignKey->getName(); + $localColumns = $foreignKey->getQuotedLocalColumns($this); + $foreignColumns = $foreignKey->getQuotedForeignColumns($this); + $foreignTableName = $foreignKey->getQuotedForeignTableName($this); + + if ( ! empty($foreignKeyName)) { + $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' '; + } + + if (empty($localColumns)) { + throw new \InvalidArgumentException("Incomplete definition. 'local' required."); + } + + if (empty($foreignColumns)) { + throw new \InvalidArgumentException("Incomplete definition. 'foreign' required."); + } + + if (empty($foreignTableName)) { + throw new \InvalidArgumentException("Incomplete definition. 'foreignTable' required."); + } + + if ($foreignKey->hasOption('notnull') && (boolean) $foreignKey->getOption('notnull')) { + $sql .= 'NOT NULL '; + } + + return $sql . + 'FOREIGN KEY (' . $this->getIndexFieldDeclarationListSQL($localColumns) . ') ' . + 'REFERENCES ' . $foreignKey->getQuotedForeignTableName($this) . + ' (' . $this->getIndexFieldDeclarationListSQL($foreignColumns) . ')'; + } + + /** + * Returns foreign key MATCH clause for given type. + * + * @param integer $type The foreign key match type + * + * @return string + * + * @throws \InvalidArgumentException if unknown match type given + */ + public function getForeignKeyMatchClauseSQL($type) + { + switch ((int) $type) { + case self::FOREIGN_KEY_MATCH_SIMPLE: + return 'SIMPLE'; + break; + case self::FOREIGN_KEY_MATCH_FULL: + return 'FULL'; + break; + case self::FOREIGN_KEY_MATCH_SIMPLE_UNIQUE: + return 'UNIQUE SIMPLE'; + break; + case self::FOREIGN_KEY_MATCH_FULL_UNIQUE: + return 'UNIQUE FULL'; + default: + throw new \InvalidArgumentException('Invalid foreign key match type: ' . $type); + } + } + + /** + * {@inheritdoc} + */ + public function getForeignKeyReferentialActionSQL($action) + { + // NO ACTION is not supported, therefore falling back to RESTRICT. + if (strtoupper($action) === 'NO ACTION') { + return 'RESTRICT'; + } + + return parent::getForeignKeyReferentialActionSQL($action); + } + + /** + * {@inheritdoc} + */ + public function getForUpdateSQL() + { + return ''; + } + + /** + * {@inheritdoc} + */ + public function getGuidExpression() + { + return 'NEWID()'; + } + + /** + * {@inheritdoc} + */ + public function getGuidTypeDeclarationSQL(array $field) + { + return 'UNIQUEIDENTIFIER'; + } + + /** + * {@inheritdoc} + */ + public function getIndexDeclarationSQL($name, Index $index) + { + // Index declaration in statements like CREATE TABLE is not supported. + throw DBALException::notSupported(__METHOD__); + } + + /** + * {@inheritdoc} + */ + public function getIntegerTypeDeclarationSQL(array $columnDef) + { + $columnDef['integer_type'] = 'INT'; + + return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritdoc} + */ + public function getListDatabasesSQL() + { + return 'SELECT db_name(number) AS name FROM sa_db_list()'; + } + + /** + * {@inheritdoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + $user = 'USER_NAME()'; + + if (strpos($table, '.') !== false) { + list($user, $table) = explode('.', $table); + $user = "'" . $user . "'"; + } + + return "SELECT col.column_name, + COALESCE(def.user_type_name, def.domain_name) AS 'type', + def.declared_width AS 'length', + def.scale, + CHARINDEX('unsigned', def.domain_name) AS 'unsigned', + IF col.nulls = 'Y' THEN 0 ELSE 1 ENDIF AS 'notnull', + col.\"default\", + def.is_autoincrement AS 'autoincrement', + rem.remarks AS 'comment' + FROM sa_describe_query('SELECT * FROM \"$table\"') AS def + JOIN SYS.SYSTABCOL AS col + ON col.table_id = def.base_table_id AND col.column_id = def.base_column_id + LEFT JOIN SYS.SYSREMARK AS rem + ON col.object_id = rem.object_id + WHERE def.base_owner_name = $user + ORDER BY def.base_column_id ASC"; + } + + /** + * {@inheritdoc} + * + * @todo Where is this used? Which information should be retrieved? + */ + public function getListTableConstraintsSQL($table) + { + $user = ''; + + if (strpos($table, '.') !== false) { + list($user, $table) = explode('.', $table); + $user = "'" . $user . "'"; + } + + return "SELECT con.* + FROM SYS.SYSCONSTRAINT AS con + JOIN SYS.SYSTAB AS tab ON con.table_object_id = tab.object_id + WHERE tab.table_name = '$table' + AND tab.creator = USER_ID($user)"; + } + + /** + * {@inheritdoc} + */ + public function getListTableForeignKeysSQL($table) + { + $user = ''; + + if (strpos($table, '.') !== false) { + list($user, $table) = explode('.', $table); + $user = "'" . $user . "'"; + } + + return "SELECT fcol.column_name AS local_column, + ptbl.table_name AS foreign_table, + pcol.column_name AS foreign_column, + idx.index_name, + IF fk.nulls = 'N' + THEN 1 + ELSE NULL + ENDIF AS notnull, + CASE ut.referential_action + WHEN 'C' THEN 'CASCADE' + WHEN 'D' THEN 'SET DEFAULT' + WHEN 'N' THEN 'SET NULL' + WHEN 'R' THEN 'RESTRICT' + ELSE NULL + END AS on_update, + CASE dt.referential_action + WHEN 'C' THEN 'CASCADE' + WHEN 'D' THEN 'SET DEFAULT' + WHEN 'N' THEN 'SET NULL' + WHEN 'R' THEN 'RESTRICT' + ELSE NULL + END AS on_delete, + IF fk.check_on_commit = 'Y' + THEN 1 + ELSE NULL + ENDIF AS check_on_commit, -- check_on_commit flag + IF ftbl.clustered_index_id = idx.index_id + THEN 1 + ELSE NULL + ENDIF AS 'clustered', -- clustered flag + IF fk.match_type = 0 + THEN NULL + ELSE fk.match_type + ENDIF AS 'match', -- match option + IF pidx.max_key_distance = 1 + THEN 1 + ELSE NULL + ENDIF AS for_olap_workload -- for_olap_workload flag + FROM SYS.SYSFKEY AS fk + JOIN SYS.SYSIDX AS idx + ON fk.foreign_table_id = idx.table_id + AND fk.foreign_index_id = idx.index_id + JOIN SYS.SYSPHYSIDX pidx + ON idx.table_id = pidx.table_id + AND idx.phys_index_id = pidx.phys_index_id + JOIN SYS.SYSTAB AS ptbl + ON fk.primary_table_id = ptbl.table_id + JOIN SYS.SYSTAB AS ftbl + ON fk.foreign_table_id = ftbl.table_id + JOIN SYS.SYSIDXCOL AS idxcol + ON idx.table_id = idxcol.table_id + AND idx.index_id = idxcol.index_id + JOIN SYS.SYSTABCOL AS pcol + ON ptbl.table_id = pcol.table_id + AND idxcol.primary_column_id = pcol.column_id + JOIN SYS.SYSTABCOL AS fcol + ON ftbl.table_id = fcol.table_id + AND idxcol.column_id = fcol.column_id + LEFT JOIN SYS.SYSTRIGGER ut + ON fk.foreign_table_id = ut.foreign_table_id + AND fk.foreign_index_id = ut.foreign_key_id + AND ut.event = 'C' + LEFT JOIN SYS.SYSTRIGGER dt + ON fk.foreign_table_id = dt.foreign_table_id + AND fk.foreign_index_id = dt.foreign_key_id + AND dt.event = 'D' + WHERE ftbl.table_name = '$table' + AND ftbl.creator = USER_ID($user) + ORDER BY fk.foreign_index_id ASC, idxcol.sequence ASC"; + } + + /** + * {@inheritdoc} + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + $user = ''; + + if (strpos($table, '.') !== false) { + list($user, $table) = explode('.', $table); + $user = "'" . $user . "'"; + } + + return "SELECT idx.index_name AS key_name, + IF idx.index_category = 1 + THEN 1 + ELSE 0 + ENDIF AS 'primary', + col.column_name, + IF idx.\"unique\" IN(1, 2, 5) + THEN 0 + ELSE 1 + ENDIF AS non_unique, + IF tbl.clustered_index_id = idx.index_id + THEN 1 + ELSE NULL + ENDIF AS 'clustered', -- clustered flag + IF idx.\"unique\" = 5 + THEN 1 + ELSE NULL + ENDIF AS with_nulls_not_distinct, -- with_nulls_not_distinct flag + IF pidx.max_key_distance = 1 + THEN 1 + ELSE NULL + ENDIF AS for_olap_workload -- for_olap_workload flag + FROM SYS.SYSIDX AS idx + JOIN SYS.SYSPHYSIDX pidx + ON idx.table_id = pidx.table_id + AND idx.phys_index_id = pidx.phys_index_id + JOIN SYS.SYSIDXCOL AS idxcol + ON idx.table_id = idxcol.table_id AND idx.index_id = idxcol.index_id + JOIN SYS.SYSTABCOL AS col + ON idxcol.table_id = col.table_id AND idxcol.column_id = col.column_id + JOIN SYS.SYSTAB AS tbl + ON idx.table_id = tbl.table_id + WHERE tbl.table_name = '$table' + AND tbl.creator = USER_ID($user) + AND idx.index_category != 2 -- exclude indexes implicitly created by foreign key constraints + ORDER BY idx.index_id ASC, idxcol.sequence ASC"; + } + + /** + * {@inheritdoc} + */ + public function getListTablesSQL() + { + return "SELECT tbl.table_name + FROM SYS.SYSTAB AS tbl + JOIN SYS.SYSUSER AS usr ON tbl.creator = usr.user_id + JOIN dbo.SYSOBJECTS AS obj ON tbl.object_id = obj.id + WHERE tbl.table_type IN(1, 3) -- 'BASE', 'GBL TEMP' + AND usr.user_name NOT IN('SYS', 'dbo', 'rs_systabgroup') -- exclude system users + AND obj.type = 'U' -- user created tables only + ORDER BY tbl.table_name ASC"; + } + + /** + * {@inheritdoc} + * + * @todo Where is this used? Which information should be retrieved? + */ + public function getListUsersSQL() + { + return 'SELECT * FROM SYS.SYSUSER ORDER BY user_name ASC'; + } + + /** + * {@inheritdoc} + */ + public function getListViewsSQL($database) + { + return "SELECT tbl.table_name, v.view_def + FROM SYS.SYSVIEW v + JOIN SYS.SYSTAB tbl ON v.view_object_id = tbl.object_id + JOIN SYS.SYSUSER usr ON tbl.creator = usr.user_id + JOIN dbo.SYSOBJECTS obj ON tbl.object_id = obj.id + WHERE usr.user_name NOT IN('SYS', 'dbo', 'rs_systabgroup') -- exclude system users + ORDER BY tbl.table_name ASC"; + } + + /** + * {@inheritdoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos == false) { + return 'LOCATE(' . $str . ', ' . $substr . ')'; + } + + return 'LOCATE(' . $str . ', ' . $substr . ', ' . $startPos . ')'; + } + + /** + * {@inheritdoc} + */ + public function getMaxIdentifierLength() + { + return 128; + } + + /** + * {@inheritdoc} + */ + public function getMd5Expression($column) + { + return "HASH(" . $column . ", 'MD5')"; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'sqlanywhere'; + } + + /** + * Obtain DBMS specific SQL code portion needed to set a primary key + * declaration to be used in statements like ALTER TABLE. + * + * @param Index $index Index definition + * @param string $name Name of the primary key + * + * @return string DBMS specific SQL code portion needed to set a primary key + * + * @throws \InvalidArgumentException if the given index is not a primary key. + */ + public function getPrimaryKeyDeclarationSQL(Index $index, $name = null) + { + if ( ! $index->isPrimary()) { + throw new \InvalidArgumentException( + 'Can only create primary key declarations with getPrimaryKeyDeclarationSQL()' + ); + } + + return $this->getTableConstraintDeclarationSQL($index, $name); + } + + /** + * {@inheritdoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET TEMPORARY OPTION isolation_level = ' . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritdoc} + */ + public function getSmallIntTypeDeclarationSQL(array $columnDef) + { + $columnDef['integer_type'] = 'SMALLINT'; + + return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * Returns the SQL statement for starting an existing database. + * + * In SQL Anywhere you can start and stop databases on a + * database server instance. + * This is a required statement after having created a new database + * as it has to be explicitly started to be usable. + * SQL Anywhere does not automatically start a database after creation! + * + * @param string $database Name of the database to start. + * + * @return string + */ + public function getStartDatabaseSQL($database) + { + $database = new Identifier($database); + + return "START DATABASE '" . $database->getName() . "' AUTOSTOP OFF"; + } + + /** + * Returns the SQL statement for stopping a running database. + * + * In SQL Anywhere you can start and stop databases on a + * database server instance. + * This is a required statement before dropping an existing database + * as it has to be explicitly stopped before it can be dropped. + * + * @param string $database Name of the database to stop. + * + * @return string + */ + public function getStopDatabaseSQL($database) + { + $database = new Identifier($database); + + return 'STOP DATABASE "' . $database->getName() . '" UNCONDITIONALLY'; + } + + /** + * {@inheritdoc} + */ + public function getSubstringExpression($value, $from, $length = null) + { + if (null === $length) { + return 'SUBSTRING(' . $value . ', ' . $from . ')'; + } + + return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $length . ')'; + } + + /** + * {@inheritdoc} + */ + public function getTemporaryTableSQL() + { + return 'GLOBAL TEMPORARY'; + } + + /** + * {@inheritdoc} + */ + public function getTimeFormatString() + { + return 'H:i:s.u'; + } + + /** + * {@inheritdoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + /** + * {@inheritdoc} + */ + public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) + { + if ( ! $char) { + switch ($pos) { + case self::TRIM_LEADING: + return $this->getLtrimExpression($str); + case self::TRIM_TRAILING: + return $this->getRtrimExpression($str); + default: + return 'TRIM(' . $str . ')'; + } + } + + $pattern = "'%[^' + $char + ']%'"; + + switch ($pos) { + case self::TRIM_LEADING: + return 'SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))'; + case self::TRIM_TRAILING: + return 'REVERSE(SUBSTR(REVERSE(' . $str . '), PATINDEX(' . $pattern . ', REVERSE(' . $str . '))))'; + default: + return + 'REVERSE(SUBSTR(REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))), ' . + 'PATINDEX(' . $pattern . ', REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))))))'; + } + } + + /** + * {@inheritdoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + return 'TRUNCATE TABLE ' . $tableName; + } + + /** + * {@inheritdoc} + */ + public function getUniqueConstraintDeclarationSQL($name, Index $index) + { + if ($index->isPrimary()) { + throw new \InvalidArgumentException( + 'Cannot create primary key constraint declarations with getUniqueConstraintDeclarationSQL().' + ); + } + + if ( ! $index->isUnique()) { + throw new \InvalidArgumentException( + 'Can only create unique constraint declarations, no common index declarations with ' . + 'getUniqueConstraintDeclarationSQL().' + ); + } + + return $this->getTableConstraintDeclarationSQL($index, $name); + } + + /** + * {@inheritdoc} + */ + public function getVarcharDefaultLength() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function getVarcharMaxLength() + { + return 32767; + } + + /** + * {@inheritdoc} + */ + public function hasNativeGuidType() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function supportsCommentOnStatement() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + $unsigned = ! empty($columnDef['unsigned']) ? 'UNSIGNED ' : ''; + $autoincrement = ! empty($columnDef['autoincrement']) ? ' IDENTITY' : ''; + + return $unsigned . $columnDef['integer_type'] . $autoincrement; + } + + /** + * {@inheritdoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) + { + $columnListSql = $this->getColumnDeclarationListSQL($columns); + $indexSql = array(); + + if ( ! empty($options['uniqueConstraints'])) { + foreach ((array) $options['uniqueConstraints'] as $name => $definition) { + $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); + } + } + + if ( ! empty($options['indexes'])) { + /** @var \Doctrine\DBAL\Schema\Index $index */ + foreach ((array) $options['indexes'] as $index) { + $indexSql[] = $this->getCreateIndexSQL($index, $tableName); + } + } + + if ( ! empty($options['primary'])) { + $flags = ''; + + if (isset($options['primary_index']) && $options['primary_index']->hasFlag('clustered')) { + $flags = ' CLUSTERED '; + } + + $columnListSql .= ', PRIMARY KEY' . $flags . ' (' . implode(', ', array_unique(array_values((array) $options['primary']))) . ')'; + } + + if ( ! empty($options['foreignKeys'])) { + foreach ((array) $options['foreignKeys'] as $definition) { + $columnListSql .= ', ' . $this->getForeignKeyDeclarationSQL($definition); + } + } + + $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql; + $check = $this->getCheckDeclarationSQL($columns); + + if ( ! empty($check)) { + $query .= ', ' . $check; + } + + $query .= ')'; + + return array_merge(array($query), $indexSql); + } + + /** + * {@inheritdoc} + */ + protected function _getTransactionIsolationLevelSQL($level) + { + switch ($level) { + case Connection::TRANSACTION_READ_UNCOMMITTED: + return 0; + case Connection::TRANSACTION_READ_COMMITTED: + return 1; + case Connection::TRANSACTION_REPEATABLE_READ: + return 2; + case Connection::TRANSACTION_SERIALIZABLE: + return 3; + default: + throw new \InvalidArgumentException('Invalid isolation level:' . $level); + } + } + + /** + * {@inheritdoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset) + { + $limitOffsetClause = ''; + + if ($limit > 0) { + $limitOffsetClause = 'TOP ' . $limit . ' '; + } + + if ($offset > 0) { + if ($limit == 0) { + $limitOffsetClause = 'TOP ALL '; + } + + $limitOffsetClause .= 'START AT ' . ($offset + 1) . ' '; + } + + if ($limitOffsetClause) { + return preg_replace('/^\s*(SELECT\s+(DISTINCT\s+)?)/i', '\1' . $limitOffsetClause, $query); + } + + return $query; + } + + /** + * Return the INDEX query section dealing with non-standard + * SQL Anywhere options. + * + * @param Index $index Index definition + * + * @return string + */ + protected function getAdvancedIndexOptionsSQL(Index $index) + { + $sql = ''; + + if ( ! $index->isPrimary() && $index->hasFlag('for_olap_workload')) { + $sql .= ' FOR OLAP WORKLOAD'; + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed + ? 'BINARY(' . ($length ?: $this->getBinaryDefaultLength()) . ')' + : 'VARBINARY(' . ($length ?: $this->getBinaryDefaultLength()) . ')'; + } + + /** + * Returns the SQL snippet for creating a table constraint. + * + * @param Constraint $constraint The table constraint to create the SQL snippet for. + * @param string|null $name The table constraint name to use if any. + * + * @return string + * + * @throws \InvalidArgumentException if the given table constraint type is not supported by this method. + */ + protected function getTableConstraintDeclarationSQL(Constraint $constraint, $name = null) + { + if ($constraint instanceof ForeignKeyConstraint) { + return $this->getForeignKeyDeclarationSQL($constraint); + } + + if ( ! $constraint instanceof Index) { + throw new \InvalidArgumentException('Unsupported constraint type: ' . get_class($constraint)); + } + + if ( ! $constraint->isPrimary() && ! $constraint->isUnique()) { + throw new \InvalidArgumentException( + 'Can only create primary, unique or foreign key constraint declarations, no common index declarations ' . + 'with getTableConstraintDeclarationSQL().' + ); + } + + $constraintColumns = $constraint->getQuotedColumns($this); + + if (empty($constraintColumns)) { + throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); + } + + $sql = ''; + $flags = ''; + + if ( ! empty($name)) { + $name = new Identifier($name); + $sql .= 'CONSTRAINT ' . $name->getQuotedName($this) . ' '; + } + + if ($constraint->hasFlag('clustered')) { + $flags = 'CLUSTERED '; + } + + if ($constraint->isPrimary()) { + return $sql . 'PRIMARY KEY ' . $flags . '('. $this->getIndexFieldDeclarationListSQL($constraintColumns) . ')'; + } + + return $sql . 'UNIQUE ' . $flags . '('. $this->getIndexFieldDeclarationListSQL($constraintColumns) . ')'; + } + + /** + * {@inheritdoc} + */ + protected function getCreateIndexSQLFlags(Index $index) + { + $type = ''; + if ($index->hasFlag('virtual')) { + $type .= 'VIRTUAL '; + } + + if ($index->isUnique()) { + $type .= 'UNIQUE '; + } + + if ($index->hasFlag('clustered')) { + $type .= 'CLUSTERED '; + } + + return $type; + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + return array( + 'ALTER INDEX ' . $oldIndexName . ' ON ' . $tableName . ' RENAME TO ' . $index->getQuotedName($this) + ); + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhereKeywords'; + } + + /** + * {@inheritdoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed + ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(' . $this->getVarcharDefaultLength() . ')') + : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(' . $this->getVarcharDefaultLength() . ')'); + } + + /** + * {@inheritdoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = array( + 'char' => 'string', + 'long nvarchar' => 'text', + 'long varchar' => 'text', + 'nchar' => 'string', + 'ntext' => 'text', + 'nvarchar' => 'string', + 'text' => 'text', + 'uniqueidentifierstr' => 'guid', + 'varchar' => 'string', + 'xml' => 'text', + 'bigint' => 'bigint', + 'unsigned bigint' => 'bigint', + 'bit' => 'boolean', + 'decimal' => 'decimal', + 'double' => 'float', + 'float' => 'float', + 'int' => 'integer', + 'integer' => 'integer', + 'unsigned int' => 'integer', + 'numeric' => 'decimal', + 'smallint' => 'smallint', + 'unsigned smallint', 'smallint', + 'tinyint' => 'smallint', + 'unsigned tinyint', 'smallint', + 'money' => 'decimal', + 'smallmoney' => 'decimal', + 'long varbit' => 'text', + 'varbit' => 'string', + 'date' => 'date', + 'datetime' => 'datetime', + 'smalldatetime' => 'datetime', + 'time' => 'time', + 'timestamp' => 'datetime', + 'binary' => 'binary', + 'image' => 'blob', + 'long binary' => 'blob', + 'uniqueidentifier' => 'guid', + 'varbinary' => 'binary', + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php index 8946854c1e..8b1184d195 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php @@ -53,6 +53,14 @@ class SQLServer2008Platform extends SQLServer2005Platform return 'TIME(0)'; } + /** + * {@inheritDoc} + */ + public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIMEOFFSET(6)'; + } + /** * {@inheritDoc} */ @@ -96,6 +104,7 @@ class SQLServer2008Platform extends SQLServer2005Platform $this->doctrineTypeMapping['datetime2'] = 'datetime'; $this->doctrineTypeMapping['date'] = 'date'; $this->doctrineTypeMapping['time'] = 'time'; + $this->doctrineTypeMapping['datetimeoffset'] = 'datetimetz'; } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php index d0c32f7088..75c1345002 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php @@ -20,8 +20,10 @@ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\LockMode; +use Doctrine\DBAL\Schema\Column; +use Doctrine\DBAL\Schema\ColumnDiff; +use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\TableDiff; -use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Table; @@ -39,43 +41,25 @@ use Doctrine\DBAL\Schema\Table; class SQLServerPlatform extends AbstractPlatform { /** - * {@inheritDoc} - */ - public function getDateDiffExpression($date1, $date2) - { - return 'DATEDIFF(day, ' . $date2 . ',' . $date1 . ')'; - } - - /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getDateAddDaysExpression($date, $days) + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { - return 'DATEADD(day, ' . $days . ', ' . $date . ')'; - } + $factorClause = ''; - /** - * {@inheritDoc} - */ - public function getDateSubDaysExpression($date, $days) - { - return 'DATEADD(day, -1 * ' . $days . ', ' . $date . ')'; - } + if ('-' === $operator) { + $factorClause = '-1 * '; + } - /** - * {@inheritDoc} - */ - public function getDateAddMonthExpression($date, $months) - { - return 'DATEADD(month, ' . $months . ', ' . $date . ')'; + return 'DATEADD(' . $unit . ', ' . $factorClause . $interval . ', ' . $date . ')'; } /** * {@inheritDoc} */ - public function getDateSubMonthExpression($date, $months) + public function getDateDiffExpression($date1, $date2) { - return 'DATEADD(month, -1 * ' . $months . ', ' . $date . ')'; + return 'DATEDIFF(day, ' . $date2 . ',' . $date1 . ')'; } /** @@ -115,6 +99,22 @@ class SQLServerPlatform extends AbstractPlatform return true; } + /** + * {@inheritdoc} + */ + public function getDefaultSchemaName() + { + return 'dbo'; + } + + /** + * {@inheritDoc} + */ + public function supportsColumnCollation() + { + return true; + } + /** * {@inheritDoc} */ @@ -147,6 +147,14 @@ class SQLServerPlatform extends AbstractPlatform return false; } + /** + * {@inheritDoc} + */ + public function getCreateSchemaSQL($schemaName) + { + return 'CREATE SCHEMA ' . $schemaName; + } + /** * {@inheritDoc} */ @@ -170,7 +178,7 @@ class SQLServerPlatform extends AbstractPlatform { if ($index instanceof Index) { $index = $index->getQuotedName($this); - } else if (!is_string($index)) { + } elseif (!is_string($index)) { throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); } @@ -194,6 +202,7 @@ class SQLServerPlatform extends AbstractPlatform protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) { $defaultConstraintsSql = array(); + $commentsSql = array(); // @todo does other code breaks because of this? // force primary keys to be not null @@ -207,6 +216,10 @@ class SQLServerPlatform extends AbstractPlatform $defaultConstraintsSql[] = 'ALTER TABLE ' . $tableName . ' ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $column); } + + if ( ! empty($column['comment']) || is_numeric($column['comment'])) { + $commentsSql[] = $this->getCreateColumnCommentSQL($tableName, $column['name'], $column['comment']); + } } $columnListSql = $this->getColumnDeclarationListSQL($columns); @@ -247,7 +260,7 @@ class SQLServerPlatform extends AbstractPlatform } } - return array_merge($sql, $defaultConstraintsSql); + return array_merge($sql, $commentsSql, $defaultConstraintsSql); } /** @@ -259,9 +272,41 @@ class SQLServerPlatform extends AbstractPlatform if ($index->hasFlag('nonclustered')) { $flags = ' NONCLUSTERED'; } + return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY' . $flags . ' (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')'; } + /** + * Returns the SQL statement for creating a column comment. + * + * SQL Server does not support native column comments, + * therefore the extended properties functionality is used + * as a workaround to store them. + * The property name used to store column comments is "MS_Description" + * which provides compatibility with SQL Server Management Studio, + * as column comments are stored in the same property there when + * specifying a column's "Description" attribute. + * + * @param string $tableName The quoted table name to which the column belongs. + * @param string $columnName The quoted column name to create the comment for. + * @param string $comment The column's comment. + * + * @return string + */ + protected function getCreateColumnCommentSQL($tableName, $columnName, $comment) + { + return $this->getAddExtendedPropertySQL( + 'MS_Description', + $comment, + 'SCHEMA', + 'dbo', + 'TABLE', + $tableName, + 'COLUMN', + $columnName + ); + } + /** * Returns the SQL snippet for declaring a default constraint. * @@ -278,11 +323,13 @@ class SQLServerPlatform extends AbstractPlatform throw new \InvalidArgumentException("Incomplete column definition. 'default' required."); } + $columnName = new Identifier($column['name']); + return ' CONSTRAINT ' . $this->generateDefaultConstraintName($table, $column['name']) . $this->getDefaultValueDeclarationSQL($column) . - ' FOR ' . $column['name']; + ' FOR ' . $columnName->getQuotedName($this); } /** @@ -323,7 +370,7 @@ class SQLServerPlatform extends AbstractPlatform if ($index->hasFlag('clustered')) { $type .= 'CLUSTERED '; - } else if ($index->hasFlag('nonclustered')) { + } elseif ($index->hasFlag('nonclustered')) { $type .= 'NONCLUSTERED '; } @@ -354,9 +401,10 @@ class SQLServerPlatform extends AbstractPlatform */ public function getAlterTableSQL(TableDiff $diff) { - $queryParts = array(); - $sql = array(); - $columnSql = array(); + $queryParts = array(); + $sql = array(); + $columnSql = array(); + $commentsSql = array(); /** @var \Doctrine\DBAL\Schema\Column $column */ foreach ($diff->addedColumns as $column) { @@ -368,8 +416,17 @@ class SQLServerPlatform extends AbstractPlatform $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); if (isset($columnDef['default'])) { - $columnDef['name'] = $column->getQuotedName($this); - $queryParts[] = 'ADD' . $this->getDefaultConstraintDeclarationSQL($diff->name, $columnDef); + $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); + } + + $comment = $this->getColumnComment($column); + + if ( ! empty($comment) || is_numeric($comment)) { + $commentsSql[] = $this->getCreateColumnCommentSQL( + $diff->name, + $column->getQuotedName($this), + $comment + ); } } @@ -387,28 +444,54 @@ class SQLServerPlatform extends AbstractPlatform continue; } - $fromColumn = $columnDiff->fromColumn; - $fromColumnDefault = isset($fromColumn) ? $fromColumn->getDefault() : null; - $column = $columnDiff->column; - $columnDef = $column->toArray(); - $columnDefaultHasChanged = $columnDiff->hasChanged('default'); + $column = $columnDiff->column; + $comment = $this->getColumnComment($column); + $hasComment = ! empty ($comment) || is_numeric($comment); + + if ($columnDiff->fromColumn instanceof Column) { + $fromComment = $this->getColumnComment($columnDiff->fromColumn); + $hasFromComment = ! empty ($fromComment) || is_numeric($fromComment); + + if ($hasFromComment && $hasComment && $fromComment != $comment) { + $commentsSql[] = $this->getAlterColumnCommentSQL( + $diff->name, + $column->getQuotedName($this), + $comment + ); + } elseif ($hasFromComment && ! $hasComment) { + $commentsSql[] = $this->getDropColumnCommentSQL($diff->name, $column->getQuotedName($this)); + } elseif ($hasComment) { + $commentsSql[] = $this->getCreateColumnCommentSQL( + $diff->name, + $column->getQuotedName($this), + $comment + ); + } + } else { + // todo: Original comment cannot be determined. What to do? Add, update, drop or skip? + } - /** - * Drop existing column default constraint - * if default value has changed and another - * default constraint already exists for the column. - */ - if ($columnDefaultHasChanged && null !== $fromColumnDefault) { - $queryParts[] = 'DROP CONSTRAINT ' . - $this->generateDefaultConstraintName($diff->name, $columnDiff->oldColumnName); + // Do not add query part if only comment has changed. + if ($columnDiff->hasChanged('comment') && count($columnDiff->changedProperties) === 1) { + continue; } + $requireDropDefaultConstraint = $this->alterColumnRequiresDropDefaultConstraint($columnDiff); + + if ($requireDropDefaultConstraint) { + $queryParts[] = $this->getAlterTableDropDefaultConstraintClause( + $diff->name, + $columnDiff->oldColumnName + ); + } + + $columnDef = $column->toArray(); + $queryParts[] = 'ALTER COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); - if ($columnDefaultHasChanged && isset($columnDef['default'])) { - $columnDef['name'] = $column->getQuotedName($this); - $queryParts[] = 'ADD' . $this->getDefaultConstraintDeclarationSQL($diff->name, $columnDef); + if (isset($columnDef['default']) && ($requireDropDefaultConstraint || $columnDiff->hasChanged('default'))) { + $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); } } @@ -417,28 +500,19 @@ class SQLServerPlatform extends AbstractPlatform continue; } - $sql[] = "sp_RENAME '". $diff->name. ".". $oldColumnName . "' , '".$column->getQuotedName($this)."', 'COLUMN'"; + $oldColumnName = new Identifier($oldColumnName); - $columnDef = $column->toArray(); - - /** - * Drop existing default constraint for the old column name - * if column has default value. - */ - if (isset($columnDef['default'])) { - $queryParts[] = 'DROP CONSTRAINT ' . - $this->generateDefaultConstraintName($diff->name, $oldColumnName); - } - - $queryParts[] = 'ALTER COLUMN ' . - $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); + $sql[] = "sp_RENAME '" . + $diff->getName($this)->getQuotedName($this) . "." . $oldColumnName->getQuotedName($this) . + "', '" . $column->getQuotedName($this) . "', 'COLUMN'"; - /** - * Readd default constraint for the new column name. - */ - if (isset($columnDef['default'])) { - $columnDef['name'] = $column->getQuotedName($this); - $queryParts[] = 'ADD' . $this->getDefaultConstraintDeclarationSQL($diff->name, $columnDef); + // Recreate default constraint with new column name if necessary (for future reference). + if ($column->getDefault() !== null) { + $queryParts[] = $this->getAlterTableDropDefaultConstraintClause( + $diff->name, + $oldColumnName->getQuotedName($this) + ); + $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); } } @@ -449,13 +523,13 @@ class SQLServerPlatform extends AbstractPlatform } foreach ($queryParts as $query) { - $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; } - $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff)); + $sql = array_merge($sql, $commentsSql); if ($diff->newName !== false) { - $sql[] = "sp_RENAME '" . $diff->name . "', '" . $diff->newName . "'"; + $sql[] = "sp_RENAME '" . $diff->getName($this)->getQuotedName($this) . "', '" . $diff->getNewName()->getName() . "'"; /** * Rename table's default constraints names @@ -471,13 +545,261 @@ class SQLServerPlatform extends AbstractPlatform "'" . $this->generateIdentifierName($diff->newName) . "') + ''', ''OBJECT'';' " . "FROM sys.default_constraints dc " . "JOIN sys.tables tbl ON dc.parent_object_id = tbl.object_id " . - "WHERE tbl.name = '" . $diff->newName . "';" . + "WHERE tbl.name = '" . $diff->getNewName()->getName() . "';" . "EXEC sp_executesql @sql"; } + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + return array_merge($sql, $tableSql, $columnSql); } + /** + * Returns the SQL clause for adding a default constraint in an ALTER TABLE statement. + * + * @param string $tableName The name of the table to generate the clause for. + * @param Column $column The column to generate the clause for. + * + * @return string + */ + private function getAlterTableAddDefaultConstraintClause($tableName, Column $column) + { + $columnDef = $column->toArray(); + $columnDef['name'] = $column->getQuotedName($this); + + return 'ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $columnDef); + } + + /** + * Returns the SQL clause for dropping an existing default constraint in an ALTER TABLE statement. + * + * @param string $tableName The name of the table to generate the clause for. + * @param string $columnName The name of the column to generate the clause for. + * + * @return string + */ + private function getAlterTableDropDefaultConstraintClause($tableName, $columnName) + { + return 'DROP CONSTRAINT ' . $this->generateDefaultConstraintName($tableName, $columnName); + } + + /** + * Checks whether a column alteration requires dropping its default constraint first. + * + * Different to other database vendors SQL Server implements column default values + * as constraints and therefore changes in a column's default value as well as changes + * in a column's type require dropping the default constraint first before being to + * alter the particular column to the new definition. + * + * @param ColumnDiff $columnDiff The column diff to evaluate. + * + * @return boolean True if the column alteration requires dropping its default constraint first, false otherwise. + */ + private function alterColumnRequiresDropDefaultConstraint(ColumnDiff $columnDiff) + { + // We can only decide whether to drop an existing default constraint + // if we know the original default value. + if ( ! $columnDiff->fromColumn instanceof Column) { + return false; + } + + // We only need to drop an existing default constraint if we know the + // column was defined with a default value before. + if ($columnDiff->fromColumn->getDefault() === null) { + return false; + } + + // We need to drop an existing default constraint if the column was + // defined with a default value before and it has changed. + if ($columnDiff->hasChanged('default')) { + return true; + } + + // We need to drop an existing default constraint if the column was + // defined with a default value before and the native column type has changed. + if ($columnDiff->hasChanged('type') || $columnDiff->hasChanged('fixed')) { + return true; + } + + return false; + } + + /** + * Returns the SQL statement for altering a column comment. + * + * SQL Server does not support native column comments, + * therefore the extended properties functionality is used + * as a workaround to store them. + * The property name used to store column comments is "MS_Description" + * which provides compatibility with SQL Server Management Studio, + * as column comments are stored in the same property there when + * specifying a column's "Description" attribute. + * + * @param string $tableName The quoted table name to which the column belongs. + * @param string $columnName The quoted column name to alter the comment for. + * @param string $comment The column's comment. + * + * @return string + */ + protected function getAlterColumnCommentSQL($tableName, $columnName, $comment) + { + return $this->getUpdateExtendedPropertySQL( + 'MS_Description', + $comment, + 'SCHEMA', + 'dbo', + 'TABLE', + $tableName, + 'COLUMN', + $columnName + ); + } + + /** + * Returns the SQL statement for dropping a column comment. + * + * SQL Server does not support native column comments, + * therefore the extended properties functionality is used + * as a workaround to store them. + * The property name used to store column comments is "MS_Description" + * which provides compatibility with SQL Server Management Studio, + * as column comments are stored in the same property there when + * specifying a column's "Description" attribute. + * + * @param string $tableName The quoted table name to which the column belongs. + * @param string $columnName The quoted column name to drop the comment for. + * + * @return string + */ + protected function getDropColumnCommentSQL($tableName, $columnName) + { + return $this->getDropExtendedPropertySQL( + 'MS_Description', + 'SCHEMA', + 'dbo', + 'TABLE', + $tableName, + 'COLUMN', + $columnName + ); + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + return array( + sprintf( + "EXEC sp_RENAME N'%s.%s', N'%s', N'INDEX'", + $tableName, + $oldIndexName, + $index->getQuotedName($this) + ) + ); + } + + /** + * Returns the SQL statement for adding an extended property to a database object. + * + * @param string $name The name of the property to add. + * @param string|null $value The value of the property to add. + * @param string|null $level0Type The type of the object at level 0 the property belongs to. + * @param string|null $level0Name The name of the object at level 0 the property belongs to. + * @param string|null $level1Type The type of the object at level 1 the property belongs to. + * @param string|null $level1Name The name of the object at level 1 the property belongs to. + * @param string|null $level2Type The type of the object at level 2 the property belongs to. + * @param string|null $level2Name The name of the object at level 2 the property belongs to. + * + * @return string + * + * @link http://msdn.microsoft.com/en-us/library/ms180047%28v=sql.90%29.aspx + */ + public function getAddExtendedPropertySQL( + $name, + $value = null, + $level0Type = null, + $level0Name = null, + $level1Type = null, + $level1Name = null, + $level2Type = null, + $level2Name = null + ) { + return "EXEC sp_addextendedproperty " . + "N" . $this->quoteStringLiteral($name) . ", N" . $this->quoteStringLiteral($value) . ", " . + "N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' . + "N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' . + "N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name; + } + + /** + * Returns the SQL statement for dropping an extended property from a database object. + * + * @param string $name The name of the property to drop. + * @param string|null $level0Type The type of the object at level 0 the property belongs to. + * @param string|null $level0Name The name of the object at level 0 the property belongs to. + * @param string|null $level1Type The type of the object at level 1 the property belongs to. + * @param string|null $level1Name The name of the object at level 1 the property belongs to. + * @param string|null $level2Type The type of the object at level 2 the property belongs to. + * @param string|null $level2Name The name of the object at level 2 the property belongs to. + * + * @return string + * + * @link http://technet.microsoft.com/en-gb/library/ms178595%28v=sql.90%29.aspx + */ + public function getDropExtendedPropertySQL( + $name, + $level0Type = null, + $level0Name = null, + $level1Type = null, + $level1Name = null, + $level2Type = null, + $level2Name = null + ) { + return "EXEC sp_dropextendedproperty " . + "N" . $this->quoteStringLiteral($name) . ", " . + "N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' . + "N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' . + "N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name; + } + + /** + * Returns the SQL statement for updating an extended property of a database object. + * + * @param string $name The name of the property to update. + * @param string|null $value The value of the property to update. + * @param string|null $level0Type The type of the object at level 0 the property belongs to. + * @param string|null $level0Name The name of the object at level 0 the property belongs to. + * @param string|null $level1Type The type of the object at level 1 the property belongs to. + * @param string|null $level1Name The name of the object at level 1 the property belongs to. + * @param string|null $level2Type The type of the object at level 2 the property belongs to. + * @param string|null $level2Name The name of the object at level 2 the property belongs to. + * + * @return string + * + * @link http://msdn.microsoft.com/en-us/library/ms186885%28v=sql.90%29.aspx + */ + public function getUpdateExtendedPropertySQL( + $name, + $value = null, + $level0Type = null, + $level0Name = null, + $level1Type = null, + $level1Name = null, + $level2Type = null, + $level2Name = null + ) { + return "EXEC sp_updateextendedproperty " . + "N" . $this->quoteStringLiteral($name) . ", N" . $this->quoteStringLiteral($value) . ", " . + "N" . $this->quoteStringLiteral($level0Type) . ", " . $level0Name . ', ' . + "N" . $this->quoteStringLiteral($level1Type) . ", " . $level1Name . ', ' . + "N" . $this->quoteStringLiteral($level2Type) . ", " . $level2Name; + } + /** * {@inheritDoc} */ @@ -492,7 +814,8 @@ class SQLServerPlatform extends AbstractPlatform public function getListTablesSQL() { // "sysdiagrams" table must be ignored as it's internal SQL Server table for Database Diagrams - return "SELECT name FROM sysobjects WHERE type = 'U' AND name != 'sysdiagrams' ORDER BY name"; + // Category 2 must be ignored as it is "MS SQL Server 'pseudo-system' object[s]" for replication + return "SELECT name FROM sysobjects WHERE type = 'U' AND name != 'sysdiagrams' AND category != 2 ORDER BY name"; } /** @@ -508,17 +831,24 @@ class SQLServerPlatform extends AbstractPlatform col.scale, col.precision, col.is_identity AS autoincrement, - col.collation_name AS collation + col.collation_name AS collation, + CAST(prop.value AS NVARCHAR(MAX)) AS comment -- CAST avoids driver error for sql_variant type FROM sys.columns AS col JOIN sys.types AS type ON col.user_type_id = type.user_type_id JOIN sys.objects AS obj ON col.object_id = obj.object_id + JOIN sys.schemas AS scm + ON obj.schema_id = scm.schema_id LEFT JOIN sys.default_constraints def ON col.default_object_id = def.object_id AND col.object_id = def.parent_object_id + LEFT JOIN sys.extended_properties AS prop + ON obj.object_id = prop.major_id + AND col.column_id = prop.minor_id + AND prop.name = 'MS_Description' WHERE obj.type = 'U' - AND obj.name = '$table'"; + AND " . $this->getTableWhereClause($table, 'scm.name', 'obj.name'); } /** @@ -539,7 +869,8 @@ class SQLServerPlatform extends AbstractPlatform INNER JOIN sys.foreign_key_columns AS fc INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id ON f.OBJECT_ID = fc.constraint_object_id - WHERE OBJECT_NAME (f.parent_object_id) = '" . $table . "'"; + WHERE " . + $this->getTableWhereClause($table, 'SCHEMA_NAME (f.schema_id)', 'OBJECT_NAME (f.parent_object_id)'); } /** @@ -549,19 +880,20 @@ class SQLServerPlatform extends AbstractPlatform { return "SELECT idx.name AS key_name, col.name AS column_name, - ~idx.is_unique AS non_unique, - idx.is_primary_key AS [primary], + ~idx.is_unique AS non_unique, + idx.is_primary_key AS [primary], CASE idx.type WHEN '1' THEN 'clustered' WHEN '2' THEN 'nonclustered' ELSE NULL END AS flags FROM sys.tables AS tbl + JOIN sys.schemas AS scm ON tbl.schema_id = scm.schema_id JOIN sys.indexes AS idx ON tbl.object_id = idx.object_id JOIN sys.index_columns AS idxcol ON idx.object_id = idxcol.object_id AND idx.index_id = idxcol.index_id JOIN sys.columns AS col ON idxcol.object_id = col.object_id AND idxcol.column_id = col.column_id - WHERE tbl.name = '$table' - ORDER BY idx.index_id ASC, idxcol.index_column_id ASC"; + WHERE " . $this->getTableWhereClause($table, 'scm.name', 'tbl.name') . " + ORDER BY idx.index_id ASC, idxcol.key_ordinal ASC"; } /** @@ -580,6 +912,27 @@ class SQLServerPlatform extends AbstractPlatform return "SELECT name FROM sysobjects WHERE type = 'V' ORDER BY name"; } + /** + * Returns the where clause to filter schema and table name in a query. + * + * @param string $table The full qualified name of the table. + * @param string $schemaColumn The name of the column to compare the schema to in the where clause. + * @param string $tableColumn The name of the column to compare the table to in the where clause. + * + * @return string + */ + private function getTableWhereClause($table, $schemaColumn, $tableColumn) + { + if (strpos($table, ".") !== false) { + list($schema, $table) = explode(".", $table); + $schema = "'" . $schema . "'"; + } else { + $schema = "SCHEMA_NAME()"; + } + + return "({$tableColumn} = '{$table}' AND {$schemaColumn} = {$schema})"; + } + /** * {@inheritDoc} */ @@ -678,6 +1031,14 @@ class SQLServerPlatform extends AbstractPlatform return 'SELECT * FROM sys.databases'; } + /** + * {@inheritDoc} + */ + public function getListNamespacesSQL() + { + return "SELECT name FROM sys.schemas WHERE name NOT IN('guest', 'INFORMATION_SCHEMA', 'sys')"; + } + /** * {@inheritDoc} */ @@ -746,12 +1107,28 @@ class SQLServerPlatform extends AbstractPlatform return $fixed ? ($length ? 'NCHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'NVARCHAR(' . $length . ')' : 'NVARCHAR(255)'); } + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 8000; + } + /** * {@inheritDoc} */ public function getClobTypeDeclarationSQL(array $field) { - return 'TEXT'; + return 'VARCHAR(MAX)'; } /** @@ -806,11 +1183,14 @@ class SQLServerPlatform extends AbstractPlatform $start = $offset + 1; $end = $offset + $limit; $orderBy = stristr($query, 'ORDER BY'); - $query = preg_replace('/\s+ORDER\s+BY\s+([^\)]*)/', '', $query); //Remove ORDER BY from $query - $format = 'SELECT * FROM (%s) AS doctrine_tbl WHERE doctrine_rownum BETWEEN %d AND %d'; + + //Remove ORDER BY from $query (including nested parentheses in order by list). + $query = preg_replace('/\s+ORDER\s+BY\s+([^()]+|\((?:(?:(?>[^()]+)|(?R))*)\))+/i', '', $query); + + $format = 'SELECT * FROM (%s) AS doctrine_tbl WHERE doctrine_rownum BETWEEN %d AND %d ORDER BY doctrine_rownum'; // Pattern to match "main" SELECT ... FROM clause (including nested parentheses in select list). - $selectFromPattern = '/^(\s*SELECT\s+(?:\((?>[^()]+)|(?:R)*\)|[^(])+)\sFROM\s/i'; + $selectFromPattern = '/^(\s*SELECT\s+(?:(.*)(?![^(]*\))))\sFROM\s/i'; if ( ! $orderBy) { //Replace only "main" FROM with OVER to prevent changing FROM also in subqueries. @@ -825,15 +1205,15 @@ class SQLServerPlatform extends AbstractPlatform } //Clear ORDER BY - $orderBy = preg_replace('/ORDER\s+BY\s+([^\)]*)(.*)/', '$1', $orderBy); + $orderBy = preg_replace('/ORDER\s+BY\s+(.*)/i', '$1', $orderBy); $orderByParts = explode(',', $orderBy); - $orderbyColumns = array(); + $orderByColumns = array(); //Split ORDER BY into parts foreach ($orderByParts as &$part) { if (preg_match('/(([^\s]*)\.)?([^\.\s]*)\s*(ASC|DESC)?/i', trim($part), $matches)) { - $orderbyColumns[] = array( + $orderByColumns[] = array( 'column' => $matches[3], 'hasTable' => ( ! empty($matches[2])), 'sort' => isset($matches[4]) ? $matches[4] : null, @@ -842,14 +1222,23 @@ class SQLServerPlatform extends AbstractPlatform } } - //Find alias for each colum used in ORDER BY - if ( ! empty($orderbyColumns)) { - foreach ($orderbyColumns as $column) { + $isWrapped = (preg_match('/SELECT DISTINCT .* FROM \(.*\) dctrn_result/', $query)) ? true : false; + + $overColumns = array(); + + //Find alias for each column used in ORDER BY + if ( ! empty($orderByColumns)) { + foreach ($orderByColumns as $column) { + $pattern = sprintf('/%s\.%s\s+(?:AS\s+)?([^,\s)]+)/i', $column['table'], $column['column']); - $pattern = sprintf('/%s\.(%s)\s*(AS)?\s*([^,\s\)]*)/i', $column['table'], $column['column']); - $overColumn = preg_match($pattern, $query, $matches) - ? ($column['hasTable'] ? $column['table'] . '.' : '') . $column['column'] - : $column['column']; + if ($isWrapped) { + $overColumn = preg_match($pattern, $query, $matches) + ? $matches[1] : ''; + } else { + $overColumn = preg_match($pattern, $query, $matches) + ? ($column['hasTable'] ? $column['table'] . '.' : '') . $column['column'] + : $column['column']; + } if (isset($column['sort'])) { $overColumn .= ' ' . $column['sort']; @@ -885,7 +1274,7 @@ class SQLServerPlatform extends AbstractPlatform $item[$key] = ($value) ? 1 : 0; } } - } else if (is_bool($item) || is_numeric($item)) { + } elseif (is_bool($item) || is_numeric($item)) { $item = ($item) ? 1 : 0; } @@ -967,7 +1356,6 @@ class SQLServerPlatform extends AbstractPlatform 'real' => 'float', 'double' => 'float', 'double precision' => 'float', - 'datetimeoffset' => 'datetimetz', 'smalldatetime' => 'datetime', 'datetime' => 'datetime', 'char' => 'string', @@ -976,9 +1364,9 @@ class SQLServerPlatform extends AbstractPlatform 'nchar' => 'string', 'nvarchar' => 'string', 'ntext' => 'text', - 'binary' => 'text', - 'varbinary' => 'blob', - 'image' => 'text', + 'binary' => 'binary', + 'varbinary' => 'binary', + 'image' => 'blob', 'uniqueidentifier' => 'guid', ); } @@ -1007,6 +1395,19 @@ class SQLServerPlatform extends AbstractPlatform return 'ROLLBACK TRANSACTION ' . $savepoint; } + /** + * {@inheritdoc} + */ + public function getForeignKeyReferentialActionSQL($action) + { + // RESTRICT is not supported, therefore falling back to NO ACTION. + if (strtoupper($action) === 'RESTRICT') { + return 'NO ACTION'; + } + + return parent::getForeignKeyReferentialActionSQL($action); + } + /** * {@inheritDoc} */ @@ -1080,11 +1481,11 @@ class SQLServerPlatform extends AbstractPlatform return " DEFAULT '" . $field['default'] . "'"; } - if (in_array((string) $field['type'], array('Integer', 'BigInteger', 'SmallInteger'))) { + if (in_array((string) $field['type'], array('Integer', 'BigInt', 'SmallInt'))) { return " DEFAULT " . $field['default']; } - if ((string) $field['type'] == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL()) { + if (in_array((string) $field['type'], array('DateTime', 'DateTimeTz')) && $field['default'] == $this->getCurrentTimestampSQL()) { return " DEFAULT " . $this->getCurrentTimestampSQL(); } @@ -1095,14 +1496,6 @@ class SQLServerPlatform extends AbstractPlatform return " DEFAULT '" . $field['default'] . "'"; } - /** - * {@inheritdoc} - */ - public function getColumnCollationDeclarationSQL($collation) - { - return 'COLLATE ' . $collation; - } - /** * {@inheritdoc} * @@ -1113,8 +1506,8 @@ class SQLServerPlatform extends AbstractPlatform if (isset($field['columnDefinition'])) { $columnDef = $this->getCustomTypeDeclarationSQL($field); } else { - $collation = (isset($field['collate']) && $field['collate']) ? - ' ' . $this->getColumnCollationDeclarationSQL($field['collate']) : ''; + $collation = (isset($field['collation']) && $field['collation']) ? + ' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : ''; $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; @@ -1153,6 +1546,9 @@ class SQLServerPlatform extends AbstractPlatform */ private function generateIdentifierName($identifier) { - return strtoupper(dechex(crc32($identifier))); + // Always generate name for unquoted identifiers to ensure consistency. + $identifier = new Identifier($identifier); + + return strtoupper(dechex(crc32($identifier->getName()))); } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php index ac3e3f425c..3d8a09b63e 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php @@ -20,10 +20,12 @@ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\Identifier; use Doctrine\DBAL\Schema\Constraint; /** @@ -43,7 +45,7 @@ class SqlitePlatform extends AbstractPlatform */ public function getRegexpExpression() { - return 'RLIKE'; + return 'REGEXP'; } /** @@ -123,43 +125,39 @@ class SqlitePlatform extends AbstractPlatform } /** - * {@inheritDoc} - */ - public function getDateDiffExpression($date1, $date2) - { - return 'ROUND(JULIANDAY('.$date1 . ')-JULIANDAY('.$date2.'))'; - } - - /** - * {@inheritDoc} + * {@inheritdoc} */ - public function getDateAddDaysExpression($date, $days) + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) { - return "DATE(" . $date . ",'+". $days . " day')"; - } + switch ($unit) { + case self::DATE_INTERVAL_UNIT_SECOND: + case self::DATE_INTERVAL_UNIT_MINUTE: + case self::DATE_INTERVAL_UNIT_HOUR: + return "DATETIME(" . $date . ",'" . $operator . $interval . " " . $unit . "')"; - /** - * {@inheritDoc} - */ - public function getDateSubDaysExpression($date, $days) - { - return "DATE(" . $date . ",'-". $days . " day')"; - } + default: + switch ($unit) { + case self::DATE_INTERVAL_UNIT_WEEK: + $interval *= 7; + $unit = self::DATE_INTERVAL_UNIT_DAY; + break; + + case self::DATE_INTERVAL_UNIT_QUARTER: + $interval *= 3; + $unit = self::DATE_INTERVAL_UNIT_MONTH; + break; + } - /** - * {@inheritDoc} - */ - public function getDateAddMonthExpression($date, $months) - { - return "DATE(" . $date . ",'+". $months . " month')"; + return "DATE(" . $date . ",'" . $operator . $interval . " " . $unit . "')"; + } } /** * {@inheritDoc} */ - public function getDateSubMonthExpression($date, $months) + public function getDateDiffExpression($date1, $date2) { - return "DATE(" . $date . ",'-". $months . " month')"; + return 'ROUND(JULIANDAY('.$date1 . ')-JULIANDAY('.$date2.'))'; } /** @@ -208,7 +206,7 @@ class SqlitePlatform extends AbstractPlatform */ public function getIntegerTypeDeclarationSQL(array $field) { - return $this->_getCommonIntegerTypeDeclarationSQL($field); + return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** @@ -216,7 +214,12 @@ class SqlitePlatform extends AbstractPlatform */ public function getBigIntTypeDeclarationSQL(array $field) { - return $this->_getCommonIntegerTypeDeclarationSQL($field); + // SQLite autoincrement is implicit for INTEGER PKs, but not for BIGINT fields. + if ( ! empty($field['autoincrement'])) { + return $this->getIntegerTypeDeclarationSQL($field); + } + + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** @@ -224,7 +227,12 @@ class SqlitePlatform extends AbstractPlatform */ public function getTinyIntTypeDeclarationSql(array $field) { - return $this->_getCommonIntegerTypeDeclarationSQL($field); + // SQLite autoincrement is implicit for INTEGER PKs, but not for TINYINT fields. + if ( ! empty($field['autoincrement'])) { + return $this->getIntegerTypeDeclarationSQL($field); + } + + return 'TINYINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** @@ -232,7 +240,12 @@ class SqlitePlatform extends AbstractPlatform */ public function getSmallIntTypeDeclarationSQL(array $field) { - return $this->_getCommonIntegerTypeDeclarationSQL($field); + // SQLite autoincrement is implicit for INTEGER PKs, but not for SMALLINT fields. + if ( ! empty($field['autoincrement'])) { + return $this->getIntegerTypeDeclarationSQL($field); + } + + return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** @@ -240,7 +253,12 @@ class SqlitePlatform extends AbstractPlatform */ public function getMediumIntTypeDeclarationSql(array $field) { - return $this->_getCommonIntegerTypeDeclarationSQL($field); + // SQLite autoincrement is implicit for INTEGER PKs, but not for MEDIUMINT fields. + if ( ! empty($field['autoincrement'])) { + return $this->getIntegerTypeDeclarationSQL($field); + } + + return 'MEDIUMINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); } /** @@ -272,7 +290,12 @@ class SqlitePlatform extends AbstractPlatform */ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) { - return 'INTEGER'; + // sqlite autoincrement is implicit for integer PKs, but not when the field is unsigned + if ( ! empty($columnDef['autoincrement'])) { + return ''; + } + + return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : ''; } /** @@ -344,6 +367,30 @@ class SqlitePlatform extends AbstractPlatform : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); } + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return 'BLOB'; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function getBinaryDefaultLength() + { + return 0; + } + /** * {@inheritDoc} */ @@ -437,6 +484,14 @@ class SqlitePlatform extends AbstractPlatform return true; } + /** + * {@inheritDoc} + */ + public function supportsColumnCollation() + { + return true; + } + /** * {@inheritDoc} */ @@ -489,9 +544,16 @@ class SqlitePlatform extends AbstractPlatform */ static public function udfLocate($str, $substr, $offset = 0) { + // SQL's LOCATE function works on 1-based positions, while PHP's strpos works on 0-based positions. + // So we have to make them compatible if an offset is given. + if ($offset > 0) { + $offset -= 1; + } + $pos = strpos($str, $substr, $offset); + if ($pos !== false) { - return $pos+1; + return $pos + 1; } return 0; @@ -583,18 +645,30 @@ class SqlitePlatform extends AbstractPlatform } $sql = array(); - $tableName = $diff->newName ?: $diff->name; + $tableName = $diff->newName ? $diff->getNewName(): $diff->getName($this); foreach ($this->getIndexesInAlteredTable($diff) as $index) { if ($index->isPrimary()) { continue; } - $sql[] = $this->getCreateIndexSQL($index, $tableName); + $sql[] = $this->getCreateIndexSQL($index, $tableName->getQuotedName($this)); } return $sql; } + /** + * {@inheritDoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset) + { + if (null === $limit && null !== $offset) { + return $query . ' LIMIT -1 OFFSET ' . $offset; + } + + return parent::doModifyLimitQuery($query, $limit, $offset); + } + /** * {@inheritDoc} */ @@ -774,7 +848,7 @@ class SqlitePlatform extends AbstractPlatform if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { $dataTable = new Table('__temp__'.$table->getName()); - $newTable = new Table($table->getName(), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions()); + $newTable = new Table($table->getQuotedName($this), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions()); $newTable->addOption('alter', true); $sql = $this->getPreAlterTableIndexForeignKeySQL($diff); @@ -787,7 +861,7 @@ class SqlitePlatform extends AbstractPlatform $sql[] = $this->getDropTableSQL($dataTable); if ($diff->newName && $diff->newName != $diff->name) { - $renamedTable = new Table($diff->newName); + $renamedTable = $diff->getNewName(); $sql[] = 'ALTER TABLE '.$newTable->getQuotedName($this).' RENAME TO '.$renamedTable->getQuotedName($this); } @@ -804,9 +878,33 @@ class SqlitePlatform extends AbstractPlatform */ private function getSimpleAlterTableSQL(TableDiff $diff) { + // Suppress changes on integer type autoincrement columns. + foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { + if ( ! $columnDiff->fromColumn instanceof Column || + ! $columnDiff->column instanceof Column || + ! $columnDiff->column->getAutoincrement() || + ! (string) $columnDiff->column->getType() === 'Integer' + ) { + continue; + } + + if ( ! $columnDiff->hasChanged('type') && $columnDiff->hasChanged('unsigned')) { + unset($diff->changedColumns[$oldColumnName]); + + continue; + } + + $fromColumnType = (string) $columnDiff->fromColumn->getType(); + + if ($fromColumnType === 'SmallInt' || $fromColumnType === 'BigInt') { + unset($diff->changedColumns[$oldColumnName]); + } + } + if ( ! empty($diff->renamedColumns) || ! empty($diff->addedForeignKeys) || ! empty($diff->addedIndexes) || ! empty($diff->changedColumns) || ! empty($diff->changedForeignKeys) || ! empty($diff->changedIndexes) || ! empty($diff->removedColumns) || ! empty($diff->removedForeignKeys) || ! empty($diff->removedIndexes) + || ! empty($diff->renamedIndexes) ) { return false; } @@ -842,7 +940,7 @@ class SqlitePlatform extends AbstractPlatform if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ($diff->newName !== false) { - $newTable = new Table($diff->newName); + $newTable = new Identifier($diff->newName); $sql[] = 'ALTER TABLE '.$table->getQuotedName($this).' RENAME TO '.$newTable->getQuotedName($this); } } @@ -900,6 +998,12 @@ class SqlitePlatform extends AbstractPlatform $columnNames = $this->getColumnNamesInAlteredTable($diff); foreach ($indexes as $key => $index) { + foreach ($diff->renamedIndexes as $oldIndexName => $renamedIndex) { + if (strtolower($key) === strtolower($oldIndexName)) { + unset($indexes[$key]); + } + } + $changed = false; $indexColumns = array(); foreach ($index->getColumns() as $columnName) { @@ -927,7 +1031,7 @@ class SqlitePlatform extends AbstractPlatform } } - foreach (array_merge($diff->changedIndexes, $diff->addedIndexes) as $index) { + foreach (array_merge($diff->changedIndexes, $diff->addedIndexes, $diff->renamedIndexes) as $index) { $indexName = strtolower($index->getName()); if (strlen($indexName)) { $indexes[$indexName] = $index; @@ -1007,4 +1111,3 @@ class SqlitePlatform extends AbstractPlatform return $primaryIndex; } } - diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Connection.php index f6a3896690..df6b957a8d 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Connection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Connection.php @@ -19,7 +19,6 @@ namespace Doctrine\DBAL\Portability; -use Doctrine\DBAL\Driver; use Doctrine\DBAL\Cache\QueryCacheProfile; /** @@ -37,11 +36,13 @@ class Connection extends \Doctrine\DBAL\Connection const PORTABILITY_EMPTY_TO_NULL = 4; const PORTABILITY_FIX_CASE = 8; + const PORTABILITY_DB2 = 13; const PORTABILITY_ORACLE = 9; const PORTABILITY_POSTGRESQL = 13; const PORTABILITY_SQLITE = 13; const PORTABILITY_OTHERVENDORS = 12; const PORTABILITY_DRIZZLE = 13; + const PORTABILITY_SQLANYWHERE = 13; const PORTABILITY_SQLSRV = 13; /** @@ -63,16 +64,20 @@ class Connection extends \Doctrine\DBAL\Connection if ($ret) { $params = $this->getParams(); if (isset($params['portability'])) { - if ($this->_platform->getName() === "oracle") { + if ($this->getDatabasePlatform()->getName() === "oracle") { $params['portability'] = $params['portability'] & self::PORTABILITY_ORACLE; - } else if ($this->_platform->getName() === "postgresql") { + } elseif ($this->getDatabasePlatform()->getName() === "postgresql") { $params['portability'] = $params['portability'] & self::PORTABILITY_POSTGRESQL; - } else if ($this->_platform->getName() === "sqlite") { + } elseif ($this->getDatabasePlatform()->getName() === "sqlite") { $params['portability'] = $params['portability'] & self::PORTABILITY_SQLITE; - } else if ($this->_platform->getName() === "drizzle") { + } elseif ($this->getDatabasePlatform()->getName() === "drizzle") { $params['portability'] = self::PORTABILITY_DRIZZLE; - } else if ($this->_platform->getName() === 'sqlsrv') { - $params['portability'] = $params['portabililty'] & self::PORTABILITY_SQLSRV; + } elseif ($this->getDatabasePlatform()->getName() === 'sqlanywhere') { + $params['portability'] = self::PORTABILITY_SQLANYWHERE; + } elseif ($this->getDatabasePlatform()->getName() === 'db2') { + $params['portability'] = self::PORTABILITY_DB2; + } elseif ($this->getDatabasePlatform()->getName() === 'mssql') { + $params['portability'] = $params['portability'] & self::PORTABILITY_SQLSRV; } else { $params['portability'] = $params['portability'] & self::PORTABILITY_OTHERVENDORS; } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php index 29bc8b6a4d..352fda9d76 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php @@ -66,9 +66,9 @@ class Statement implements \IteratorAggregate, \Doctrine\DBAL\Driver\Statement /** * {@inheritdoc} */ - public function bindParam($column, &$variable, $type = null,$length = null) + public function bindParam($column, &$variable, $type = null, $length = null) { - return $this->stmt->bindParam($column, $variable, $type); + return $this->stmt->bindParam($column, $variable, $type, $length); } /** * {@inheritdoc} @@ -203,7 +203,7 @@ class Statement implements \IteratorAggregate, \Doctrine\DBAL\Driver\Statement foreach ($row as $k => $v) { if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') { $row[$k] = null; - } else if (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) { + } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) { $row[$k] = rtrim($v); } } @@ -222,7 +222,7 @@ class Statement implements \IteratorAggregate, \Doctrine\DBAL\Driver\Statement if ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) { if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $value === '') { $value = null; - } else if (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) { + } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) { $value = rtrim($value); } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php index 5f2b3cfa65..2736fcf226 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php @@ -258,12 +258,12 @@ class ExpressionBuilder { return $this->comparison($x, 'LIKE', $y); } - + /** * Creates a NOT LIKE() comparison expression with the given arguments. * * @param string $x Field in string format to be inspected by NOT LIKE() comparison. - * @param mixed $y Argument to be used in NOT LIKE() comparison. + * @param mixed $y Argument to be used in NOT LIKE() comparison. * * @return string */ @@ -275,27 +275,27 @@ class ExpressionBuilder /** * Creates a IN () comparison expression with the given arguments. * - * @param string $x The field in string format to be inspected by IN() comparison. - * @param array $y The array of values to be used by IN() comparison. + * @param string $x The field in string format to be inspected by IN() comparison. + * @param string|array $y The placeholder or the array of values to be used by IN() comparison. * * @return string */ - public function in($x, array $y) + public function in($x, $y) { - return $this->comparison($x, 'IN', '('.implode(', ', $y).')'); + return $this->comparison($x, 'IN', '('.implode(', ', (array) $y).')'); } /** * Creates a NOT IN () comparison expression with the given arguments. * - * @param string $x The field in string format to be inspected by NOT IN() comparison. - * @param array $y The array of values to be used by NOT IN() comparison. + * @param string $x The field in string format to be inspected by NOT IN() comparison. + * @param string|array $y The placeholder or the array of values to be used by NOT IN() comparison. * * @return string */ - public function notIn($x, array $y) + public function notIn($x, $y) { - return $this->comparison($x, 'NOT IN', '('.implode(', ', $y).')'); + return $this->comparison($x, 'NOT IN', '('.implode(', ', (array) $y).')'); } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php index ff5682366d..0a6d59e374 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php @@ -45,6 +45,7 @@ class QueryBuilder const SELECT = 0; const DELETE = 1; const UPDATE = 2; + const INSERT = 3; /* * The builder states. @@ -70,7 +71,8 @@ class QueryBuilder 'where' => null, 'groupBy' => array(), 'having' => null, - 'orderBy' => array() + 'orderBy' => array(), + 'values' => array(), ); /** @@ -196,7 +198,7 @@ class QueryBuilder * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate} * for insert, update and delete statements. * - * @return mixed + * @return \Doctrine\DBAL\Driver\Statement|int */ public function execute() { @@ -226,6 +228,9 @@ class QueryBuilder } switch ($this->type) { + case self::INSERT: + $sql = $this->getSQLForInsert(); + break; case self::DELETE: $sql = $this->getSQLForDelete(); break; @@ -302,9 +307,9 @@ class QueryBuilder } /** - * Gets all defined query parameters for the query being constructed. + * Gets all defined query parameters for the query being constructed indexed by parameter index or name. * - * @return array The currently defined query parameters. + * @return array The currently defined query parameters indexed by parameter index or name. */ public function getParameters() { @@ -323,6 +328,28 @@ class QueryBuilder return isset($this->params[$key]) ? $this->params[$key] : null; } + /** + * Gets all defined query parameter types for the query being constructed indexed by parameter index or name. + * + * @return array The currently defined query parameter types indexed by parameter index or name. + */ + public function getParameterTypes() + { + return $this->paramTypes; + } + + /** + * Gets a (previously set) query parameter type of the query being constructed. + * + * @param mixed $key The key (index or name) of the bound parameter type. + * + * @return mixed The value of the bound parameter type. + */ + public function getParameterType($key) + { + return isset($this->paramTypes[$key]) ? $this->paramTypes[$key] : null; + } + /** * Sets the position of the first result to retrieve (the "offset"). * @@ -403,10 +430,10 @@ class QueryBuilder foreach ($sqlPart as $part) { $this->sqlParts[$sqlPartName][] = $part; } - } else if ($isArray && is_array($sqlPart[key($sqlPart)])) { + } elseif ($isArray && is_array($sqlPart[key($sqlPart)])) { $key = key($sqlPart); $this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key]; - } else if ($isMultiple) { + } elseif ($isMultiple) { $this->sqlParts[$sqlPartName][] = $sqlPart; } else { $this->sqlParts[$sqlPartName] = $sqlPart; @@ -536,6 +563,38 @@ class QueryBuilder )); } + /** + * Turns the query being built into an insert query that inserts into + * a certain table + * + * + * $qb = $conn->createQueryBuilder() + * ->insert('users') + * ->values( + * array( + * 'name' => '?', + * 'password' => '?' + * ) + * ); + * + * + * @param string $insert The table into which the rows should be inserted. + * + * @return QueryBuilder This QueryBuilder instance. + */ + public function insert($insert = null) + { + $this->type = self::INSERT; + + if ( ! $insert) { + return $this; + } + + return $this->add('from', array( + 'table' => $insert + )); + } + /** * Creates and adds a query root corresponding to the table identified by the * given alias, forming a cartesian product with any existing query roots. @@ -546,12 +605,12 @@ class QueryBuilder * ->from('users', 'u') * * - * @param string $from The table. - * @param string $alias The alias of the table. + * @param string $from The table. + * @param string|null $alias The alias of the table. * - * @return \Doctrine\DBAL\Query\QueryBuilder This QueryBuilder instance. + * @return QueryBuilder This QueryBuilder instance. */ - public function from($from, $alias) + public function from($from, $alias = null) { return $this->add('from', array( 'table' => $from, @@ -716,7 +775,7 @@ class QueryBuilder */ public function where($predicates) { - if ( ! (func_num_args() == 1 && $predicates instanceof CompositeExpression) ) { + if ( ! (func_num_args() == 1 && $predicates instanceof CompositeExpression)) { $predicates = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); } @@ -743,8 +802,8 @@ class QueryBuilder */ public function andWhere($where) { - $where = $this->getQueryPart('where'); $args = func_get_args(); + $where = $this->getQueryPart('where'); if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) { $where->addMultiple($args); @@ -776,8 +835,8 @@ class QueryBuilder */ public function orWhere($where) { - $where = $this->getQueryPart('where'); $args = func_get_args(); + $where = $this->getQueryPart('where'); if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) { $where->addMultiple($args); @@ -842,6 +901,56 @@ class QueryBuilder return $this->add('groupBy', $groupBy, true); } + /** + * Sets a value for a column in an insert query. + * + * + * $qb = $conn->createQueryBuilder() + * ->insert('users') + * ->values( + * array( + * 'name' => '?' + * ) + * ) + * ->setValue('password', '?'); + * + * + * @param string $column The column into which the value should be inserted. + * @param string $value The value that should be inserted into the column. + * + * @return QueryBuilder This QueryBuilder instance. + */ + public function setValue($column, $value) + { + $this->sqlParts['values'][$column] = $value; + + return $this; + } + + /** + * Specifies values for an insert query indexed by column names. + * Replaces any previous values, if any. + * + * + * $qb = $conn->createQueryBuilder() + * ->insert('users') + * ->values( + * array( + * 'name' => '?', + * 'password' => '?' + * ) + * ); + * + * + * @param array $values The values to specify for the insert query indexed by column names. + * + * @return QueryBuilder This QueryBuilder instance. + */ + public function values(array $values) + { + return $this->add('values', $values); + } + /** * Specifies a restriction over the groups of the query. * Replaces any previous having restrictions, if any. @@ -869,8 +978,8 @@ class QueryBuilder */ public function andHaving($having) { - $having = $this->getQueryPart('having'); $args = func_get_args(); + $having = $this->getQueryPart('having'); if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) { $having->addMultiple($args); @@ -892,8 +1001,8 @@ class QueryBuilder */ public function orHaving($having) { - $having = $this->getQueryPart('having'); $args = func_get_args(); + $having = $this->getQueryPart('having'); if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) { $having->addMultiple($args); @@ -1000,33 +1109,83 @@ class QueryBuilder { $query = 'SELECT ' . implode(', ', $this->sqlParts['select']) . ' FROM '; + $query .= implode(', ', $this->getFromClauses()) + . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '') + . ($this->sqlParts['groupBy'] ? ' GROUP BY ' . implode(', ', $this->sqlParts['groupBy']) : '') + . ($this->sqlParts['having'] !== null ? ' HAVING ' . ((string) $this->sqlParts['having']) : '') + . ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : ''); + + if ($this->isLimitQuery()) { + return $this->connection->getDatabasePlatform()->modifyLimitQuery( + $query, + $this->maxResults, + $this->firstResult + ); + } + + return $query; + } + + /** + * @return string[] + */ + private function getFromClauses() + { $fromClauses = array(); $knownAliases = array(); // Loop through all FROM clauses foreach ($this->sqlParts['from'] as $from) { - $knownAliases[$from['alias']] = true; - $fromClause = $from['table'] . ' ' . $from['alias'] - . $this->getSQLForJoins($from['alias'], $knownAliases); + if ($from['alias'] === null) { + $tableSql = $from['table']; + $tableReference = $from['table']; + } else { + $tableSql = $from['table'] . ' ' . $from['alias']; + $tableReference = $from['alias']; + } + + $knownAliases[$tableReference] = true; - $fromClauses[$from['alias']] = $fromClause; + $fromClauses[$tableReference] = $tableSql . $this->getSQLForJoins($tableReference, $knownAliases); } + $this->verifyAllAliasesAreKnown($knownAliases); + + return $fromClauses; + } + + /** + * @param array $knownAliases + * + * @throws QueryException + */ + private function verifyAllAliasesAreKnown(array $knownAliases) + { foreach ($this->sqlParts['join'] as $fromAlias => $joins) { - if ( ! isset($knownAliases[$fromAlias]) ) { + if ( ! isset($knownAliases[$fromAlias])) { throw QueryException::unknownAlias($fromAlias, array_keys($knownAliases)); } } + } - $query .= implode(', ', $fromClauses) - . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '') - . ($this->sqlParts['groupBy'] ? ' GROUP BY ' . implode(', ', $this->sqlParts['groupBy']) : '') - . ($this->sqlParts['having'] !== null ? ' HAVING ' . ((string) $this->sqlParts['having']) : '') - . ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : ''); + /** + * @return bool + */ + private function isLimitQuery() + { + return $this->maxResults !== null || $this->firstResult !== null; + } - return ($this->maxResults === null && $this->firstResult == null) - ? $query - : $this->connection->getDatabasePlatform()->modifyLimitQuery($query, $this->maxResults, $this->firstResult); + /** + * Converts this instance into an INSERT string in SQL. + * + * @return string + */ + private function getSQLForInsert() + { + return 'INSERT INTO ' . $this->sqlParts['from']['table'] . + ' (' . implode(', ', array_keys($this->sqlParts['values'])) . ')' . + ' VALUES(' . implode(', ', $this->sqlParts['values']) . ')'; } /** @@ -1038,8 +1197,8 @@ class QueryBuilder { $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); $query = 'UPDATE ' . $table - . ' SET ' . implode(", ", $this->sqlParts['set']) - . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); + . ' SET ' . implode(", ", $this->sqlParts['set']) + . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); return $query; } @@ -1097,9 +1256,9 @@ class QueryBuilder * * @return string the placeholder name used. */ - public function createNamedParameter( $value, $type = \PDO::PARAM_STR, $placeHolder = null ) + public function createNamedParameter($value, $type = \PDO::PARAM_STR, $placeHolder = null) { - if ( $placeHolder === null ) { + if ($placeHolder === null) { $this->boundCounter++; $placeHolder = ":dcValue" . $this->boundCounter; } @@ -1134,6 +1293,7 @@ class QueryBuilder { $this->boundCounter++; $this->setParameter($this->boundCounter, $value, $type); + return "?"; } @@ -1149,11 +1309,16 @@ class QueryBuilder if (isset($this->sqlParts['join'][$fromAlias])) { foreach ($this->sqlParts['join'][$fromAlias] as $join) { + if (array_key_exists($join['joinAlias'], $knownAliases)) { + throw QueryException::nonUniqueAlias($join['joinAlias'], array_keys($knownAliases)); + } $sql .= ' ' . strtoupper($join['joinType']) - . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias'] - . ' ON ' . ((string) $join['joinCondition']); + . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias'] + . ' ON ' . ((string) $join['joinCondition']); $knownAliases[$join['joinAlias']] = true; + } + foreach ($this->sqlParts['join'][$fromAlias] as $join) { $sql .= $this->getSQLForJoins($join['joinAlias'], $knownAliases); } } @@ -1175,13 +1340,13 @@ class QueryBuilder $this->sqlParts[$part][$idx] = clone $element; } } - } else if (is_object($elements)) { + } elseif (is_object($elements)) { $this->sqlParts[$part] = clone $elements; } } foreach ($this->params as $name => $param) { - if(is_object($param)){ + if (is_object($param)) { $this->params[$name] = clone $param; } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php index aeeaab396d..92c9336d6e 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php @@ -38,4 +38,17 @@ class QueryException extends DBALException "any FROM or JOIN clause table. The currently registered " . "aliases are: " . implode(", ", $registeredAliases) . "."); } + + /** + * @param string $alias + * @param array $registeredAliases + * + * @return \Doctrine\DBAL\Query\QueryException + */ + static public function nonUniqueAlias($alias, $registeredAliases) + { + return new self("The given alias '" . $alias . "' is not unique " . + "in FROM and JOIN clause table. The currently registered " . + "aliases are: " . implode(", ", $registeredAliases) . "."); + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtils.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtils.php index cd1e0c7795..a9037ffc5f 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtils.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtils.php @@ -35,6 +35,7 @@ class SQLParserUtils const ESCAPED_SINGLE_QUOTED_TEXT = "'(?:[^'\\\\]|\\\\'?)*'"; const ESCAPED_DOUBLE_QUOTED_TEXT = '"(?:[^"\\\\]|\\\\"?)*"'; const ESCAPED_BACKTICK_QUOTED_TEXT = '`(?:[^`\\\\]|\\\\`?)*`'; + const ESCAPED_BRACKET_QUOTED_TEXT = '\[(?:[^\]])*\]'; /** * Gets an array of the placeholders in an sql statements as keys and their positions in the query string. @@ -89,6 +90,11 @@ class SQLParserUtils $arrayPositions = array(); $bindIndex = -1; + if ($isPositional) { + ksort($params); + ksort($types); + } + foreach ($types as $name => $type) { ++$bindIndex; @@ -112,6 +118,8 @@ class SQLParserUtils if ($isPositional) { $paramOffset = 0; $queryOffset = 0; + $params = array_values($params); + $types = array_values($types); foreach ($paramPos as $needle => $needlePos) { if ( ! isset($arrayPositions[$needle])) { @@ -195,8 +203,9 @@ class SQLParserUtils { $literal = self::ESCAPED_SINGLE_QUOTED_TEXT . '|' . self::ESCAPED_DOUBLE_QUOTED_TEXT . '|' . - self::ESCAPED_BACKTICK_QUOTED_TEXT; - preg_match_all("/([^'\"`]+)(?:$literal)?/s", $statement, $fragments, PREG_OFFSET_CAPTURE); + self::ESCAPED_BACKTICK_QUOTED_TEXT . '|' . + self::ESCAPED_BRACKET_QUOTED_TEXT; + preg_match_all("/([^'\"`\[]+)(?:$literal)?/s", $statement, $fragments, PREG_OFFSET_CAPTURE); return $fragments[1]; } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php index 6ac6e9051f..25c7209c7b 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php @@ -24,7 +24,7 @@ namespace Doctrine\DBAL; /** * Doctrine\DBAL\ConnectionException * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @license http://www.opensource.org/licenses/mit-license.php MIT * @link www.doctrine-project.org * @since 2.4 * @author Lars Strojny diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractAsset.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractAsset.php index 2159b029b7..051dce92c4 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractAsset.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractAsset.php @@ -99,7 +99,7 @@ abstract class AbstractAsset * The shortest name is stripped of the default namespace. All other * namespaced elements are returned as full-qualified names. * - * @param string + * @param string $defaultNamespaceName * * @return string */ @@ -155,7 +155,7 @@ abstract class AbstractAsset */ protected function isIdentifierQuoted($identifier) { - return (isset($identifier[0]) && ($identifier[0] == '`' || $identifier[0] == '"')); + return (isset($identifier[0]) && ($identifier[0] == '`' || $identifier[0] == '"' || $identifier[0] == '[')); } /** @@ -167,7 +167,7 @@ abstract class AbstractAsset */ protected function trimQuotes($identifier) { - return str_replace(array('`', '"'), '', $identifier); + return str_replace(array('`', '"', '[', ']'), '', $identifier); } /** @@ -180,6 +180,7 @@ abstract class AbstractAsset if ($this->_namespace) { return $this->_namespace . "." . $this->_name; } + return $this->_name; } @@ -217,7 +218,7 @@ abstract class AbstractAsset */ protected function _generateIdentifierName($columnNames, $prefix='', $maxSize=30) { - $hash = implode("", array_map(function($column) { + $hash = implode("", array_map(function ($column) { return dechex(crc32($column)); }, $columnNames)); diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php index 72fb530d3b..19dfa9369b 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php @@ -22,7 +22,6 @@ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Events; use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs; use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; -use Doctrine\DBAL\Types; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Platforms\AbstractPlatform; @@ -115,6 +114,20 @@ abstract class AbstractSchemaManager return $this->_getPortableDatabasesList($databases); } + /** + * Returns a list of all namespaces in the current database. + * + * @return array + */ + public function listNamespaceNames() + { + $sql = $this->_platform->getListNamespacesSQL(); + + $namespaces = $this->_conn->fetchAll($sql); + + return $this->getPortableNamespacesList($namespaces); + } + /** * Lists the available sequences for this connection. * @@ -189,7 +202,7 @@ abstract class AbstractSchemaManager */ public function tablesExist($tableNames) { - $tableNames = array_map('strtolower', (array)$tableNames); + $tableNames = array_map('strtolower', (array) $tableNames); return count($tableNames) == count(\array_intersect($tableNames, array_map('strtolower', $this->listTableNames()))); } @@ -224,9 +237,10 @@ abstract class AbstractSchemaManager return $assetNames; } - return array_values ( + return array_values( array_filter($assetNames, function ($assetName) use ($filterExpr) { $assetName = ($assetName instanceof AbstractAsset) ? $assetName->getName() : $assetName; + return preg_match($filterExpr, $assetName); }) ); @@ -326,13 +340,13 @@ abstract class AbstractSchemaManager /** * Drops the given table. * - * @param string $table The name of the table to drop. + * @param string $tableName The name of the table to drop. * * @return void */ - public function dropTable($table) + public function dropTable($tableName) { - $this->_execSql($this->_platform->getDropTableSQL($table)); + $this->_execSql($this->_platform->getDropTableSQL($tableName)); } /** @@ -345,7 +359,7 @@ abstract class AbstractSchemaManager */ public function dropIndex($index, $table) { - if($index instanceof Index) { + if ($index instanceof Index) { $index = $index->getQuotedName($this->_platform); } @@ -651,6 +665,24 @@ abstract class AbstractSchemaManager return $list; } + /** + * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition. + * + * @param array $namespaces The list of namespace names in the native DBMS data definition. + * + * @return array + */ + protected function getPortableNamespacesList(array $namespaces) + { + $namespacesList = array(); + + foreach ($namespaces as $namespace) { + $namespacesList[] = $this->getPortableNamespaceDefinition($namespace); + } + + return $namespacesList; + } + /** * @param array $database * @@ -661,6 +693,18 @@ abstract class AbstractSchemaManager return $database; } + /** + * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition. + * + * @param array $namespace The native DBMS namespace definition. + * + * @return mixed + */ + protected function getPortableNamespaceDefinition(array $namespace) + { + return $namespace; + } + /** * @param array $functions * @@ -805,20 +849,21 @@ abstract class AbstractSchemaManager protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null) { $result = array(); - foreach($tableIndexRows as $tableIndex) { + foreach ($tableIndexRows as $tableIndex) { $indexName = $keyName = $tableIndex['key_name']; - if($tableIndex['primary']) { + if ($tableIndex['primary']) { $keyName = 'primary'; } $keyName = strtolower($keyName); - if(!isset($result[$keyName])) { + if (!isset($result[$keyName])) { $result[$keyName] = array( 'name' => $indexName, 'columns' => array($tableIndex['column_name']), 'unique' => $tableIndex['non_unique'] ? false : true, 'primary' => $tableIndex['primary'], 'flags' => isset($tableIndex['flags']) ? $tableIndex['flags'] : array(), + 'options' => isset($tableIndex['where']) ? array('where' => $tableIndex['where']) : array(), ); } else { $result[$keyName]['columns'][] = $tableIndex['column_name']; @@ -828,7 +873,7 @@ abstract class AbstractSchemaManager $eventManager = $this->_platform->getEventManager(); $indexes = array(); - foreach($result as $indexKey => $data) { + foreach ($result as $indexKey => $data) { $index = null; $defaultPrevented = false; @@ -841,7 +886,7 @@ abstract class AbstractSchemaManager } if ( ! $defaultPrevented) { - $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags']); + $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']); } if ($index) { @@ -908,6 +953,7 @@ abstract class AbstractSchemaManager /** * @param array $views + * * @return array */ protected function _getPortableViewsList($views) @@ -979,13 +1025,21 @@ abstract class AbstractSchemaManager */ public function createSchema() { + $namespaces = array(); + + if ($this->_platform->supportsSchemas()) { + $namespaces = $this->listNamespaceNames(); + } + $sequences = array(); - if($this->_platform->supportsSequences()) { + + if ($this->_platform->supportsSequences()) { $sequences = $this->listSequences(); } + $tables = $this->listTables(); - return new Schema($tables, $sequences, $this->createSchemaConfig()); + return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces); } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php index c086c86a1e..192ce1d2ee 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php @@ -20,7 +20,6 @@ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Types\Type; -use Doctrine\DBAL\Schema\Visitor\Visitor; /** * Object representation of a database column. @@ -32,7 +31,7 @@ use Doctrine\DBAL\Schema\Visitor\Visitor; class Column extends AbstractAsset { /** - * @var \Doctrine\DBAL\Types\Type + * @var Type */ protected $_type; @@ -99,9 +98,9 @@ class Column extends AbstractAsset /** * Creates a new Column. * - * @param string $columnName - * @param \Doctrine\DBAL\Types\Type $type - * @param array $options + * @param string $columnName + * @param Type $type + * @param array $options */ public function __construct($columnName, Type $type, array $options=array()) { @@ -113,7 +112,7 @@ class Column extends AbstractAsset /** * @param array $options * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setOptions(array $options) { @@ -128,25 +127,26 @@ class Column extends AbstractAsset } /** - * @param \Doctrine\DBAL\Types\Type $type + * @param Type $type * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setType(Type $type) { $this->_type = $type; + return $this; } /** * @param integer|null $length * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setLength($length) { - if($length !== null) { - $this->_length = (int)$length; + if ($length !== null) { + $this->_length = (int) $length; } else { $this->_length = null; } @@ -157,7 +157,7 @@ class Column extends AbstractAsset /** * @param integer $precision * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setPrecision($precision) { @@ -165,7 +165,7 @@ class Column extends AbstractAsset $precision = 10; // defaults to 10 when no valid precision is given. } - $this->_precision = (int)$precision; + $this->_precision = (int) $precision; return $this; } @@ -173,7 +173,7 @@ class Column extends AbstractAsset /** * @param integer $scale * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setScale($scale) { @@ -181,7 +181,7 @@ class Column extends AbstractAsset $scale = 0; } - $this->_scale = (int)$scale; + $this->_scale = (int) $scale; return $this; } @@ -189,11 +189,11 @@ class Column extends AbstractAsset /** * @param boolean $unsigned * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setUnsigned($unsigned) { - $this->_unsigned = (bool)$unsigned; + $this->_unsigned = (bool) $unsigned; return $this; } @@ -201,11 +201,11 @@ class Column extends AbstractAsset /** * @param boolean $fixed * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setFixed($fixed) { - $this->_fixed = (bool)$fixed; + $this->_fixed = (bool) $fixed; return $this; } @@ -213,11 +213,11 @@ class Column extends AbstractAsset /** * @param boolean $notnull * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setNotnull($notnull) { - $this->_notnull = (bool)$notnull; + $this->_notnull = (bool) $notnull; return $this; } @@ -225,7 +225,7 @@ class Column extends AbstractAsset /** * @param mixed $default * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setDefault($default) { @@ -237,7 +237,7 @@ class Column extends AbstractAsset /** * @param array $platformOptions * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setPlatformOptions(array $platformOptions) { @@ -250,7 +250,7 @@ class Column extends AbstractAsset * @param string $name * @param mixed $value * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setPlatformOption($name, $value) { @@ -262,7 +262,7 @@ class Column extends AbstractAsset /** * @param string $value * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setColumnDefinition($value) { @@ -272,7 +272,7 @@ class Column extends AbstractAsset } /** - * @return \Doctrine\DBAL\Types\Type + * @return Type */ public function getType() { @@ -382,18 +382,19 @@ class Column extends AbstractAsset /** * @param boolean $flag * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setAutoincrement($flag) { $this->_autoincrement = $flag; + return $this; } /** * @param string $comment * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setComment($comment) { @@ -414,7 +415,7 @@ class Column extends AbstractAsset * @param string $name * @param mixed $value * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setCustomSchemaOption($name, $value) { @@ -446,7 +447,7 @@ class Column extends AbstractAsset /** * @param array $customSchemaOptions * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function setCustomSchemaOptions(array $customSchemaOptions) { @@ -463,14 +464,6 @@ class Column extends AbstractAsset return $this->_customSchemaOptions; } - /** - * @param \Doctrine\DBAL\Schema\Visitor\Visitor $visitor - */ - public function visit(Visitor $visitor) - { - $visitor->accept($this); - } - /** * @return array */ diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php index 150f44e3fe..c993c9b118 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php @@ -34,7 +34,7 @@ class ColumnDiff public $oldColumnName; /** - * @var \Doctrine\DBAL\Schema\Column + * @var Column */ public $column; @@ -44,15 +44,15 @@ class ColumnDiff public $changedProperties = array(); /** - * @var \Doctrine\DBAL\Schema\Column + * @var Column */ public $fromColumn; /** - * @param string $oldColumnName - * @param \Doctrine\DBAL\Schema\Column $column - * @param array $changedProperties - * @param \Doctrine\DBAL\Schema\Column $fromColumn + * @param string $oldColumnName + * @param Column $column + * @param string[] $changedProperties + * @param Column $fromColumn */ public function __construct($oldColumnName, Column $column, array $changedProperties = array(), Column $fromColumn = null) { @@ -73,7 +73,7 @@ class ColumnDiff } /** - * @return \Doctrine\DBAL\Schema\Identifier + * @return Identifier */ public function getOldColumnName() { diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php index e4a01d3f29..4f11e6c8df 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php @@ -19,6 +19,8 @@ namespace Doctrine\DBAL\Schema; +use Doctrine\DBAL\Types; + /** * Compares two Schemas and return an instance of SchemaDiff. * @@ -60,7 +62,19 @@ class Comparator $foreignKeysToTable = array(); - foreach ( $toSchema->getTables() as $table ) { + foreach ($toSchema->getNamespaces() as $namespace) { + if ( ! $fromSchema->hasNamespace($namespace)) { + $diff->newNamespaces[$namespace] = $namespace; + } + } + + foreach ($fromSchema->getNamespaces() as $namespace) { + if ( ! $toSchema->hasNamespace($namespace)) { + $diff->removedNamespaces[$namespace] = $namespace; + } + } + + foreach ($toSchema->getTables() as $table) { $tableName = $table->getShortestName($toSchema->getName()); if ( ! $fromSchema->hasTable($tableName)) { $diff->newTables[$tableName] = $toSchema->getTable($tableName); @@ -77,7 +91,7 @@ class Comparator $tableName = $table->getShortestName($fromSchema->getName()); $table = $fromSchema->getTable($tableName); - if ( ! $toSchema->hasTable($tableName) ) { + if ( ! $toSchema->hasTable($tableName)) { $diff->removedTables[$tableName] = $table; } @@ -112,7 +126,9 @@ class Comparator foreach ($toSchema->getSequences() as $sequence) { $sequenceName = $sequence->getShortestName($toSchema->getName()); if ( ! $fromSchema->hasSequence($sequenceName)) { - $diff->newSequences[] = $sequence; + if ( ! $this->isAutoIncrementSequenceInSchema($fromSchema, $sequence)) { + $diff->newSequences[] = $sequence; + } } else { if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) { $diff->changedSequences[] = $toSchema->getSequence($sequenceName); @@ -160,11 +176,11 @@ class Comparator */ public function diffSequence(Sequence $sequence1, Sequence $sequence2) { - if($sequence1->getAllocationSize() != $sequence2->getAllocationSize()) { + if ($sequence1->getAllocationSize() != $sequence2->getAllocationSize()) { return true; } - if($sequence1->getInitialValue() != $sequence2->getInitialValue()) { + if ($sequence1->getInitialValue() != $sequence2->getInitialValue()) { return true; } @@ -191,29 +207,29 @@ class Comparator $table2Columns = $table2->getColumns(); /* See if all the fields in table 1 exist in table 2 */ - foreach ( $table2Columns as $columnName => $column ) { - if ( !$table1->hasColumn($columnName) ) { + foreach ($table2Columns as $columnName => $column) { + if ( !$table1->hasColumn($columnName)) { $tableDifferences->addedColumns[$columnName] = $column; $changes++; } } /* See if there are any removed fields in table 2 */ - foreach ( $table1Columns as $columnName => $column ) { - if ( !$table2->hasColumn($columnName) ) { + foreach ($table1Columns as $columnName => $column) { + // See if column is removed in table 2. + if ( ! $table2->hasColumn($columnName)) { $tableDifferences->removedColumns[$columnName] = $column; $changes++; + continue; } - } - foreach ( $table1Columns as $columnName => $column ) { - if ( $table2->hasColumn($columnName) ) { - $changedProperties = $this->diffColumn( $column, $table2->getColumn($columnName) ); - if (count($changedProperties) ) { - $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); - $columnDiff->fromColumn = $column; - $tableDifferences->changedColumns[$column->getName()] = $columnDiff; - $changes++; - } + // See if column has changed properties in table 2. + $changedProperties = $this->diffColumn($column, $table2->getColumn($columnName)); + + if ( ! empty($changedProperties)) { + $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); + $columnDiff->fromColumn = $column; + $tableDifferences->changedColumns[$column->getName()] = $columnDiff; + $changes++; } } @@ -222,38 +238,43 @@ class Comparator $table1Indexes = $table1->getIndexes(); $table2Indexes = $table2->getIndexes(); - foreach ($table2Indexes as $index2Name => $index2Definition) { - foreach ($table1Indexes as $index1Name => $index1Definition) { - if ($this->diffIndex($index1Definition, $index2Definition) === false) { - unset($table1Indexes[$index1Name]); - unset($table2Indexes[$index2Name]); - } else { - if ($index1Name == $index2Name) { - $tableDifferences->changedIndexes[$index2Name] = $table2Indexes[$index2Name]; - unset($table1Indexes[$index1Name]); - unset($table2Indexes[$index2Name]); - $changes++; - } - } + /* See if all the indexes in table 1 exist in table 2 */ + foreach ($table2Indexes as $indexName => $index) { + if (($index->isPrimary() && $table1->hasPrimaryKey()) || $table1->hasIndex($indexName)) { + continue; } - } - foreach ($table1Indexes as $index1Name => $index1Definition) { - $tableDifferences->removedIndexes[$index1Name] = $index1Definition; + $tableDifferences->addedIndexes[$indexName] = $index; $changes++; } + /* See if there are any removed indexes in table 2 */ + foreach ($table1Indexes as $indexName => $index) { + // See if index is removed in table 2. + if (($index->isPrimary() && ! $table2->hasPrimaryKey()) || + ! $index->isPrimary() && ! $table2->hasIndex($indexName) + ) { + $tableDifferences->removedIndexes[$indexName] = $index; + $changes++; + continue; + } - foreach ($table2Indexes as $index2Name => $index2Definition) { - $tableDifferences->addedIndexes[$index2Name] = $index2Definition; - $changes++; + // See if index has changed in table 2. + $table2Index = $index->isPrimary() ? $table2->getPrimaryKey() : $table2->getIndex($indexName); + + if ($this->diffIndex($index, $table2Index)) { + $tableDifferences->changedIndexes[$indexName] = $table2Index; + $changes++; + } } + $this->detectIndexRenamings($tableDifferences); + $fromFkeys = $table1->getForeignKeys(); $toFkeys = $table2->getForeignKeys(); foreach ($fromFkeys as $key1 => $constraint1) { foreach ($toFkeys as $key2 => $constraint2) { - if($this->diffForeignKey($constraint1, $constraint2) === false) { + if ($this->diffForeignKey($constraint1, $constraint2) === false) { unset($fromFkeys[$key1]); unset($toFkeys[$key2]); } else { @@ -314,6 +335,47 @@ class Comparator } } + /** + * Try to find indexes that only changed their name, rename operations maybe cheaper than add/drop + * however ambiguities between different possibilities should not lead to renaming at all. + * + * @param \Doctrine\DBAL\Schema\TableDiff $tableDifferences + * + * @return void + */ + private function detectIndexRenamings(TableDiff $tableDifferences) + { + $renameCandidates = array(); + + // Gather possible rename candidates by comparing each added and removed index based on semantics. + foreach ($tableDifferences->addedIndexes as $addedIndexName => $addedIndex) { + foreach ($tableDifferences->removedIndexes as $removedIndex) { + if (! $this->diffIndex($addedIndex, $removedIndex)) { + $renameCandidates[$addedIndex->getName()][] = array($removedIndex, $addedIndex, $addedIndexName); + } + } + } + + foreach ($renameCandidates as $candidateIndexes) { + // If the current rename candidate contains exactly one semantically equal index, + // we can safely rename it. + // Otherwise it is unclear if a rename action is really intended, + // therefore we let those ambiguous indexes be added/dropped. + if (count($candidateIndexes) === 1) { + list($removedIndex, $addedIndex) = $candidateIndexes[0]; + + $removedIndexName = strtolower($removedIndex->getName()); + $addedIndexName = strtolower($addedIndex->getName()); + + if (! isset($tableDifferences->renamedIndexes[$removedIndexName])) { + $tableDifferences->renamedIndexes[$removedIndexName] = $addedIndex; + unset($tableDifferences->addedIndexes[$addedIndexName]); + unset($tableDifferences->removedIndexes[$removedIndexName]); + } + } + } + } + /** * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $key1 * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $key2 @@ -358,78 +420,77 @@ class Comparator */ public function diffColumn(Column $column1, Column $column2) { + $properties1 = $column1->toArray(); + $properties2 = $column2->toArray(); + $changedProperties = array(); - if ( $column1->getType() != $column2->getType() ) { - $changedProperties[] = 'type'; - } - if ($column1->getNotnull() != $column2->getNotnull()) { - $changedProperties[] = 'notnull'; + foreach (array('type', 'notnull', 'unsigned', 'autoincrement') as $property) { + if ($properties1[$property] != $properties2[$property]) { + $changedProperties[] = $property; + } } - $column1Default = $column1->getDefault(); - $column2Default = $column2->getDefault(); - - if ($column1Default != $column2Default || + if ($properties1['default'] != $properties2['default'] || // Null values need to be checked additionally as they tell whether to create or drop a default value. // null != 0, null != false, null != '' etc. This affects platform's table alteration SQL generation. - (null === $column1Default && null !== $column2Default) || - (null === $column2Default && null !== $column1Default) + (null === $properties1['default'] && null !== $properties2['default']) || + (null === $properties2['default'] && null !== $properties1['default']) ) { $changedProperties[] = 'default'; } - if ($column1->getUnsigned() != $column2->getUnsigned()) { - $changedProperties[] = 'unsigned'; - } - - if ($column1->getType() instanceof \Doctrine\DBAL\Types\StringType) { + if (($properties1['type'] instanceof Types\StringType && ! $properties1['type'] instanceof Types\GuidType) || + $properties1['type'] instanceof Types\BinaryType + ) { // check if value of length is set at all, default value assumed otherwise. - $length1 = $column1->getLength() ?: 255; - $length2 = $column2->getLength() ?: 255; + $length1 = $properties1['length'] ?: 255; + $length2 = $properties2['length'] ?: 255; if ($length1 != $length2) { $changedProperties[] = 'length'; } - if ($column1->getFixed() != $column2->getFixed()) { + if ($properties1['fixed'] != $properties2['fixed']) { $changedProperties[] = 'fixed'; } - } - - if ($column1->getType() instanceof \Doctrine\DBAL\Types\DecimalType) { - if (($column1->getPrecision()?:10) != ($column2->getPrecision()?:10)) { + } elseif ($properties1['type'] instanceof Types\DecimalType) { + if (($properties1['precision'] ?: 10) != ($properties2['precision'] ?: 10)) { $changedProperties[] = 'precision'; } - if ($column1->getScale() != $column2->getScale()) { + if ($properties1['scale'] != $properties2['scale']) { $changedProperties[] = 'scale'; } } - if ($column1->getAutoincrement() != $column2->getAutoincrement()) { - $changedProperties[] = 'autoincrement'; - } - - // only allow to delete comment if its set to '' not to null. - if ($column1->getComment() !== null && $column1->getComment() != $column2->getComment()) { + // A null value and an empty string are actually equal for a comment so they should not trigger a change. + if ($properties1['comment'] !== $properties2['comment'] && + ! (null === $properties1['comment'] && '' === $properties2['comment']) && + ! (null === $properties2['comment'] && '' === $properties1['comment']) + ) { $changedProperties[] = 'comment'; } - $options1 = $column1->getCustomSchemaOptions(); - $options2 = $column2->getCustomSchemaOptions(); - - $commonKeys = array_keys(array_intersect_key($options1, $options2)); + $customOptions1 = $column1->getCustomSchemaOptions(); + $customOptions2 = $column2->getCustomSchemaOptions(); - foreach ($commonKeys as $key) { - if ($options1[$key] !== $options2[$key]) { + foreach (array_merge(array_keys($customOptions1), array_keys($customOptions2)) as $key) { + if ( ! array_key_exists($key, $properties1) || ! array_key_exists($key, $properties2)) { + $changedProperties[] = $key; + } elseif ($properties1[$key] !== $properties2[$key]) { $changedProperties[] = $key; } } - $diffKeys = array_keys(array_diff_key($options1, $options2) + array_diff_key($options2, $options1)); + $platformOptions1 = $column1->getPlatformOptions(); + $platformOptions2 = $column2->getPlatformOptions(); - $changedProperties = array_merge($changedProperties, $diffKeys); + foreach (array_keys(array_intersect_key($platformOptions1, $platformOptions2)) as $key) { + if ($properties1[$key] !== $properties2[$key]) { + $changedProperties[] = $key; + } + } - return $changedProperties; + return array_unique($changedProperties); } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DB2SchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DB2SchemaManager.php index e26254470f..ff914c60f9 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DB2SchemaManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DB2SchemaManager.php @@ -19,9 +19,6 @@ namespace Doctrine\DBAL\Schema; -use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; -use Doctrine\DBAL\Events; - /** * IBM Db2 Schema Manager. * @@ -60,6 +57,12 @@ class DB2SchemaManager extends AbstractSchemaManager $scale = false; $precision = false; + $default = null; + + if (null !== $tableColumn['default'] && 'NULL' != $tableColumn['default']) { + $default = trim($tableColumn['default'], "'"); + } + $type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']); switch (strtolower($tableColumn['typename'])) { @@ -84,9 +87,10 @@ class DB2SchemaManager extends AbstractSchemaManager $options = array( 'length' => $length, - 'unsigned' => (bool)$unsigned, - 'fixed' => (bool)$fixed, - 'default' => ($tableColumn['default'] == "NULL") ? null : $tableColumn['default'], + 'unsigned' => (bool) $unsigned, + 'fixed' => (bool) $fixed, + 'default' => $default, + 'autoincrement' => (boolean) $tableColumn['autoincrement'], 'notnull' => (bool) ($tableColumn['nulls'] == 'N'), 'scale' => null, 'precision' => null, @@ -118,46 +122,14 @@ class DB2SchemaManager extends AbstractSchemaManager /** * {@inheritdoc} */ - protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) + protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) { - $eventManager = $this->_platform->getEventManager(); - - $indexes = array(); - foreach($tableIndexes as $indexKey => $data) { - $data = array_change_key_case($data, \CASE_LOWER); - $unique = ($data['uniquerule'] == "D") ? false : true; - $primary = ($data['uniquerule'] == "P"); - - $indexName = strtolower($data['name']); - - $data = array( - 'name' => $indexName, - 'columns' => explode("+", ltrim($data['colnames'], '+')), - 'unique' => $unique, - 'primary' => $primary - ); - - $index = null; - $defaultPrevented = false; - - if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { - $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); - $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); - - $defaultPrevented = $eventArgs->isDefaultPrevented(); - $index = $eventArgs->getIndex(); - } - - if ( ! $defaultPrevented) { - $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']); - } - - if ($index) { - $indexes[$indexKey] = $index; - } + foreach ($tableIndexRows as &$tableIndexRow) { + $tableIndexRow = array_change_key_case($tableIndexRow, \CASE_LOWER); + $tableIndexRow['primary'] = (boolean) $tableIndexRow['primary']; } - return $indexes; + return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); } /** @@ -165,23 +137,45 @@ class DB2SchemaManager extends AbstractSchemaManager */ protected function _getPortableTableForeignKeyDefinition($tableForeignKey) { - $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER); - - $tableForeignKey['deleterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['deleterule']); - $tableForeignKey['updaterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['updaterule']); - return new ForeignKeyConstraint( - array_map('trim', (array)$tableForeignKey['fkcolnames']), - $tableForeignKey['reftbname'], - array_map('trim', (array)$tableForeignKey['pkcolnames']), - $tableForeignKey['relname'], - array( - 'onUpdate' => $tableForeignKey['updaterule'], - 'onDelete' => $tableForeignKey['deleterule'], - ) + $tableForeignKey['local_columns'], + $tableForeignKey['foreign_table'], + $tableForeignKey['foreign_columns'], + $tableForeignKey['name'], + $tableForeignKey['options'] ); } + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $foreignKeys = array(); + + foreach ($tableForeignKeys as $tableForeignKey) { + $tableForeignKey = array_change_key_case($tableForeignKey, \CASE_LOWER); + + if (!isset($foreignKeys[$tableForeignKey['index_name']])) { + $foreignKeys[$tableForeignKey['index_name']] = array( + 'local_columns' => array($tableForeignKey['local_column']), + 'foreign_table' => $tableForeignKey['foreign_table'], + 'foreign_columns' => array($tableForeignKey['foreign_column']), + 'name' => $tableForeignKey['index_name'], + 'options' => array( + 'onUpdate' => $tableForeignKey['on_update'], + 'onDelete' => $tableForeignKey['on_delete'], + ) + ); + } else { + $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column']; + $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column']; + } + } + + return parent::_getPortableTableForeignKeysList($foreignKeys); + } + /** * {@inheritdoc} */ @@ -189,7 +183,7 @@ class DB2SchemaManager extends AbstractSchemaManager { if ($def == "C") { return "CASCADE"; - } else if ($def == "N") { + } elseif ($def == "N") { return "SET NULL"; } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php index fa97898377..e9503c359a 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php @@ -19,6 +19,8 @@ namespace Doctrine\DBAL\Schema; +use Doctrine\DBAL\Types\Type; + /** * Schema manager for the Drizzle RDBMS. * @@ -31,7 +33,6 @@ class DrizzleSchemaManager extends AbstractSchemaManager */ protected function _getPortableTableColumnDefinition($tableColumn) { - $tableName = $tableColumn['COLUMN_NAME']; $dbType = strtolower($tableColumn['DATA_TYPE']); $type = $this->_platform->getDoctrineTypeMapping($dbType); @@ -39,16 +40,24 @@ class DrizzleSchemaManager extends AbstractSchemaManager $tableColumn['COLUMN_COMMENT'] = $this->removeDoctrineTypeFromComment($tableColumn['COLUMN_COMMENT'], $type); $options = array( - 'notnull' => !(bool)$tableColumn['IS_NULLABLE'], - 'length' => (int)$tableColumn['CHARACTER_MAXIMUM_LENGTH'], + 'notnull' => !(bool) $tableColumn['IS_NULLABLE'], + 'length' => (int) $tableColumn['CHARACTER_MAXIMUM_LENGTH'], 'default' => isset($tableColumn['COLUMN_DEFAULT']) ? $tableColumn['COLUMN_DEFAULT'] : null, - 'autoincrement' => (bool)$tableColumn['IS_AUTO_INCREMENT'], - 'scale' => (int)$tableColumn['NUMERIC_SCALE'], - 'precision' => (int)$tableColumn['NUMERIC_PRECISION'], - 'comment' => (isset($tableColumn['COLUMN_COMMENT']) ? $tableColumn['COLUMN_COMMENT'] : null), + 'autoincrement' => (bool) $tableColumn['IS_AUTO_INCREMENT'], + 'scale' => (int) $tableColumn['NUMERIC_SCALE'], + 'precision' => (int) $tableColumn['NUMERIC_PRECISION'], + 'comment' => isset($tableColumn['COLUMN_COMMENT']) && '' !== $tableColumn['COLUMN_COMMENT'] + ? $tableColumn['COLUMN_COMMENT'] + : null, ); - return new Column($tableName, \Doctrine\DBAL\Types\Type::getType($type), $options); + $column = new Column($tableColumn['COLUMN_NAME'], Type::getType($type), $options); + + if ( ! empty($tableColumn['COLLATION_NAME'])) { + $column->setPlatformOption('collation', $tableColumn['COLLATION_NAME']); + } + + return $column; } /** @@ -77,15 +86,15 @@ class DrizzleSchemaManager extends AbstractSchemaManager $columns[] = trim($value, ' `'); } - $ref_columns = array(); + $refColumns = array(); foreach (explode(',', $tableForeignKey['REFERENCED_TABLE_COLUMNS']) as $value) { - $ref_columns[] = trim($value, ' `'); + $refColumns[] = trim($value, ' `'); } return new ForeignKeyConstraint( $columns, $tableForeignKey['REFERENCED_TABLE_NAME'], - $ref_columns, + $refColumns, $tableForeignKey['CONSTRAINT_NAME'], array( 'onUpdate' => $tableForeignKey['UPDATE_RULE'], @@ -101,7 +110,7 @@ class DrizzleSchemaManager extends AbstractSchemaManager { $indexes = array(); foreach ($tableIndexes as $k) { - $k['primary'] = (boolean)$k['primary']; + $k['primary'] = (boolean) $k['primary']; $indexes[] = $k; } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php index 7999cb5e12..6070eb2e5b 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php @@ -231,6 +231,7 @@ class ForeignKeyConstraint extends AbstractAsset implements Constraint public function getUnqualifiedForeignTableName() { $parts = explode(".", $this->_foreignTableName->getName()); + return strtolower(end($parts)); } @@ -362,5 +363,27 @@ class ForeignKeyConstraint extends AbstractAsset implements Constraint return false; } -} + /** + * Checks whether this foreign key constraint intersects the given index columns. + * + * Returns `true` if at least one of this foreign key's local columns + * matches one of the given index's columns, `false` otherwise. + * + * @param Index $index The index to be checked against. + * + * @return boolean + */ + public function intersectsIndexColumns(Index $index) + { + foreach ($index->getColumns() as $indexColumn) { + foreach ($this->_localColumnNames as $localColumn) { + if (strtolower($indexColumn) === strtolower($localColumn->getName())) { + return true; + } + } + } + + return false; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php index e50e767811..1e48614660 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php @@ -19,8 +19,6 @@ namespace Doctrine\DBAL\Schema; -use Doctrine\DBAL\Schema\AbstractAsset; - /** * An abstraction class for an asset identifier. * diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php index 7efc20152a..bc5cd93dc6 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php @@ -29,7 +29,7 @@ class Index extends AbstractAsset implements Constraint * * @var Identifier[] */ - protected $_columns; + protected $_columns = array(); /** * @var boolean @@ -43,25 +43,37 @@ class Index extends AbstractAsset implements Constraint /** * Platform specific flags for indexes. + * array($flagName => true) * * @var array */ protected $_flags = array(); /** - * @param string $indexName - * @param array $columns - * @param boolean $isUnique - * @param boolean $isPrimary - * @param array $flags + * Platform specific options + * + * @todo $_flags should eventually be refactored into options + * + * @var array */ - public function __construct($indexName, array $columns, $isUnique = false, $isPrimary = false, array $flags = array()) + private $options = array(); + + /** + * @param string $indexName + * @param string[] $columns + * @param boolean $isUnique + * @param boolean $isPrimary + * @param string[] $flags + * @param array $options + */ + public function __construct($indexName, array $columns, $isUnique = false, $isPrimary = false, array $flags = array(), array $options = array()) { - $isUnique = ($isPrimary)?true:$isUnique; + $isUnique = $isUnique || $isPrimary; $this->_setName($indexName); $this->_isUnique = $isUnique; $this->_isPrimary = $isPrimary; + $this->options = $options; foreach ($columns as $column) { $this->_addColumn($column); @@ -80,7 +92,7 @@ class Index extends AbstractAsset implements Constraint */ protected function _addColumn($column) { - if(is_string($column)) { + if (is_string($column)) { $this->_columns[$column] = new Identifier($column); } else { throw new \InvalidArgumentException("Expecting a string as Index Column"); @@ -110,7 +122,7 @@ class Index extends AbstractAsset implements Constraint } /** - * @return array + * @return string[] */ public function getUnquotedColumns() { @@ -182,7 +194,7 @@ class Index extends AbstractAsset implements Constraint /** * Checks if the other index already fulfills all the indexing and constraint needs of the current one. * - * @param \Doctrine\DBAL\Schema\Index $other + * @param Index $other * * @return boolean */ @@ -198,15 +210,23 @@ class Index extends AbstractAsset implements Constraint $sameColumns = $this->spansColumns($other->getColumns()); if ($sameColumns) { - if ( ! $this->isUnique() && !$this->isPrimary()) { + if ( ! $this->samePartialIndex($other)) { + return false; + } + + if ( ! $this->isUnique() && ! $this->isPrimary()) { // this is a special case: If the current key is neither primary or unique, any uniqe or // primary key will always have the same effect for the index and there cannot be any constraint // overlaps. This means a primary or unique index can always fulfill the requirements of just an // index that has no constraints. return true; - } else if ($other->isPrimary() != $this->isPrimary()) { + } + + if ($other->isPrimary() != $this->isPrimary()) { return false; - } else if ($other->isUnique() != $this->isUnique()) { + } + + if ($other->isUnique() != $this->isUnique()) { return false; } @@ -219,7 +239,7 @@ class Index extends AbstractAsset implements Constraint /** * Detects if the other index is a non-unique, non primary index that can be overwritten by this one. * - * @param \Doctrine\DBAL\Schema\Index $other + * @param Index $other * * @return boolean */ @@ -227,11 +247,11 @@ class Index extends AbstractAsset implements Constraint { if ($other->isPrimary()) { return false; - } else if ($this->isSimpleIndex() && $other->isUnique()) { + } elseif ($this->isSimpleIndex() && $other->isUnique()) { return false; } - if ($this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique())) { + if ($this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique()) && $this->samePartialIndex($other)) { return true; } @@ -241,7 +261,7 @@ class Index extends AbstractAsset implements Constraint /** * Returns platform specific flags for indexes. * - * @return array + * @return string[] */ public function getFlags() { @@ -255,11 +275,11 @@ class Index extends AbstractAsset implements Constraint * * @param string $flag * - * @return \Doctrine\DBAL\Schema\Index + * @return Index */ public function addFlag($flag) { - $this->flags[strtolower($flag)] = true; + $this->_flags[strtolower($flag)] = true; return $this; } @@ -273,7 +293,7 @@ class Index extends AbstractAsset implements Constraint */ public function hasFlag($flag) { - return isset($this->flags[strtolower($flag)]); + return isset($this->_flags[strtolower($flag)]); } /** @@ -285,6 +305,54 @@ class Index extends AbstractAsset implements Constraint */ public function removeFlag($flag) { - unset($this->flags[strtolower($flag)]); + unset($this->_flags[strtolower($flag)]); + } + + /** + * @param string $name + * + * @return boolean + */ + public function hasOption($name) + { + return isset($this->options[strtolower($name)]); + } + + /** + * @param string $name + * + * @return mixed + */ + public function getOption($name) + { + return $this->options[strtolower($name)]; + } + + /** + * @return array + */ + public function getOptions() + { + return $this->options; + } + + /** + * Return whether the two indexes have the same partial index + * @param \Doctrine\DBAL\Schema\Index $other + * + * @return boolean + */ + private function samePartialIndex(Index $other) + { + if ($this->hasOption('where') && $other->hasOption('where') && $this->getOption('where') == $other->getOption('where')) { + return true; + } + + if ( ! $this->hasOption('where') && ! $other->hasOption('where')) { + return true; + } + + return false; } + } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php index 675b8a0a07..0b36762b6c 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php @@ -19,6 +19,9 @@ namespace Doctrine\DBAL\Schema; +use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Types\Type; + /** * Schema manager for the MySql RDBMS. * @@ -62,15 +65,17 @@ class MySqlSchemaManager extends AbstractSchemaManager */ protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) { - foreach($tableIndexes as $k => $v) { + foreach ($tableIndexes as $k => $v) { $v = array_change_key_case($v, CASE_LOWER); - if($v['key_name'] == 'PRIMARY') { + if ($v['key_name'] == 'PRIMARY') { $v['primary'] = true; } else { $v['primary'] = false; } if (strpos($v['index_type'], 'FULLTEXT') !== false) { $v['flags'] = array('FULLTEXT'); + } elseif (strpos($v['index_type'], 'SPATIAL') !== false) { + $v['flags'] = array('SPATIAL'); } $tableIndexes[$k] = $v; } @@ -128,6 +133,7 @@ class MySqlSchemaManager extends AbstractSchemaManager switch ($dbType) { case 'char': + case 'binary': $fixed = true; break; case 'float': @@ -135,22 +141,36 @@ class MySqlSchemaManager extends AbstractSchemaManager case 'real': case 'numeric': case 'decimal': - if(preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) { + if (preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) { $precision = $match[1]; $scale = $match[2]; $length = null; } break; + case 'tinytext': + $length = MySqlPlatform::LENGTH_LIMIT_TINYTEXT; + break; + case 'text': + $length = MySqlPlatform::LENGTH_LIMIT_TEXT; + break; + case 'mediumtext': + $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMTEXT; + break; + case 'tinyblob': + $length = MySqlPlatform::LENGTH_LIMIT_TINYBLOB; + break; + case 'blob': + $length = MySqlPlatform::LENGTH_LIMIT_BLOB; + break; + case 'mediumblob': + $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMBLOB; + break; case 'tinyint': case 'smallint': case 'mediumint': case 'int': case 'integer': case 'bigint': - case 'tinyblob': - case 'mediumblob': - case 'longblob': - case 'blob': case 'year': $length = null; break; @@ -167,7 +187,9 @@ class MySqlSchemaManager extends AbstractSchemaManager 'scale' => null, 'precision' => null, 'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false), - 'comment' => (isset($tableColumn['comment'])) ? $tableColumn['comment'] : null + 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' + ? $tableColumn['comment'] + : null, ); if ($scale !== null && $precision !== null) { @@ -175,7 +197,13 @@ class MySqlSchemaManager extends AbstractSchemaManager $options['precision'] = $precision; } - return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); + $column = new Column($tableColumn['field'], Type::getType($type), $options); + + if (isset($tableColumn['collation'])) { + $column->setPlatformOption('collation', $tableColumn['collation']); + } + + return $column; } /** @@ -208,7 +236,7 @@ class MySqlSchemaManager extends AbstractSchemaManager } $result = array(); - foreach($list as $constraint) { + foreach ($list as $constraint) { $result[] = new ForeignKeyConstraint( array_values($constraint['local']), $constraint['foreignTable'], array_values($constraint['foreign']), $constraint['name'], diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php index f37bcf81bd..a02933d241 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php @@ -19,6 +19,8 @@ namespace Doctrine\DBAL\Schema; +use Doctrine\DBAL\Types\Type; + /** * Oracle Schema Manager. * @@ -36,7 +38,7 @@ class OracleSchemaManager extends AbstractSchemaManager { $view = \array_change_key_case($view, CASE_LOWER); - return new View($view['view_name'], $view['text']); + return new View($this->getQuotedIdentifierName($view['view_name']), $view['text']); } /** @@ -58,7 +60,7 @@ class OracleSchemaManager extends AbstractSchemaManager { $table = \array_change_key_case($table, CASE_LOWER); - return $table['table_name']; + return $this->getQuotedIdentifierName($table['table_name']); } /** @@ -70,21 +72,21 @@ class OracleSchemaManager extends AbstractSchemaManager protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) { $indexBuffer = array(); - foreach ( $tableIndexes as $tableIndex ) { + foreach ($tableIndexes as $tableIndex) { $tableIndex = \array_change_key_case($tableIndex, CASE_LOWER); $keyName = strtolower($tableIndex['name']); - if ( strtolower($tableIndex['is_primary']) == "p" ) { + if (strtolower($tableIndex['is_primary']) == "p") { $keyName = 'primary'; $buffer['primary'] = true; $buffer['non_unique'] = false; } else { $buffer['primary'] = false; - $buffer['non_unique'] = ( $tableIndex['is_unique'] == 0 ) ? true : false; + $buffer['non_unique'] = ($tableIndex['is_unique'] == 0) ? true : false; } $buffer['key_name'] = $keyName; - $buffer['column_name'] = $tableIndex['column_name']; + $buffer['column_name'] = $this->getQuotedIdentifierName($tableIndex['column_name']); $indexBuffer[] = $buffer; } @@ -99,7 +101,7 @@ class OracleSchemaManager extends AbstractSchemaManager $tableColumn = \array_change_key_case($tableColumn, CASE_LOWER); $dbType = strtolower($tableColumn['data_type']); - if(strpos($dbType, "timestamp(") === 0) { + if (strpos($dbType, "timestamp(") === 0) { if (strpos($dbType, "WITH TIME ZONE")) { $dbType = "timestamptz"; } else { @@ -113,14 +115,16 @@ class OracleSchemaManager extends AbstractSchemaManager $tableColumn['column_name'] = ''; } - if ($tableColumn['data_default'] === 'NULL') { + // Default values returned from database sometimes have trailing spaces. + $tableColumn['data_default'] = trim($tableColumn['data_default']); + + if ($tableColumn['data_default'] === '' || $tableColumn['data_default'] === 'NULL') { $tableColumn['data_default'] = null; } if (null !== $tableColumn['data_default']) { // Default values returned from database are enclosed in single quotes. - // Sometimes trailing spaces are also encountered. - $tableColumn['data_default'] = trim(trim($tableColumn['data_default']), "'"); + $tableColumn['data_default'] = trim($tableColumn['data_default'], "'"); } $precision = null; @@ -171,6 +175,8 @@ class OracleSchemaManager extends AbstractSchemaManager $length = null; break; case 'float': + case 'binary_float': + case 'binary_double': $precision = $tableColumn['data_precision']; $scale = $tableColumn['data_scale']; $length = null; @@ -199,11 +205,13 @@ class OracleSchemaManager extends AbstractSchemaManager 'length' => $length, 'precision' => $precision, 'scale' => $scale, - 'comment' => (isset($tableColumn['comments'])) ? $tableColumn['comments'] : null, + 'comment' => isset($tableColumn['comments']) && '' !== $tableColumn['comments'] + ? $tableColumn['comments'] + : null, 'platformDetails' => array(), ); - return new Column($tableColumn['column_name'], \Doctrine\DBAL\Types\Type::getType($type), $options); + return new Column($this->getQuotedIdentifierName($tableColumn['column_name']), Type::getType($type), $options); } /** @@ -220,22 +228,26 @@ class OracleSchemaManager extends AbstractSchemaManager } $list[$value['constraint_name']] = array( - 'name' => $value['constraint_name'], + 'name' => $this->getQuotedIdentifierName($value['constraint_name']), 'local' => array(), 'foreign' => array(), 'foreignTable' => $value['references_table'], 'onDelete' => $value['delete_rule'], ); } - $list[$value['constraint_name']]['local'][$value['position']] = $value['local_column']; - $list[$value['constraint_name']]['foreign'][$value['position']] = $value['foreign_column']; + + $localColumn = $this->getQuotedIdentifierName($value['local_column']); + $foreignColumn = $this->getQuotedIdentifierName($value['foreign_column']); + + $list[$value['constraint_name']]['local'][$value['position']] = $localColumn; + $list[$value['constraint_name']]['foreign'][$value['position']] = $foreignColumn; } $result = array(); - foreach($list as $constraint) { + foreach ($list as $constraint) { $result[] = new ForeignKeyConstraint( - array_values($constraint['local']), $constraint['foreignTable'], - array_values($constraint['foreign']), $constraint['name'], + array_values($constraint['local']), $this->getQuotedIdentifierName($constraint['foreignTable']), + array_values($constraint['foreign']), $this->getQuotedIdentifierName($constraint['name']), array('onDelete' => $constraint['onDelete']) ); } @@ -250,7 +262,11 @@ class OracleSchemaManager extends AbstractSchemaManager { $sequence = \array_change_key_case($sequence, CASE_LOWER); - return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['min_value']); + return new Sequence( + $this->getQuotedIdentifierName($sequence['sequence_name']), + $sequence['increment_by'], + $sequence['min_value'] + ); } /** @@ -315,8 +331,27 @@ class OracleSchemaManager extends AbstractSchemaManager */ public function dropTable($name) { - $this->dropAutoincrement($name); + $this->tryMethod('dropAutoincrement', $name); parent::dropTable($name); } + + /** + * Returns the quoted representation of the given identifier name. + * + * Quotes non-uppercase identifiers explicitly to preserve case + * and thus make references to the particular identifier work. + * + * @param string $identifier The identifier to quote. + * + * @return string The quoted identifier. + */ + private function getQuotedIdentifierName($identifier) + { + if (preg_match('/[a-z]/', $identifier)) { + return $this->_platform->quoteIdentifier($identifier); + } + + return $identifier; + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php index 5008540757..5b7b82e152 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php @@ -19,6 +19,9 @@ namespace Doctrine\DBAL\Schema; +use Doctrine\DBAL\Exception\DriverException; +use Doctrine\DBAL\Types\Type; + /** * PostgreSQL Schema Manager. * @@ -43,7 +46,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager { $rows = $this->_conn->fetchAll("SELECT nspname as schema_name FROM pg_namespace WHERE nspname !~ '^pg_.*' and nspname != 'information_schema'"); - return array_map(function($v) { return $v['schema_name']; }, $rows); + return array_map(function ($v) { return $v['schema_name']; }, $rows); } /** @@ -98,6 +101,33 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager }); } + /** + * {@inheritdoc} + */ + public function dropDatabase($database) + { + try { + parent::dropDatabase($database); + } catch (DriverException $exception) { + // If we have a SQLSTATE 55006, the drop database operation failed + // because of active connections on the database. + // To force dropping the database, we first have to close all active connections + // on that database and issue the drop database operation again. + if ($exception->getSQLState() !== '55006') { + throw $exception; + } + + $this->_execSql( + array( + $this->_platform->getDisallowDatabaseConnectionsSQL($database), + $this->_platform->getCloseActiveDatabaseConnectionsSQL($database), + ) + ); + + parent::dropDatabase($database); + } + } + /** * {@inheritdoc} */ @@ -122,8 +152,8 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager } return new ForeignKeyConstraint( - $localColumns, $foreignTable, $foreignColumns, $tableForeignKey['conname'], - array('onUpdate' => $onUpdate, 'onDelete' => $onDelete) + $localColumns, $foreignTable, $foreignColumns, $tableForeignKey['conname'], + array('onUpdate' => $onUpdate, 'onDelete' => $onDelete) ); } @@ -140,7 +170,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager */ protected function _getPortableViewDefinition($view) { - return new View($view['viewname'], $view['definition']); + return new View($view['schemaname'].'.'.$view['viewname'], $view['definition']); } /** @@ -195,7 +225,8 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager 'key_name' => $row['relname'], 'column_name' => trim($colRow['attname']), 'non_unique' => !$row['indisunique'], - 'primary' => $row['indisprimary'] + 'primary' => $row['indisprimary'], + 'where' => $row['where'], ); } } @@ -213,6 +244,40 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager return $database['datname']; } + /** + * {@inheritdoc} + */ + protected function _getPortableSequencesList($sequences) + { + $sequenceDefinitions = array(); + + foreach ($sequences as $sequence) { + if ($sequence['schemaname'] != 'public') { + $sequenceName = $sequence['schemaname'] . "." . $sequence['relname']; + } else { + $sequenceName = $sequence['relname']; + } + + $sequenceDefinitions[$sequenceName] = $sequence; + } + + $list = array(); + + foreach ($this->filterAssetNames(array_keys($sequenceDefinitions)) as $sequenceName) { + $list[] = $this->_getPortableSequenceDefinition($sequenceDefinitions[$sequenceName]); + } + + return $list; + } + + /** + * {@inheritdoc} + */ + protected function getPortableNamespaceDefinition(array $namespace) + { + return $namespace['nspname']; + } + /** * {@inheritdoc} */ @@ -357,9 +422,17 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager 'fixed' => $fixed, 'unsigned' => false, 'autoincrement' => $autoincrement, - 'comment' => $tableColumn['comment'], + 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' + ? $tableColumn['comment'] + : null, ); - return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); + $column = new Column($tableColumn['field'], Type::getType($type), $options); + + if (isset($tableColumn['collation']) && !empty($tableColumn['collation'])) { + $column->setPlatformOption('collation', $tableColumn['collation']); + } + + return $column; } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php new file mode 100644 index 0000000000..793a5fe8ba --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php @@ -0,0 +1,243 @@ +. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Types\Type; + +/** + * SAP Sybase SQL Anywhere schema manager. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +class SQLAnywhereSchemaManager extends AbstractSchemaManager +{ + /** + * {@inheritdoc} + * + * Starts a database after creation + * as SQL Anywhere needs a database to be started + * before it can be used. + * + * @see startDatabase + */ + public function createDatabase($database) + { + parent::createDatabase($database); + $this->startDatabase($database); + } + + /** + * {@inheritdoc} + * + * Tries stopping a database before dropping + * as SQL Anywhere needs a database to be stopped + * before it can be dropped. + * + * @see stopDatabase + */ + public function dropDatabase($database) + { + $this->tryMethod('stopDatabase', $database); + parent::dropDatabase($database); + } + + /** + * Starts a database. + * + * @param string $database The name of the database to start. + */ + public function startDatabase($database) + { + $this->_execSql($this->_platform->getStartDatabaseSQL($database)); + } + + /** + * Stops a database. + * + * @param string $database The name of the database to stop. + */ + public function stopDatabase($database) + { + $this->_execSql($this->_platform->getStopDatabaseSQL($database)); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableDatabaseDefinition($database) + { + return $database['name']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableSequenceDefinition($sequence) + { + return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['start_with']); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $type = $this->_platform->getDoctrineTypeMapping($tableColumn['type']); + $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); + $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); + $precision = null; + $scale = null; + $fixed = false; + $default = null; + + if (null !== $tableColumn['default']) { + // Strip quotes from default value. + $default = preg_replace(array("/^'(.*)'$/", "/''/"), array("$1", "'"), $tableColumn['default']); + + if ('autoincrement' == $default) { + $default = null; + } + } + + switch ($tableColumn['type']) { + case 'binary': + case 'char': + case 'nchar': + $fixed = true; + } + + switch ($type) { + case 'decimal': + case 'float': + $precision = $tableColumn['length']; + $scale = $tableColumn['scale']; + } + + return new Column( + $tableColumn['column_name'], + Type::getType($type), + array( + 'length' => $type == 'string' ? $tableColumn['length'] : null, + 'precision' => $precision, + 'scale' => $scale, + 'unsigned' => (bool) $tableColumn['unsigned'], + 'fixed' => $fixed, + 'notnull' => (bool) $tableColumn['notnull'], + 'default' => $default, + 'autoincrement' => (bool) $tableColumn['autoincrement'], + 'comment' => isset($tableColumn['comment']) && '' !== $tableColumn['comment'] + ? $tableColumn['comment'] + : null, + )); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableDefinition($table) + { + return $table['table_name']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + return new ForeignKeyConstraint( + $tableForeignKey['local_columns'], + $tableForeignKey['foreign_table'], + $tableForeignKey['foreign_columns'], + $tableForeignKey['name'], + $tableForeignKey['options'] + ); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $foreignKeys = array(); + + foreach ($tableForeignKeys as $tableForeignKey) { + if (!isset($foreignKeys[$tableForeignKey['index_name']])) { + $foreignKeys[$tableForeignKey['index_name']] = array( + 'local_columns' => array($tableForeignKey['local_column']), + 'foreign_table' => $tableForeignKey['foreign_table'], + 'foreign_columns' => array($tableForeignKey['foreign_column']), + 'name' => $tableForeignKey['index_name'], + 'options' => array( + 'notnull' => $tableForeignKey['notnull'], + 'match' => $tableForeignKey['match'], + 'onUpdate' => $tableForeignKey['on_update'], + 'onDelete' => $tableForeignKey['on_delete'], + 'check_on_commit' => $tableForeignKey['check_on_commit'], + 'clustered' => $tableForeignKey['clustered'], + 'for_olap_workload' => $tableForeignKey['for_olap_workload'] + ) + ); + } else { + $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column']; + $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column']; + } + } + + return parent::_getPortableTableForeignKeysList($foreignKeys); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) + { + foreach ($tableIndexRows as &$tableIndex) { + $tableIndex['primary'] = (boolean) $tableIndex['primary']; + $tableIndex['flags'] = array(); + + if ($tableIndex['clustered']) { + $tableIndex['flags'][] = 'clustered'; + } + + if ($tableIndex['with_nulls_not_distinct']) { + $tableIndex['flags'][] = 'with_nulls_not_distinct'; + } + + if ($tableIndex['for_olap_workload']) { + $tableIndex['flags'][] = 'for_olap_workload'; + } + } + + return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableViewDefinition($view) + { + return new View( + $view['table_name'], + preg_replace('/^.*\s+as\s+SELECT(.*)/i', "SELECT$1", $view['view_def']) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php index 45d44930c5..b56f8b2917 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php @@ -25,7 +25,7 @@ use Doctrine\DBAL\Types\Type; /** * SQL Server Schema Manager. * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @license http://www.opensource.org/licenses/mit-license.php MIT * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @author Juozas Kaziukenas @@ -79,34 +79,31 @@ class SQLServerSchemaManager extends AbstractSchemaManager break; } - $type = $this->_platform->getDoctrineTypeMapping($dbType); - - switch ($type) { - case 'char': - $fixed = true; - break; - case 'text': - $fixed = false; - break; + if ('char' === $dbType || 'nchar' === $dbType || 'binary' === $dbType) { + $fixed = true; } + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); + $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); + $options = array( - 'length' => ($length == 0 || !in_array($type, array('text', 'string'))) ? null : $length, - 'unsigned' => false, - 'fixed' => (bool) $fixed, - 'default' => $default !== 'NULL' ? $default : null, - 'notnull' => (bool) $tableColumn['notnull'], - 'scale' => $tableColumn['scale'], - 'precision' => $tableColumn['precision'], + 'length' => ($length == 0 || !in_array($type, array('text', 'string'))) ? null : $length, + 'unsigned' => false, + 'fixed' => (bool) $fixed, + 'default' => $default !== 'NULL' ? $default : null, + 'notnull' => (bool) $tableColumn['notnull'], + 'scale' => $tableColumn['scale'], + 'precision' => $tableColumn['precision'], 'autoincrement' => (bool) $tableColumn['autoincrement'], - ); - - $platformOptions = array( - 'collate' => $tableColumn['collation'] == 'NULL' ? null : $tableColumn['collation'] + 'comment' => $tableColumn['comment'] !== '' ? $tableColumn['comment'] : null, ); $column = new Column($tableColumn['name'], Type::getType($type), $options); - $column->setPlatformOptions($platformOptions); + + if (isset($tableColumn['collation']) && $tableColumn['collation'] !== 'NULL') { + $column->setPlatformOption('collation', $tableColumn['collation']); + } return $column; } @@ -183,6 +180,14 @@ class SQLServerSchemaManager extends AbstractSchemaManager return $database['name']; } + /** + * {@inheritdoc} + */ + protected function getPortableNamespaceDefinition(array $namespace) + { + return $namespace['name']; + } + /** * {@inheritdoc} */ @@ -201,13 +206,13 @@ class SQLServerSchemaManager extends AbstractSchemaManager try { $tableIndexes = $this->_conn->fetchAll($sql); - } catch(\PDOException $e) { + } catch (\PDOException $e) { if ($e->getCode() == "IMSSP") { return array(); } else { throw $e; } - } catch(SQLSrvException $e) { + } catch (SQLSrvException $e) { if (strpos($e->getMessage(), 'SQLSTATE [01000, 15472]') === 0) { return array(); } else { @@ -223,8 +228,8 @@ class SQLServerSchemaManager extends AbstractSchemaManager */ public function alterTable(TableDiff $tableDiff) { - if(count($tableDiff->removedColumns) > 0) { - foreach($tableDiff->removedColumns as $col){ + if (count($tableDiff->removedColumns) > 0) { + foreach ($tableDiff->removedColumns as $col) { $columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName()); foreach ($this->_conn->fetchAll($columnConstraintSql) as $constraint) { $this->_conn->exec("ALTER TABLE $tableDiff->name DROP CONSTRAINT " . $constraint['Name']); diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php index fcb6d32387..b7e24fe919 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php @@ -21,6 +21,7 @@ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Schema\Visitor\CreateSchemaSqlCollector; use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector; +use Doctrine\DBAL\Schema\Visitor\NamespaceVisitor; use Doctrine\DBAL\Schema\Visitor\Visitor; use Doctrine\DBAL\Platforms\AbstractPlatform; @@ -54,6 +55,13 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; */ class Schema extends AbstractAsset { + /** + * The namespaces in this schema. + * + * @var array + */ + private $namespaces = array(); + /** * @var \Doctrine\DBAL\Schema\Table[] */ @@ -73,15 +81,24 @@ class Schema extends AbstractAsset * @param \Doctrine\DBAL\Schema\Table[] $tables * @param \Doctrine\DBAL\Schema\Sequence[] $sequences * @param \Doctrine\DBAL\Schema\SchemaConfig $schemaConfig + * @param array $namespaces */ - public function __construct(array $tables=array(), array $sequences=array(), SchemaConfig $schemaConfig=null) - { + public function __construct( + array $tables = array(), + array $sequences = array(), + SchemaConfig $schemaConfig = null, + array $namespaces = array() + ) { if ($schemaConfig == null) { $schemaConfig = new SchemaConfig(); } $this->_schemaConfig = $schemaConfig; $this->_setName($schemaConfig->getName() ?: 'public'); + foreach ($namespaces as $namespace) { + $this->createNamespace($namespace); + } + foreach ($tables as $table) { $this->_addTable($table); } @@ -108,11 +125,17 @@ class Schema extends AbstractAsset */ protected function _addTable(Table $table) { + $namespaceName = $table->getNamespaceName(); $tableName = $table->getFullQualifiedName($this->getName()); - if(isset($this->_tables[$tableName])) { + + if (isset($this->_tables[$tableName])) { throw SchemaException::tableAlreadyExists($tableName); } + if ( ! $table->isInDefaultNamespace($this->getName()) && ! $this->hasNamespace($namespaceName)) { + $this->createNamespace($namespaceName); + } + $this->_tables[$tableName] = $table; $table->setSchemaConfig($this->_schemaConfig); } @@ -126,13 +149,30 @@ class Schema extends AbstractAsset */ protected function _addSequence(Sequence $sequence) { + $namespaceName = $sequence->getNamespaceName(); $seqName = $sequence->getFullQualifiedName($this->getName()); + if (isset($this->_sequences[$seqName])) { throw SchemaException::sequenceAlreadyExists($seqName); } + + if ( ! $sequence->isInDefaultNamespace($this->getName()) && ! $this->hasNamespace($namespaceName)) { + $this->createNamespace($namespaceName); + } + $this->_sequences[$seqName] = $sequence; } + /** + * Returns the namespaces of this schema. + * + * @return array A list of namespace names. + */ + public function getNamespaces() + { + return $this->namespaces; + } + /** * Gets all tables of this schema. * @@ -167,9 +207,8 @@ class Schema extends AbstractAsset */ private function getFullQualifiedAssetName($name) { - if ($this->isIdentifierQuoted($name)) { - $name = $this->trimQuotes($name); - } + $name = $this->getUnquotedAssetName($name); + if (strpos($name, ".") === false) { $name = $this->getName() . "." . $name; } @@ -177,6 +216,36 @@ class Schema extends AbstractAsset return strtolower($name); } + /** + * Returns the unquoted representation of a given asset name. + * + * @param string $assetName Quoted or unquoted representation of an asset name. + * + * @return string + */ + private function getUnquotedAssetName($assetName) + { + if ($this->isIdentifierQuoted($assetName)) { + return $this->trimQuotes($assetName); + } + + return $assetName; + } + + /** + * Does this schema have a namespace with the given name? + * + * @param string $namespaceName + * + * @return boolean + */ + public function hasNamespace($namespaceName) + { + $namespaceName = strtolower($this->getUnquotedAssetName($namespaceName)); + + return isset($this->namespaces[$namespaceName]); + } + /** * Does this schema have a table with the given name? * @@ -223,7 +292,7 @@ class Schema extends AbstractAsset public function getSequence($sequenceName) { $sequenceName = $this->getFullQualifiedAssetName($sequenceName); - if(!$this->hasSequence($sequenceName)) { + if (!$this->hasSequence($sequenceName)) { throw SchemaException::sequenceDoesNotExist($sequenceName); } @@ -238,6 +307,26 @@ class Schema extends AbstractAsset return $this->_sequences; } + /** + * Creates a new namespace. + * + * @param string $namespaceName The name of the namespace to create. + * + * @return \Doctrine\DBAL\Schema\Schema This schema instance. + */ + public function createNamespace($namespaceName) + { + $unquotedNamespaceName = strtolower($this->getUnquotedAssetName($namespaceName)); + + if (isset($this->namespaces[$unquotedNamespaceName])) { + throw SchemaException::namespaceAlreadyExists($unquotedNamespaceName); + } + + $this->namespaces[$unquotedNamespaceName] = $namespaceName; + + return $this; + } + /** * Creates a new table. * @@ -389,9 +478,16 @@ class Schema extends AbstractAsset { $visitor->acceptSchema($this); + if ($visitor instanceof NamespaceVisitor) { + foreach ($this->namespaces as $namespace) { + $visitor->acceptNamespace($namespace); + } + } + foreach ($this->_tables as $table) { $table->visit($visitor); } + foreach ($this->_sequences as $sequence) { $sequence->visit($visitor); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php index e8ba6fd56b..cc23237d87 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php @@ -63,7 +63,7 @@ class SchemaConfig */ public function setExplicitForeignKeyIndexes($flag) { - $this->hasExplicitForeignKeyIndexes = (bool)$flag; + $this->hasExplicitForeignKeyIndexes = (bool) $flag; } /** @@ -73,7 +73,7 @@ class SchemaConfig */ public function setMaxIdentifierLength($length) { - $this->maxIdentifierLength = (int)$length; + $this->maxIdentifierLength = (int) $length; } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php index 4fcdc308f6..35afe1febc 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php @@ -37,6 +37,20 @@ class SchemaDiff */ public $fromSchema; + /** + * All added namespaces. + * + * @var string[] + */ + public $newNamespaces = array(); + + /** + * All removed namespaces. + * + * @var string[] + */ + public $removedNamespaces = array(); + /** * All added tables. * @@ -132,6 +146,12 @@ class SchemaDiff { $sql = array(); + if ($platform->supportsSchemas()) { + foreach ($this->newNamespaces as $newNamespace) { + $sql[] = $platform->getCreateSchemaSQL($newNamespace); + } + } + if ($platform->supportsForeignKeyConstraints() && $saveMode == false) { foreach ($this->orphanedForeignKeys as $orphanedForeignKey) { $sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTableName()); diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php index 2b2d2ef316..152f374da0 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php @@ -31,6 +31,7 @@ class SchemaException extends \Doctrine\DBAL\DBALException const SEQUENCE_ALREADY_EXISTS = 80; const INDEX_INVALID_NAME = 90; const FOREIGNKEY_DOESNT_EXIST = 100; + const NAMESPACE_ALREADY_EXISTS = 110; /** * @param string $tableName @@ -85,6 +86,19 @@ class SchemaException extends \Doctrine\DBAL\DBALException return new self("There is no column with name '$columnName' on table '$table'.", self::COLUMN_DOESNT_EXIST); } + /** + * @param string $namespaceName + * + * @return \Doctrine\DBAL\Schema\SchemaException + */ + static public function namespaceAlreadyExists($namespaceName) + { + return new self( + sprintf("The namespace with name '%s' already exists.", $namespaceName), + self::NAMESPACE_ALREADY_EXISTS + ); + } + /** * @param string $tableName * @@ -162,6 +176,6 @@ class SchemaException extends \Doctrine\DBAL\DBALException */ static public function alterTableChangeNotSupported($changeName) { - return new self ("Alter table change not supported, given '$changeName'"); + return new self("Alter table change not supported, given '$changeName'"); } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php index 1077237593..cc5b5016e1 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php @@ -33,23 +33,30 @@ class Sequence extends AbstractAsset /** * @var integer */ - protected $_allocationSize = 1; + protected $allocationSize = 1; /** * @var integer */ - protected $_initialValue = 1; + protected $initialValue = 1; /** - * @param string $name - * @param integer $allocationSize - * @param integer $initialValue + * @var integer|null + */ + protected $cache = null; + + /** + * @param string $name + * @param integer $allocationSize + * @param integer $initialValue + * @param integer|null $cache */ - public function __construct($name, $allocationSize=1, $initialValue=1) + public function __construct($name, $allocationSize = 1, $initialValue = 1, $cache = null) { $this->_setName($name); - $this->_allocationSize = (is_numeric($allocationSize))?$allocationSize:1; - $this->_initialValue = (is_numeric($initialValue))?$initialValue:1; + $this->allocationSize = is_numeric($allocationSize) ? $allocationSize : 1; + $this->initialValue = is_numeric($initialValue) ? $initialValue : 1; + $this->cache = $cache; } /** @@ -57,7 +64,7 @@ class Sequence extends AbstractAsset */ public function getAllocationSize() { - return $this->_allocationSize; + return $this->allocationSize; } /** @@ -65,27 +72,51 @@ class Sequence extends AbstractAsset */ public function getInitialValue() { - return $this->_initialValue; + return $this->initialValue; + } + + /** + * @return integer|null + */ + public function getCache() + { + return $this->cache; } /** * @param integer $allocationSize * - * @return void + * @return \Doctrine\DBAL\Schema\Sequence */ public function setAllocationSize($allocationSize) { - $this->_allocationSize = (is_numeric($allocationSize))?$allocationSize:1; + $this->allocationSize = is_numeric($allocationSize) ? $allocationSize : 1; + + return $this; } /** * @param integer $initialValue * - * @return void + * @return \Doctrine\DBAL\Schema\Sequence */ public function setInitialValue($initialValue) { - $this->_initialValue = (is_numeric($initialValue))?$initialValue:1; + $this->initialValue = is_numeric($initialValue) ? $initialValue : 1; + + return $this; + } + + /** + * @param integer $cache + * + * @return \Doctrine\DBAL\Schema\Sequence + */ + public function setCache($cache) + { + $this->cache = $cache; + + return $this; } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php index 1dfc846764..08c90cf984 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php @@ -20,6 +20,8 @@ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Types\StringType; +use Doctrine\DBAL\Types\TextType; /** * Sqlite SchemaManager. @@ -164,10 +166,17 @@ class SqliteSchemaManager extends AbstractSchemaManager $indexBuffer = array(); // fetch primary - $stmt = $this->_conn->executeQuery( "PRAGMA TABLE_INFO ('$tableName')" ); + $stmt = $this->_conn->executeQuery("PRAGMA TABLE_INFO ('$tableName')"); $indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC); - foreach($indexArray as $indexColumnRow) { - if($indexColumnRow['pk'] !== "0") { + usort($indexArray, function($a, $b) { + if ($a['pk'] == $b['pk']) { + return $a['cid'] - $b['cid']; + } + + return $a['pk'] - $b['pk']; + }); + foreach ($indexArray as $indexColumnRow) { + if ($indexColumnRow['pk'] != "0") { $indexBuffer[] = array( 'key_name' => 'primary', 'primary' => true, @@ -178,7 +187,7 @@ class SqliteSchemaManager extends AbstractSchemaManager } // fetch regular indexes - foreach($tableIndexes as $tableIndex) { + foreach ($tableIndexes as $tableIndex) { // Ignore indexes with reserved names, e.g. autoindexes if (strpos($tableIndex['name'], 'sqlite_') !== 0) { $keyName = $tableIndex['name']; @@ -187,10 +196,10 @@ class SqliteSchemaManager extends AbstractSchemaManager $idx['primary'] = false; $idx['non_unique'] = $tableIndex['unique']?false:true; - $stmt = $this->_conn->executeQuery( "PRAGMA INDEX_INFO ( '{$keyName}' )" ); + $stmt = $this->_conn->executeQuery("PRAGMA INDEX_INFO ('{$keyName}')"); $indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC); - foreach ( $indexArray as $indexColumnRow ) { + foreach ($indexArray as $indexColumnRow) { $idx['column_name'] = $indexColumnRow['name']; $indexBuffer[] = $idx; } @@ -217,8 +226,11 @@ class SqliteSchemaManager extends AbstractSchemaManager protected function _getPortableTableColumnList($table, $database, $tableColumns) { $list = parent::_getPortableTableColumnList($table, $database, $tableColumns); + + // find column with autoincrement $autoincrementColumn = null; $autoincrementCount = 0; + foreach ($tableColumns as $tableColumn) { if ('0' != $tableColumn['pk']) { $autoincrementCount++; @@ -236,6 +248,18 @@ class SqliteSchemaManager extends AbstractSchemaManager } } + // inspect column collation + $createSql = $this->_conn->fetchAll("SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = 'table' AND name = '$table'"); + $createSql = isset($createSql[0]['sql']) ? $createSql[0]['sql'] : ''; + + foreach ($list as $columnName => $column) { + $type = $column->getType(); + + if ($type instanceof StringType || $type instanceof TextType) { + $column->setPlatformOption('collation', $this->parseColumnCollationFromSQL($columnName, $createSql) ?: 'BINARY'); + } + } + return $list; } @@ -263,7 +287,7 @@ class SqliteSchemaManager extends AbstractSchemaManager $fixed = false; $type = $this->_platform->getDoctrineTypeMapping($dbType); $default = $tableColumn['dflt_value']; - if ($default == 'NULL') { + if ($default == 'NULL') { $default = null; } if ($default !== null) { @@ -291,7 +315,7 @@ class SqliteSchemaManager extends AbstractSchemaManager if (isset($tableColumn['length'])) { if (strpos($tableColumn['length'], ',') === false) { $tableColumn['length'] .= ",0"; - } + } list($precision, $scale) = array_map('trim', explode(',', $tableColumn['length'])); } $length = null; @@ -353,7 +377,7 @@ class SqliteSchemaManager extends AbstractSchemaManager } $result = array(); - foreach($list as $constraint) { + foreach ($list as $constraint) { $result[] = new ForeignKeyConstraint( array_values($constraint['local']), $constraint['foreignTable'], array_values($constraint['foreign']), $constraint['name'], @@ -393,4 +417,17 @@ class SqliteSchemaManager extends AbstractSchemaManager return $tableDiff; } + + private function parseColumnCollationFromSQL($column, $sql) + { + if (preg_match( + '{(?:'.preg_quote($column).'|'.preg_quote($this->_platform->quoteSingleIdentifier($column)).') + [^,(]+(?:\([^()]+\)[^,]*)? + (?:(?:DEFAULT|CHECK)\s*(?:\(.*?\))?[^,]*)* + COLLATE\s+["\']?([^\s,"\')]+)}isx', $sql, $match)) { + return $match[1]; + } + + return false; + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php index fc1bec1be0..3158df47de 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php @@ -47,7 +47,7 @@ abstract class AbstractSchemaSynchronizer implements SchemaSynchronizer foreach ($sql as $s) { try { $this->conn->exec($s); - } catch(\Exception $e) { + } catch (\Exception $e) { } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php index 9e28cb0fe2..7cab7a5b3a 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php @@ -83,7 +83,7 @@ class SingleDatabaseSynchronizer extends AbstractSchemaSynchronizer $fullSchema = $sm->createSchema(); foreach ($fullSchema->getTables() as $table) { - if ( $dropSchema->hasTable($table->getName())) { + if ($dropSchema->hasTable($table->getName())) { $visitor->acceptTable($table); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php index 37a9962ad5..857caeb085 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php @@ -38,12 +38,17 @@ class Table extends AbstractAsset protected $_name = null; /** - * @var \Doctrine\DBAL\Schema\Column[] + * @var Column[] */ protected $_columns = array(); /** - * @var \Doctrine\DBAL\Schema\Index[] + * @var Index[] + */ + private $implicitIndexes = array(); + + /** + * @var Index[] */ protected $_indexes = array(); @@ -53,7 +58,7 @@ class Table extends AbstractAsset protected $_primaryKeyName = false; /** - * @var \Doctrine\DBAL\Schema\ForeignKeyConstraint[] + * @var ForeignKeyConstraint[] */ protected $_fkConstraints = array(); @@ -63,19 +68,19 @@ class Table extends AbstractAsset protected $_options = array(); /** - * @var \Doctrine\DBAL\Schema\SchemaConfig + * @var SchemaConfig */ protected $_schemaConfig = null; /** - * @param string $tableName - * @param array $columns - * @param array $indexes - * @param array $fkConstraints - * @param integer $idGeneratorType - * @param array $options + * @param string $tableName + * @param Column[] $columns + * @param Index[] $indexes + * @param ForeignKeyConstraint[] $fkConstraints + * @param integer $idGeneratorType + * @param array $options * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function __construct($tableName, array $columns=array(), array $indexes=array(), array $fkConstraints=array(), $idGeneratorType = 0, array $options=array()) { @@ -84,7 +89,6 @@ class Table extends AbstractAsset } $this->_setName($tableName); - $this->_idGeneratorType = $idGeneratorType; foreach ($columns as $column) { $this->_addColumn($column); @@ -102,7 +106,7 @@ class Table extends AbstractAsset } /** - * @param \Doctrine\DBAL\Schema\SchemaConfig $schemaConfig + * @param SchemaConfig $schemaConfig * * @return void */ @@ -129,36 +133,37 @@ class Table extends AbstractAsset * @param array $columns * @param string|boolean $indexName * - * @return \Doctrine\DBAL\Schema\Table + * @return self */ public function setPrimaryKey(array $columns, $indexName = false) { - $primaryKey = $this->_createIndex($columns, $indexName ?: "primary", true, true); + $this->_addIndex($this->_createIndex($columns, $indexName ?: "primary", true, true)); foreach ($columns as $columnName) { $column = $this->getColumn($columnName); $column->setNotnull(true); } - return $primaryKey; + return $this; } /** * @param array $columnNames * @param string|null $indexName * @param array $flags + * @param array $options * - * @return \Doctrine\DBAL\Schema\Table + * @return self */ - public function addIndex(array $columnNames, $indexName = null, array $flags = array()) + public function addIndex(array $columnNames, $indexName = null, array $flags = array(), array $options = array()) { - if($indexName == null) { + if ($indexName == null) { $indexName = $this->_generateIdentifierName( array_merge(array($this->getName()), $columnNames), "idx", $this->_getMaxIdentifierLength() ); } - return $this->_createIndex($columnNames, $indexName, false, false, $flags); + return $this->_addIndex($this->_createIndex($columnNames, $indexName, false, false, $flags, $options)); } /** @@ -179,11 +184,11 @@ class Table extends AbstractAsset * * @return void * - * @throws \Doctrine\DBAL\Schema\SchemaException If the index does not exist. + * @throws SchemaException If the index does not exist. */ public function dropIndex($indexName) { - $indexName = strtolower($indexName); + $indexName = $this->normalizeIdentifier($indexName); if ( ! $this->hasIndex($indexName)) { throw SchemaException::indexDoesNotExist($indexName, $this->_name); } @@ -193,10 +198,11 @@ class Table extends AbstractAsset /** * @param array $columnNames * @param string|null $indexName + * @param array $options * - * @return \Doctrine\DBAL\Schema\Table + * @return self */ - public function addUniqueIndex(array $columnNames, $indexName = null) + public function addUniqueIndex(array $columnNames, $indexName = null, array $options = array()) { if ($indexName === null) { $indexName = $this->_generateIdentifierName( @@ -204,7 +210,53 @@ class Table extends AbstractAsset ); } - return $this->_createIndex($columnNames, $indexName, true, false); + return $this->_addIndex($this->_createIndex($columnNames, $indexName, true, false, array(), $options)); + } + + /** + * Renames an index. + * + * @param string $oldIndexName The name of the index to rename from. + * @param string|null $newIndexName The name of the index to rename to. + * If null is given, the index name will be auto-generated. + * + * @return self This table instance. + * + * @throws SchemaException if no index exists for the given current name + * or if an index with the given new name already exists on this table. + */ + public function renameIndex($oldIndexName, $newIndexName = null) + { + $oldIndexName = $this->normalizeIdentifier($oldIndexName); + $normalizedNewIndexName = $this->normalizeIdentifier($newIndexName); + + if ($oldIndexName === $normalizedNewIndexName) { + return $this; + } + + if ( ! $this->hasIndex($oldIndexName)) { + throw SchemaException::indexDoesNotExist($oldIndexName, $this->_name); + } + + if ($this->hasIndex($normalizedNewIndexName)) { + throw SchemaException::indexAlreadyExists($normalizedNewIndexName, $this->_name); + } + + $oldIndex = $this->_indexes[$oldIndexName]; + + if ($oldIndex->isPrimary()) { + $this->dropPrimaryKey(); + + return $this->setPrimaryKey($oldIndex->getColumns(), $newIndexName); + } + + unset($this->_indexes[$oldIndexName]); + + if ($oldIndex->isUnique()) { + return $this->addUniqueIndex($oldIndex->getColumns(), $newIndexName); + } + + return $this->addIndex($oldIndex->getColumns(), $newIndexName, $oldIndex->getFlags()); } /** @@ -232,14 +284,15 @@ class Table extends AbstractAsset * @param boolean $isUnique * @param boolean $isPrimary * @param array $flags + * @param array $options * - * @return \Doctrine\DBAL\Schema\Table + * @return Index * - * @throws \Doctrine\DBAL\Schema\SchemaException + * @throws SchemaException */ - private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary, array $flags = array()) + private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary, array $flags = array(), array $options = array()) { - if (preg_match('(([^a-zA-Z0-9_]+))', $indexName)) { + if (preg_match('(([^a-zA-Z0-9_]+))', $this->normalizeIdentifier($indexName))) { throw SchemaException::indexNameInvalid($indexName); } @@ -253,9 +306,7 @@ class Table extends AbstractAsset } } - $this->_addIndex(new Index($indexName, $columnNames, $isUnique, $isPrimary, $flags)); - - return $this; + return new Index($indexName, $columnNames, $isUnique, $isPrimary, $flags, $options); } /** @@ -263,7 +314,7 @@ class Table extends AbstractAsset * @param string $typeName * @param array $options * - * @return \Doctrine\DBAL\Schema\Column + * @return Column */ public function addColumn($columnName, $typeName, array $options=array()) { @@ -280,9 +331,9 @@ class Table extends AbstractAsset * @param string $oldColumnName * @param string $newColumnName * - * @return \Doctrine\DBAL\Schema\Table + * @return self * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function renameColumn($oldColumnName, $newColumnName) { @@ -297,7 +348,7 @@ class Table extends AbstractAsset * @param string $columnName * @param array $options * - * @return \Doctrine\DBAL\Schema\Table + * @return self */ public function changeColumn($columnName, array $options) { @@ -312,11 +363,11 @@ class Table extends AbstractAsset * * @param string $columnName * - * @return \Doctrine\DBAL\Schema\Table + * @return self */ public function dropColumn($columnName) { - $columnName = strtolower($columnName); + $columnName = $this->normalizeIdentifier($columnName); unset($this->_columns[$columnName]); return $this; @@ -327,17 +378,17 @@ class Table extends AbstractAsset * * Name is inferred from the local columns. * - * @param \Doctrine\DBAL\Schema\Table $foreignTable - * @param array $localColumnNames - * @param array $foreignColumnNames - * @param array $options - * @param string|null $constraintName + * @param Table|string $foreignTable Table schema instance or table name + * @param array $localColumnNames + * @param array $foreignColumnNames + * @param array $options + * @param string|null $constraintName * - * @return \Doctrine\DBAL\Schema\Table + * @return self */ public function addForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array(), $constraintName = null) { - $constraintName = $constraintName ?: $this->_generateIdentifierName(array_merge((array)$this->getName(), $localColumnNames), "fk", $this->_getMaxIdentifierLength()); + $constraintName = $constraintName ?: $this->_generateIdentifierName(array_merge((array) $this->getName(), $localColumnNames), "fk", $this->_getMaxIdentifierLength()); return $this->addNamedForeignKeyConstraint($constraintName, $foreignTable, $localColumnNames, $foreignColumnNames, $options); } @@ -349,12 +400,12 @@ class Table extends AbstractAsset * * @deprecated Use {@link addForeignKeyConstraint} * - * @param \Doctrine\DBAL\Schema\Table $foreignTable - * @param array $localColumnNames - * @param array $foreignColumnNames - * @param array $options + * @param Table|string $foreignTable Table schema instance or table name + * @param array $localColumnNames + * @param array $foreignColumnNames + * @param array $options * - * @return \Doctrine\DBAL\Schema\Table + * @return self */ public function addUnnamedForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array()) { @@ -366,15 +417,15 @@ class Table extends AbstractAsset * * @deprecated Use {@link addForeignKeyConstraint} * - * @param string $name - * @param \Doctrine\DBAL\Schema\Table $foreignTable - * @param array $localColumnNames - * @param array $foreignColumnNames - * @param array $options + * @param string $name + * @param Table|string $foreignTable Table schema instance or table name + * @param array $localColumnNames + * @param array $foreignColumnNames + * @param array $options * - * @return \Doctrine\DBAL\Schema\Table + * @return self * - * @throws \Doctrine\DBAL\Schema\SchemaException + * @throws SchemaException */ public function addNamedForeignKeyConstraint($name, $foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array()) { @@ -404,7 +455,7 @@ class Table extends AbstractAsset * @param string $name * @param string $value * - * @return \Doctrine\DBAL\Schema\Table + * @return self */ public function addOption($name, $value) { @@ -414,16 +465,16 @@ class Table extends AbstractAsset } /** - * @param \Doctrine\DBAL\Schema\Column $column + * @param Column $column * * @return void * - * @throws \Doctrine\DBAL\Schema\SchemaException + * @throws SchemaException */ protected function _addColumn(Column $column) { $columnName = $column->getName(); - $columnName = strtolower($columnName); + $columnName = $this->normalizeIdentifier($columnName); if (isset($this->_columns[$columnName])) { throw SchemaException::columnAlreadyExists($this->getName(), $columnName); @@ -435,33 +486,32 @@ class Table extends AbstractAsset /** * Adds an index to the table. * - * @param \Doctrine\DBAL\Schema\Index $indexCandidate + * @param Index $indexCandidate * - * @return \Doctrine\DBAL\Schema\Table + * @return self * - * @throws \Doctrine\DBAL\Schema\SchemaException + * @throws SchemaException */ protected function _addIndex(Index $indexCandidate) { - // check for duplicates - foreach ($this->_indexes as $existingIndex) { - if ($indexCandidate->isFullfilledBy($existingIndex)) { - return $this; + $indexName = $indexCandidate->getName(); + $indexName = $this->normalizeIdentifier($indexName); + $replacedImplicitIndexes = array(); + + foreach ($this->implicitIndexes as $name => $implicitIndex) { + if ($implicitIndex->isFullfilledBy($indexCandidate) && isset($this->_indexes[$name])) { + $replacedImplicitIndexes[] = $name; } } - $indexName = $indexCandidate->getName(); - $indexName = strtolower($indexName); - - if (isset($this->_indexes[$indexName]) || ($this->_primaryKeyName != false && $indexCandidate->isPrimary())) { + if ((isset($this->_indexes[$indexName]) && ! in_array($indexName, $replacedImplicitIndexes, true)) || + ($this->_primaryKeyName != false && $indexCandidate->isPrimary()) + ) { throw SchemaException::indexAlreadyExists($indexName, $this->_name); } - // remove overruled indexes - foreach ($this->_indexes as $idxKey => $existingIndex) { - if ($indexCandidate->overrules($existingIndex)) { - unset($this->_indexes[$idxKey]); - } + foreach ($replacedImplicitIndexes as $name) { + unset($this->_indexes[$name], $this->implicitIndexes[$name]); } if ($indexCandidate->isPrimary()) { @@ -474,7 +524,7 @@ class Table extends AbstractAsset } /** - * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $constraint + * @param ForeignKeyConstraint $constraint * * @return void */ @@ -482,20 +532,35 @@ class Table extends AbstractAsset { $constraint->setLocalTable($this); - if(strlen($constraint->getName())) { + if (strlen($constraint->getName())) { $name = $constraint->getName(); } else { $name = $this->_generateIdentifierName( - array_merge((array)$this->getName(), $constraint->getLocalColumns()), "fk", $this->_getMaxIdentifierLength() + array_merge((array) $this->getName(), $constraint->getLocalColumns()), "fk", $this->_getMaxIdentifierLength() ); } - $name = strtolower($name); + $name = $this->normalizeIdentifier($name); $this->_fkConstraints[$name] = $constraint; + // add an explicit index on the foreign key columns. If there is already an index that fulfils this requirements drop the request. // In the case of __construct calling this method during hydration from schema-details all the explicitly added indexes // lead to duplicates. This creates computation overhead in this case, however no duplicate indexes are ever added (based on columns). - $this->addIndex($constraint->getColumns()); + $indexName = $this->_generateIdentifierName( + array_merge(array($this->getName()), $constraint->getColumns()), + "idx", + $this->_getMaxIdentifierLength() + ); + $indexCandidate = $this->_createIndex($constraint->getColumns(), $indexName, false, false); + + foreach ($this->_indexes as $existingIndex) { + if ($indexCandidate->isFullfilledBy($existingIndex)) { + return; + } + } + + $this->_addIndex($indexCandidate); + $this->implicitIndexes[$this->normalizeIdentifier($indexName)] = $indexCandidate; } /** @@ -507,7 +572,7 @@ class Table extends AbstractAsset */ public function hasForeignKey($constraintName) { - $constraintName = strtolower($constraintName); + $constraintName = $this->normalizeIdentifier($constraintName); return isset($this->_fkConstraints[$constraintName]); } @@ -517,14 +582,14 @@ class Table extends AbstractAsset * * @param string $constraintName The constraint name. * - * @return \Doctrine\DBAL\Schema\ForeignKeyConstraint + * @return ForeignKeyConstraint * - * @throws \Doctrine\DBAL\Schema\SchemaException If the foreign key does not exist. + * @throws SchemaException If the foreign key does not exist. */ public function getForeignKey($constraintName) { - $constraintName = strtolower($constraintName); - if(!$this->hasForeignKey($constraintName)) { + $constraintName = $this->normalizeIdentifier($constraintName); + if (!$this->hasForeignKey($constraintName)) { throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); } @@ -538,12 +603,12 @@ class Table extends AbstractAsset * * @return void * - * @throws \Doctrine\DBAL\Schema\SchemaException + * @throws SchemaException */ public function removeForeignKey($constraintName) { - $constraintName = strtolower($constraintName); - if(!$this->hasForeignKey($constraintName)) { + $constraintName = $this->normalizeIdentifier($constraintName); + if (!$this->hasForeignKey($constraintName)) { throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); } @@ -551,7 +616,7 @@ class Table extends AbstractAsset } /** - * @return \Doctrine\DBAL\Schema\Column[] + * @return Column[] */ public function getColumns() { @@ -569,7 +634,7 @@ class Table extends AbstractAsset } $colNames = array_unique(array_merge($pkCols, $fkCols, array_keys($columns))); - uksort($columns, function($a, $b) use($colNames) { + uksort($columns, function ($a, $b) use ($colNames) { return (array_search($a, $colNames) >= array_search($b, $colNames)); }); @@ -585,7 +650,7 @@ class Table extends AbstractAsset */ public function hasColumn($columnName) { - $columnName = $this->trimQuotes(strtolower($columnName)); + $columnName = $this->normalizeIdentifier($columnName); return isset($this->_columns[$columnName]); } @@ -595,13 +660,13 @@ class Table extends AbstractAsset * * @param string $columnName The column name. * - * @return \Doctrine\DBAL\Schema\Column + * @return Column * - * @throws \Doctrine\DBAL\Schema\SchemaException If the column does not exist. + * @throws SchemaException If the column does not exist. */ public function getColumn($columnName) { - $columnName = strtolower($this->trimQuotes($columnName)); + $columnName = $this->normalizeIdentifier($columnName); if ( ! $this->hasColumn($columnName)) { throw SchemaException::columnDoesNotExist($columnName, $this->_name); } @@ -612,7 +677,7 @@ class Table extends AbstractAsset /** * Returns the primary key. * - * @return \Doctrine\DBAL\Schema\Index|null The primary key, or null if this Table has no primary key. + * @return Index|null The primary key, or null if this Table has no primary key. */ public function getPrimaryKey() { @@ -628,7 +693,7 @@ class Table extends AbstractAsset * * @return array * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ public function getPrimaryKeyColumns() { @@ -658,7 +723,7 @@ class Table extends AbstractAsset */ public function hasIndex($indexName) { - $indexName = strtolower($indexName); + $indexName = $this->normalizeIdentifier($indexName); return (isset($this->_indexes[$indexName])); } @@ -668,13 +733,13 @@ class Table extends AbstractAsset * * @param string $indexName The index name. * - * @return \Doctrine\DBAL\Schema\Index + * @return Index * - * @throws \Doctrine\DBAL\Schema\SchemaException If the index does not exist. + * @throws SchemaException If the index does not exist. */ public function getIndex($indexName) { - $indexName = strtolower($indexName); + $indexName = $this->normalizeIdentifier($indexName); if ( ! $this->hasIndex($indexName)) { throw SchemaException::indexDoesNotExist($indexName, $this->_name); } @@ -683,7 +748,7 @@ class Table extends AbstractAsset } /** - * @return \Doctrine\DBAL\Schema\Index[] + * @return Index[] */ public function getIndexes() { @@ -693,7 +758,7 @@ class Table extends AbstractAsset /** * Returns the foreign key constraints. * - * @return \Doctrine\DBAL\Schema\ForeignKeyConstraint[] + * @return ForeignKeyConstraint[] */ public function getForeignKeys() { @@ -729,7 +794,7 @@ class Table extends AbstractAsset } /** - * @param \Doctrine\DBAL\Schema\Visitor\Visitor $visitor + * @param Visitor $visitor * * @return void */ @@ -768,4 +833,18 @@ class Table extends AbstractAsset $this->_fkConstraints[$k]->setLocalTable($this); } } + + /** + * Normalizes a given identifier. + * + * Trims quotes and lowercases the given identifier. + * + * @param string $identifier The identifier to normalize. + * + * @return string The normalized identifier. + */ + private function normalizeIdentifier($identifier) + { + return $this->trimQuotes(strtolower($identifier)); + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php index a61f0ce265..a837fab674 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php @@ -19,6 +19,8 @@ namespace Doctrine\DBAL\Schema; +use Doctrine\DBAL\Platforms\AbstractPlatform; + /** * Table Diff. * @@ -48,7 +50,7 @@ class TableDiff /** * All changed fields. * - * @var \Doctrine\DBAL\Schema\Column[] + * @var \Doctrine\DBAL\Schema\ColumnDiff[] */ public $changedColumns = array(); @@ -87,6 +89,13 @@ class TableDiff */ public $removedIndexes = array(); + /** + * Indexes that are only renamed but are identical otherwise. + * + * @var \Doctrine\DBAL\Schema\Index[] + */ + public $renamedIndexes = array(); + /** * All added foreign key definitions * @@ -116,14 +125,14 @@ class TableDiff /** * Constructs an TableDiff object. * - * @param string $tableName - * @param \Doctrine\DBAL\Schema\Column[] $addedColumns - * @param \Doctrine\DBAL\Schema\Column[] $changedColumns - * @param \Doctrine\DBAL\Schema\Column[] $removedColumns - * @param \Doctrine\DBAL\Schema\Index[] $addedIndexes - * @param \Doctrine\DBAL\Schema\Index[] $changedIndexes - * @param \Doctrine\DBAL\Schema\Index[] $removedIndexes - * @param \Doctrine\DBAL\Schema\Table|null $fromTable + * @param string $tableName + * @param \Doctrine\DBAL\Schema\Column[] $addedColumns + * @param \Doctrine\DBAL\Schema\ColumnDiff[] $changedColumns + * @param \Doctrine\DBAL\Schema\Column[] $removedColumns + * @param \Doctrine\DBAL\Schema\Index[] $addedIndexes + * @param \Doctrine\DBAL\Schema\Index[] $changedIndexes + * @param \Doctrine\DBAL\Schema\Index[] $removedIndexes + * @param \Doctrine\DBAL\Schema\Table|null $fromTable */ public function __construct($tableName, $addedColumns = array(), $changedColumns = array(), $removedColumns = array(), $addedIndexes = array(), @@ -138,4 +147,24 @@ class TableDiff $this->removedIndexes = $removedIndexes; $this->fromTable = $fromTable; } + + /** + * @param AbstractPlatform $platform The platform to use for retrieving this table diff's name. + * + * @return \Doctrine\DBAL\Schema\Identifier + */ + public function getName(AbstractPlatform $platform) + { + return new Identifier( + $this->fromTable instanceof Table ? $this->fromTable->getQuotedName($platform) : $this->name + ); + } + + /** + * @return \Doctrine\DBAL\Schema\Identifier|boolean + */ + public function getNewName() + { + return $this->newName ? new Identifier($this->newName) : $this->newName; + } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php index af1b63ea7b..7bf5b2fec3 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php @@ -19,7 +19,6 @@ namespace Doctrine\DBAL\Schema\Visitor; -use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Column; @@ -30,7 +29,7 @@ use Doctrine\DBAL\Schema\Index; /** * Abstract Visitor with empty methods for easy extension. */ -class AbstractVisitor implements Visitor +class AbstractVisitor implements Visitor, NamespaceVisitor { /** * @param \Doctrine\DBAL\Schema\Schema $schema @@ -39,6 +38,13 @@ class AbstractVisitor implements Visitor { } + /** + * {@inheritdoc} + */ + public function acceptNamespace($namespaceName) + { + } + /** * @param \Doctrine\DBAL\Schema\Table $table */ diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php index ad28e6483d..5e0c6ed437 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php @@ -26,6 +26,11 @@ use Doctrine\DBAL\Schema\Sequence; class CreateSchemaSqlCollector extends AbstractVisitor { + /** + * @var array + */ + private $createNamespaceQueries = array(); + /** * @var array */ @@ -58,14 +63,22 @@ class CreateSchemaSqlCollector extends AbstractVisitor /** * {@inheritdoc} */ - public function acceptTable(Table $table) + public function acceptNamespace($namespaceName) { - $namespace = $this->getNamespace($table); + if ($this->platform->supportsSchemas()) { + $this->createNamespaceQueries = array_merge( + $this->createNamespaceQueries, + (array) $this->platform->getCreateSchemaSQL($namespaceName) + ); + } + } - $this->createTableQueries[$namespace] = array_merge( - $this->createTableQueries[$namespace], - $this->platform->getCreateTableSQL($table) - ); + /** + * {@inheritdoc} + */ + public function acceptTable(Table $table) + { + $this->createTableQueries = array_merge($this->createTableQueries, (array) $this->platform->getCreateTableSQL($table)); } /** @@ -73,11 +86,9 @@ class CreateSchemaSqlCollector extends AbstractVisitor */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) { - $namespace = $this->getNamespace($localTable); - if ($this->platform->supportsForeignKeyConstraints()) { - $this->createFkConstraintQueries[$namespace] = array_merge( - $this->createFkConstraintQueries[$namespace], + $this->createFkConstraintQueries = array_merge( + $this->createFkConstraintQueries, (array) $this->platform->getCreateForeignKeySQL( $fkConstraint, $localTable ) @@ -90,36 +101,18 @@ class CreateSchemaSqlCollector extends AbstractVisitor */ public function acceptSequence(Sequence $sequence) { - $namespace = $this->getNamespace($sequence); - - $this->createSequenceQueries[$namespace] = array_merge( - $this->createSequenceQueries[$namespace], - (array)$this->platform->getCreateSequenceSQL($sequence) + $this->createSequenceQueries = array_merge( + $this->createSequenceQueries, + (array) $this->platform->getCreateSequenceSQL($sequence) ); } - /** - * @param \Doctrine\DBAL\Schema\AbstractAsset $asset - * - * @return string - */ - private function getNamespace($asset) - { - $namespace = $asset->getNamespaceName() ?: 'default'; - if ( !isset($this->createTableQueries[$namespace])) { - $this->createTableQueries[$namespace] = array(); - $this->createSequenceQueries[$namespace] = array(); - $this->createFkConstraintQueries[$namespace] = array(); - } - - return $namespace; - } - /** * @return void */ public function resetQueries() { + $this->createNamespaceQueries = array(); $this->createTableQueries = array(); $this->createSequenceQueries = array(); $this->createFkConstraintQueries = array(); @@ -134,22 +127,20 @@ class CreateSchemaSqlCollector extends AbstractVisitor { $sql = array(); - foreach (array_keys($this->createTableQueries) as $namespace) { - if ($this->platform->supportsSchemas()) { - // TODO: Create Schema here - } + foreach ($this->createNamespaceQueries as $schemaSql) { + $sql = array_merge($sql, (array) $schemaSql); } foreach ($this->createTableQueries as $schemaSql) { - $sql = array_merge($sql, $schemaSql); + $sql = array_merge($sql, (array) $schemaSql); } foreach ($this->createSequenceQueries as $schemaSql) { - $sql = array_merge($sql, $schemaSql); + $sql = array_merge($sql, (array) $schemaSql); } foreach ($this->createFkConstraintQueries as $schemaSql) { - $sql = array_merge($sql, $schemaSql); + $sql = array_merge($sql, (array) $schemaSql); } return $sql; diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php index 047ac98e62..ab9752d584 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php @@ -50,12 +50,12 @@ class DropSchemaSqlCollector extends AbstractVisitor private $tables; /** - * @var \Doctrine\DBAL\Platforms\AbstractPlatform + * @var AbstractPlatform */ private $platform; /** - * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + * @param AbstractPlatform $platform */ public function __construct(AbstractPlatform $platform) { @@ -80,8 +80,7 @@ class DropSchemaSqlCollector extends AbstractVisitor throw SchemaException::namedForeignKeyRequired($localTable, $fkConstraint); } - $this->constraints->attach($fkConstraint); - $this->constraints[$fkConstraint] = $localTable; + $this->constraints->attach($fkConstraint, $localTable); } /** diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php index e49afdd0db..1573ddf5b2 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php @@ -19,7 +19,6 @@ namespace Doctrine\DBAL\Schema\Visitor; -use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\ForeignKeyConstraint; @@ -55,7 +54,7 @@ class Graphviz extends AbstractVisitor */ public function acceptSchema(Schema $schema) { - $this->output = 'digraph "' . sha1( mt_rand() ) . '" {' . "\n"; + $this->output = 'digraph "' . sha1(mt_rand()) . '" {' . "\n"; $this->output .= 'splines = true;' . "\n"; $this->output .= 'overlap = false;' . "\n"; $this->output .= 'outputorder=edgesfirst;'."\n"; @@ -71,7 +70,7 @@ class Graphviz extends AbstractVisitor $this->output .= $this->createNode( $table->getName(), array( - 'label' => $this->createTableLabel( $table ), + 'label' => $this->createTableLabel($table), 'shape' => 'plaintext', ) ); @@ -91,7 +90,7 @@ class Graphviz extends AbstractVisitor $label .= '' . $table->getName() . ''; // The attributes block - foreach( $table->getColumns() as $column ) { + foreach ($table->getColumns() as $column) { $columnLabel = $column->getName(); $label .= ''; @@ -120,8 +119,7 @@ class Graphviz extends AbstractVisitor private function createNode($name, $options) { $node = $name . " ["; - foreach( $options as $key => $value ) - { + foreach ($options as $key => $value) { $node .= $key . '=' . $value . ' '; } $node .= "]\n"; @@ -139,8 +137,7 @@ class Graphviz extends AbstractVisitor private function createNodeRelation($node1, $node2, $options) { $relation = $node1 . ' -> ' . $node2 . ' ['; - foreach( $options as $key => $value ) - { + foreach ($options as $key => $value) { $relation .= $key . '=' . $value . ' '; } $relation .= "]\n"; diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php new file mode 100644 index 0000000000..da7b1edbca --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php @@ -0,0 +1,37 @@ +. + */ + +namespace Doctrine\DBAL\Schema\Visitor; + +/** + * Visitor that can visit schema namespaces. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +interface NamespaceVisitor +{ + /** + * Accepts a schema namespace name. + * + * @param string $namespaceName The schema namespace name to accept. + */ + public function acceptNamespace($namespaceName); +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php index 05f52bea2d..e328d071cd 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php @@ -19,7 +19,6 @@ namespace Doctrine\DBAL\Schema\Visitor; -use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\ForeignKeyConstraint; @@ -59,7 +58,7 @@ class RemoveNamespacedAssets extends AbstractVisitor */ public function acceptTable(Table $table) { - if ( ! $table->isInDefaultNamespace($this->schema->getName()) ) { + if ( ! $table->isInDefaultNamespace($this->schema->getName())) { $this->schema->dropTable($table->getName()); } } @@ -69,7 +68,7 @@ class RemoveNamespacedAssets extends AbstractVisitor */ public function acceptSequence(Sequence $sequence) { - if ( ! $sequence->isInDefaultNamespace($this->schema->getName()) ) { + if ( ! $sequence->isInDefaultNamespace($this->schema->getName())) { $this->schema->dropSequence($sequence->getName()); } } @@ -88,7 +87,7 @@ class RemoveNamespacedAssets extends AbstractVisitor } $foreignTable = $this->schema->getTable($fkConstraint->getForeignTableName()); - if ( ! $foreignTable->isInDefaultNamespace($this->schema->getName()) ) { + if ( ! $foreignTable->isInDefaultNamespace($this->schema->getName())) { $localTable->removeForeignKey($fkConstraint->getName()); } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php index b139aa22e7..bde4453b35 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php @@ -19,12 +19,10 @@ namespace Doctrine\DBAL\Schema\Visitor; -use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Sequence; -use Doctrine\DBAL\Schema\SchemaException; /** * Visit a SchemaDiff. diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Visitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Visitor.php index 9bd5528c7d..656f0e20c6 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Visitor.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Visitor.php @@ -19,7 +19,6 @@ namespace Doctrine\DBAL\Schema\Visitor; -use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Column; diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php index 6048e814c3..29c041e6dd 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php @@ -19,14 +19,12 @@ namespace Doctrine\DBAL\Sharding; +use Doctrine\Common\EventManager; +use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver; use Doctrine\DBAL\Event\ConnectionEventArgs; use Doctrine\DBAL\Events; -use Doctrine\DBAL\Driver; -use Doctrine\DBAL\Configuration; - -use Doctrine\Common\EventManager; - use Doctrine\DBAL\Sharding\ShardChoser\ShardChoser; /** @@ -104,7 +102,7 @@ class PoolingShardConnection extends Connection } if ( ! ($params['shardChoser'] instanceof ShardChoser)) { - throw new \InvalidArgumentException("The 'shardChoser' configuration is not a valid instance of Doctrine\DBAL\Sharding\ShardChoser\ShardChoser"); + throw new \InvalidArgumentException("The 'shardChoser' configuration is not a valid instance of Doctrine\DBAL\Sharding\ShardChoser\ShardChoser"); } $this->connections[0] = array_merge($params, $params['global']); @@ -128,6 +126,64 @@ class PoolingShardConnection extends Connection parent::__construct($params, $driver, $config, $eventManager); } + /** + * Get active shard id. + * + * @return integer + */ + public function getActiveShardId() + { + return $this->activeShardId; + } + + /** + * {@inheritdoc} + */ + public function getParams() + { + return $this->activeShardId ? $this->connections[$this->activeShardId] : parent::getParams(); + } + + /** + * {@inheritdoc} + */ + public function getHost() + { + $params = $this->getParams(); + + return isset($params['host']) ? $params['host'] : parent::getHost(); + } + + /** + * {@inheritdoc} + */ + public function getPort() + { + $params = $this->getParams(); + + return isset($params['port']) ? $params['port'] : parent::getPort(); + } + + /** + * {@inheritdoc} + */ + public function getUsername() + { + $params = $this->getParams(); + + return isset($params['user']) ? $params['user'] : parent::getUsername(); + } + + /** + * {@inheritdoc} + */ + public function getPassword() + { + $params = $this->getParams(); + + return isset($params['password']) ? $params['password'] : parent::getPassword(); + } + /** * Connects to a given shard. * @@ -155,13 +211,14 @@ class PoolingShardConnection extends Connection if (isset($this->activeConnections[$this->activeShardId])) { $this->_conn = $this->activeConnections[$this->activeShardId]; + return false; } $this->_conn = $this->activeConnections[$this->activeShardId] = $this->connectTo($this->activeShardId); if ($this->_eventManager->hasListeners(Events::postConnect)) { - $eventArgs = new \Doctrine\DBAL\Event\ConnectionEventArgs($this); + $eventArgs = new ConnectionEventArgs($this); $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); } @@ -210,5 +267,6 @@ class PoolingShardConnection extends Connection { $this->_conn = null; $this->activeConnections = null; + $this->activeShardId = null; } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php index d4bdee80fc..64307ca666 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php @@ -19,6 +19,8 @@ namespace Doctrine\DBAL\Sharding; +use Doctrine\DBAL\Sharding\ShardChoser\ShardChoser; + /** * Shard Manager for the Connection Pooling Shard Strategy * @@ -27,12 +29,12 @@ namespace Doctrine\DBAL\Sharding; class PoolingShardManager implements ShardManager { /** - * @var \Doctrine\DBAL\Sharding\PoolingShardConnection + * @var PoolingShardConnection */ private $conn; /** - * @var \Doctrine\DBAL\Sharding\ShardChoser\ShardChoser + * @var ShardChoser */ private $choser; @@ -42,7 +44,7 @@ class PoolingShardManager implements ShardManager private $currentDistributionValue; /** - * @param \Doctrine\DBAL\Sharding\PoolingShardConnection $conn + * @param PoolingShardConnection $conn */ public function __construct(PoolingShardConnection $conn) { diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php index 564c54b69a..edda835876 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php @@ -98,7 +98,7 @@ class SQLAzureFederationsSynchronizer extends AbstractSchemaSynchronizer */ public function getUpdateSchema(Schema $toSchema, $noDrops = false) { - return $this->work($toSchema, function($synchronizer, $schema) use ($noDrops) { + return $this->work($toSchema, function ($synchronizer, $schema) use ($noDrops) { return $synchronizer->getUpdateSchema($schema, $noDrops); }); } @@ -108,7 +108,7 @@ class SQLAzureFederationsSynchronizer extends AbstractSchemaSynchronizer */ public function getDropSchema(Schema $dropSchema) { - return $this->work($dropSchema, function($synchronizer, $schema) { + return $this->work($dropSchema, function ($synchronizer, $schema) { return $synchronizer->getDropSchema($schema); }); } @@ -206,7 +206,7 @@ class SQLAzureFederationsSynchronizer extends AbstractSchemaSynchronizer $table->addOption(self::FEDERATION_DISTRIBUTION_NAME, $this->shardManager->getDistributionKey()); } - if ( $table->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { + if ($table->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { $partitionedSchema->dropTable($table->getName()); } else { foreach ($table->getForeignKeys() as $fk) { @@ -280,6 +280,7 @@ class SQLAzureFederationsSynchronizer extends AbstractSchemaSynchronizer $defaultValue = ''; break; } + return $defaultValue; } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php index c343981d0a..b9047a9563 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php @@ -86,7 +86,7 @@ class SQLAzureShardManager implements ShardManager $this->federationName = $params['sharding']['federationName']; $this->distributionKey = $params['sharding']['distributionKey']; $this->distributionType = $params['sharding']['distributionType']; - $this->filteringEnabled = (isset($params['sharding']['filteringEnabled'])) ? (bool)$params['sharding']['filteringEnabled'] : false; + $this->filteringEnabled = (isset($params['sharding']['filteringEnabled'])) ? (bool) $params['sharding']['filteringEnabled'] : false; } /** @@ -128,7 +128,7 @@ class SQLAzureShardManager implements ShardManager */ public function setFilteringEnabled($flag) { - $this->filteringEnabled = (bool)$flag; + $this->filteringEnabled = (bool) $flag; } /** @@ -191,6 +191,7 @@ class SQLAzureShardManager implements ShardManager FROM sys.federation_member_distributions d INNER JOIN sys.federations f ON f.federation_id = d.federation_id WHERE f.name = " . $this->conn->quote($this->federationName); + return $this->conn->fetchAll($sql); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php index ae327a4f7f..c1a524f76a 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php @@ -125,7 +125,7 @@ class MultiTenantVisitor implements Visitor foreach ($table->getIndexes() as $index) { if ($index->isPrimary() && ! $index->hasFlag('nonclustered')) { return $index; - } else if ($index->hasFlag('clustered')) { + } elseif ($index->hasFlag('clustered')) { return $index; } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php index 7943d6c9d5..25ec652d2d 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php @@ -164,7 +164,15 @@ class Statement implements \IteratorAggregate, DriverStatement try { $stmt = $this->stmt->execute($params); } catch (\Exception $ex) { - throw DBALException::driverExceptionDuringQuery($ex, $this->sql, $this->conn->resolveParams($this->params, $this->types)); + if ($logger) { + $logger->stopQuery(); + } + throw DBALException::driverExceptionDuringQuery( + $this->conn->getDriver(), + $ex, + $this->sql, + $this->conn->resolveParams($this->params, $this->types) + ); } if ($logger) { @@ -223,7 +231,7 @@ class Statement implements \IteratorAggregate, DriverStatement { if ($arg2 === null) { return $this->stmt->setFetchMode($fetchMode); - } else if ($arg3 === null) { + } elseif ($arg3 === null) { return $this->stmt->setFetchMode($fetchMode, $arg2); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php index 18744315ff..4d76ca92b7 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php @@ -63,22 +63,27 @@ EOT { $conn = $this->getHelper('db')->getConnection(); - if (($fileNames = $input->getArgument('file')) !== null) { + if (($fileNames = $input->getArgument('file')) !== null) { foreach ((array) $fileNames as $fileName) { - $fileName = realpath($fileName); + $filePath = realpath($fileName); - if ( ! file_exists($fileName)) { + // Phar compatibility. + if (false === $filePath) { + $filePath = $fileName; + } + + if ( ! file_exists($filePath)) { throw new \InvalidArgumentException( - sprintf("SQL file '%s' does not exist.", $fileName) + sprintf("SQL file '%s' does not exist.", $filePath) ); - } else if ( ! is_readable($fileName)) { + } elseif ( ! is_readable($filePath)) { throw new \InvalidArgumentException( - sprintf("SQL file '%s' does not have read permissions.", $fileName) + sprintf("SQL file '%s' does not have read permissions.", $filePath) ); } - $output->write(sprintf("Processing file '%s'... ", $fileName)); - $sql = file_get_contents($fileName); + $output->write(sprintf("Processing file '%s'... ", $filePath)); + $sql = file_get_contents($filePath); if ($conn instanceof \Doctrine\DBAL\Driver\PDOConnection) { // PDO Drivers diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php index 846acb82ba..f7acd0a86e 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php @@ -19,7 +19,6 @@ namespace Doctrine\DBAL\Tools\Console\Command; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -33,14 +32,21 @@ class ReservedWordsCommand extends Command */ private $keywordListClasses = array( 'mysql' => 'Doctrine\DBAL\Platforms\Keywords\MySQLKeywords', + 'mysql57' => 'Doctrine\DBAL\Platforms\Keywords\MySQL57Keywords', 'sqlserver' => 'Doctrine\DBAL\Platforms\Keywords\SQLServerKeywords', 'sqlserver2005' => 'Doctrine\DBAL\Platforms\Keywords\SQLServer2005Keywords', 'sqlserver2008' => 'Doctrine\DBAL\Platforms\Keywords\SQLServer2008Keywords', 'sqlserver2012' => 'Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords', 'sqlite' => 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords', 'pgsql' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords', + 'pgsql91' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL91Keywords', + 'pgsql92' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQL92Keywords', 'oracle' => 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords', 'db2' => 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords', + 'sqlanywhere' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhereKeywords', + 'sqlanywhere11' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere11Keywords', + 'sqlanywhere12' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere12Keywords', + 'sqlanywhere16' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere16Keywords', ); /** @@ -73,8 +79,8 @@ class ReservedWordsCommand extends Command Checks if the current database contains tables and columns with names that are identifiers in this dialect or in other SQL dialects. -By default SQLite, MySQL, PostgreSQL, Microsoft SQL Server and Oracle -keywords are checked: +By default SQLite, MySQL, PostgreSQL, Microsoft SQL Server, Oracle +and SQL Anywhere keywords are checked: %command.full_name% @@ -86,13 +92,19 @@ pass them to the command: The following keyword lists are currently shipped with Doctrine: * mysql + * mysql57 * pgsql + * pgsql92 * sqlite * oracle * sqlserver * sqlserver2005 * sqlserver2008 * sqlserver2012 + * sqlanywhere + * sqlanywhere11 + * sqlanywhere12 + * sqlanywhere16 * db2 (Not checked by default) EOT ); @@ -106,17 +118,23 @@ EOT /* @var $conn \Doctrine\DBAL\Connection */ $conn = $this->getHelper('db')->getConnection(); - $keywordLists = (array)$input->getOption('list'); + $keywordLists = (array) $input->getOption('list'); if ( ! $keywordLists) { $keywordLists = array( 'mysql', + 'mysql57', 'pgsql', + 'pgsql92', 'sqlite', 'oracle', 'sqlserver', 'sqlserver2005', 'sqlserver2008', - 'sqlserver2012' + 'sqlserver2012', + 'sqlanywhere', + 'sqlanywhere11', + 'sqlanywhere12', + 'sqlanywhere16', ); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php new file mode 100644 index 0000000000..3fb9c050cd --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php @@ -0,0 +1,107 @@ +. + */ + +namespace Doctrine\DBAL\Tools\Console; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Tools\Console\Command\ImportCommand; +use Doctrine\DBAL\Tools\Console\Command\ReservedWordsCommand; +use Doctrine\DBAL\Tools\Console\Command\RunSqlCommand; +use Symfony\Component\Console\Helper\HelperSet; +use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper; +use Symfony\Component\Console\Application; +use Doctrine\DBAL\Version; + +/** + * Handles running the Console Tools inside Symfony Console context. + */ +class ConsoleRunner +{ + /** + * Create a Symfony Console HelperSet + * + * @param Connection $connection + * + * @return HelperSet + */ + static public function createHelperSet(Connection $connection) + { + return new HelperSet(array( + 'db' => new ConnectionHelper($connection) + )); + } + + /** + * Runs console with the given helperset. + * + * @param \Symfony\Component\Console\Helper\HelperSet $helperSet + * @param \Symfony\Component\Console\Command\Command[] $commands + * + * @return void + */ + static public function run(HelperSet $helperSet, $commands = array()) + { + $cli = new Application('Doctrine Command Line Interface', Version::VERSION); + + $cli->setCatchExceptions(true); + $cli->setHelperSet($helperSet); + + self::addCommands($cli); + + $cli->addCommands($commands); + $cli->run(); + } + + /** + * @param Application $cli + * + * @return void + */ + static public function addCommands(Application $cli) + { + $cli->addCommands(array( + new RunSqlCommand(), + new ImportCommand(), + new ReservedWordsCommand(), + )); + } + + /** + * Prints the instructions to create a configuration file + */ + static public function printCliConfigTemplate() + { + echo <<<'HELP' +You are missing a "cli-config.php" or "config/cli-config.php" file in your +project, which is required to get the Doctrine-DBAL Console working. You can use the +following sample as a template: + +. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps ab SQL BINARY/VARBINARY to a PHP resource stream. + * + * @author Steve Müller + * @since 2.5 + */ +class BinaryType extends Type +{ + /** + * {@inheritdoc} + */ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getBinaryTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if (null === $value) { + return null; + } + + if (is_string($value)) { + $fp = fopen('php://temp', 'rb+'); + fwrite($fp, $value); + fseek($fp, 0); + $value = $fp; + } + + if ( ! is_resource($value)) { + throw ConversionException::conversionFailed($value, self::BINARY); + } + + return $value; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Type::BINARY; + } + + /** + * {@inheritdoc} + */ + public function getBindingType() + { + return \PDO::PARAM_LOB; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php index 7ce033fb97..bd89301e21 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php @@ -46,9 +46,12 @@ class BlobType extends Type } if (is_string($value)) { - $value = fopen('data://text/plain;base64,' . base64_encode($value), 'r'); - } - + $fp = fopen('php://temp', 'rb+'); + fwrite($fp, $value); + fseek($fp, 0); + $value = $fp; + } + if ( ! is_resource($value)) { throw ConversionException::conversionFailed($value, self::BLOB); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php index bd6eda10e3..c5715a795c 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php @@ -63,6 +63,11 @@ class DateTimeType extends Type } $val = \DateTime::createFromFormat($platform->getDateTimeFormatString(), $value); + + if ( ! $val) { + $val = date_create($value); + } + if ( ! $val) { throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeFormatString()); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php index 7303ff01ca..2a9c6fa7b7 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php @@ -37,12 +37,12 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; * the offset and re-created from persistence with only the offset, not the original timezone * attached. * - * @link www.doctrine-project.org - * @since 1.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel + * @link www.doctrine-project.org + * @since 1.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel */ class DateTimeTzType extends Type { diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php index ceb7d69111..df251d7175 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php @@ -22,7 +22,7 @@ namespace Doctrine\DBAL\Types; use Doctrine\DBAL\Platforms\AbstractPlatform; /** - * Type that maps an SQL DECIMAL to a PHP double. + * Type that maps an SQL DECIMAL to a PHP string. * * @since 2.0 */ diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php old mode 100755 new mode 100644 index 2c7f767785..79c3259411 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php @@ -34,7 +34,7 @@ class JsonArrayType extends Type */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { - return $platform->getClobTypeDeclarationSQL($fieldDeclaration); + return $platform->getJsonTypeDeclarationSQL($fieldDeclaration); } /** @@ -76,6 +76,6 @@ class JsonArrayType extends Type */ public function requiresSQLCommentHint(AbstractPlatform $platform) { - return true; + return ! $platform->hasNativeJsonType(); } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SimpleArrayType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SimpleArrayType.php old mode 100755 new mode 100644 diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php index 54e740bb4f..554d56dc06 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php @@ -62,7 +62,7 @@ class TimeType extends Type return $value; } - $val = \DateTime::createFromFormat($platform->getTimeFormatString(), $value); + $val = \DateTime::createFromFormat('!' . $platform->getTimeFormatString(), $value); if ( ! $val) { throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getTimeFormatString()); } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php index 73f853fc60..9fa464f58b 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php @@ -48,6 +48,7 @@ abstract class Type const SMALLINT = 'smallint'; const STRING = 'string'; const TEXT = 'text'; + const BINARY = 'binary'; const BLOB = 'blob'; const FLOAT = 'float'; const GUID = 'guid'; @@ -81,6 +82,7 @@ abstract class Type self::TIME => 'Doctrine\DBAL\Types\TimeType', self::DECIMAL => 'Doctrine\DBAL\Types\DecimalType', self::FLOAT => 'Doctrine\DBAL\Types\FloatType', + self::BINARY => 'Doctrine\DBAL\Types\BinaryType', self::BLOB => 'Doctrine\DBAL\Types\BlobType', self::GUID => 'Doctrine\DBAL\Types\GuidType', ); diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php index 52bd56b4bc..5cf35f7958 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php @@ -50,6 +50,7 @@ class VarDateTimeType extends DateTimeType if ( ! $val) { throw ConversionException::conversionFailed($value, $this->getName()); } + return $val; } } diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php index 6ce5992fc7..5260933661 100644 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php @@ -34,7 +34,7 @@ class Version /** * Current Doctrine Version. */ - const VERSION = '2.4.4'; + const VERSION = '2.5.2'; /** * Compares a Doctrine version with the current one. diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/VersionAwarePlatformDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/VersionAwarePlatformDriver.php new file mode 100644 index 0000000000..53e2d3ab78 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/VersionAwarePlatformDriver.php @@ -0,0 +1,47 @@ +. + */ + +namespace Doctrine\DBAL; + +/** + * Contract for a driver that is able to create platform instances by version. + * + * Doctrine uses different platform classes for different vendor versions to + * support the correct features and SQL syntax of each version. + * This interface should be implemented by drivers that are capable to do this + * distinction. + * + * @author Steve Müller + * @link www.doctrine-project.org + * @since 2.5 + */ +interface VersionAwarePlatformDriver +{ + /** + * Factory method for creating the appropriate platform instance for the given version. + * + * @param string $version The platform/server version string to evaluate. This should be given in the notation + * the underlying database vendor uses. + * + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + * + * @throws DBALException if the given version string could not be evaluated. + */ + public function createDatabasePlatformForVersion($version); +} diff --git a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Normalizer/CamelKeysNormalizer.php b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Normalizer/CamelKeysNormalizer.php index 89f9a78684..0128191e3c 100644 --- a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Normalizer/CamelKeysNormalizer.php +++ b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Normalizer/CamelKeysNormalizer.php @@ -69,14 +69,23 @@ class CamelKeysNormalizer implements ArrayNormalizerInterface * * @return string */ - private function normalizeString($string) + protected function normalizeString($string) { if (false === strpos($string, '_')) { return $string; } - return preg_replace_callback('/_([a-zA-Z0-9])/', function ($matches) { + if (preg_match('/^(_+)(.*)/', $string, $matches)) { + $underscorePrefix = $matches[1]; + $string = $matches[2]; + } else { + $underscorePrefix = ''; + } + + $string = preg_replace_callback('/_([a-zA-Z0-9])/', function ($matches) { return strtoupper($matches[1]); }, $string); + + return $underscorePrefix.$string; } } diff --git a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Normalizer/CamelKeysNormalizerWithLeadingUnderscore.php b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Normalizer/CamelKeysNormalizerWithLeadingUnderscore.php new file mode 100644 index 0000000000..3ca2f675b2 --- /dev/null +++ b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Normalizer/CamelKeysNormalizerWithLeadingUnderscore.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FOS\RestBundle\Normalizer; + +/** + * Normalizes the array by changing its keys from underscore to camel case, while + * leaving leading underscores unchanged. + * + * @author Lukas Kahwe Smith + */ +class CamelKeysNormalizerWithLeadingUnderscore extends CamelKeysNormalizer +{ + /** + * Normalizes a string while leaving leading underscores unchanged. + * + * @param string $string + * + * @return string + */ + protected function normalizeString($string) + { + if (false === strpos($string, '_')) { + return $string; + } + + $offset = strspn($string, '_'); + if ($offset) { + $underscorePrefix = substr($string, 0, $offset); + $string = substr($string, $offset); + } else { + $underscorePrefix = ''; + } + + return $underscorePrefix.parent::normalizeString($string); + } +} diff --git a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/config/body_listener.xml b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/config/body_listener.xml index 6b870a59e6..c86cb99d94 100644 --- a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/config/body_listener.xml +++ b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/config/body_listener.xml @@ -19,6 +19,8 @@ + + diff --git a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/doc/body_listener.rst b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/doc/body_listener.rst index 3ff5893a75..bafb0ef5a6 100644 --- a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/doc/body_listener.rst +++ b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/doc/body_listener.rst @@ -56,6 +56,11 @@ to camel cased ones, you can use the ``camel_keys`` array normalizer: body_listener: array_normalizer: fos_rest.normalizer.camel_keys +.. note:: + + If you want to ignore leading underscores, for example in ``_username`` you can + instead use the ``fos_rest.normalizer.camel_keys_with_leading_underscore`` service. + Sometimes an array contains a key, which once normalized, will override an existing array key. For example ``foo_bar`` and ``foo_Bar`` will both lead to ``fooBar``. If the normalizer receives this data, the listener will throw a diff --git a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/doc/param_fetcher_listener.rst b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/doc/param_fetcher_listener.rst index 5808871d02..d587098e0e 100644 --- a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/doc/param_fetcher_listener.rst +++ b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Resources/doc/param_fetcher_listener.rst @@ -40,7 +40,7 @@ configured for the matched controller so that the user does not need to do this * * Will check if a blank value, e.g an empty string is passed and if so, it will set to the default of asc. * - * @QueryParam(name="sort", requirements="(asc|desc)+", allowBlank=false, default="asc", description="Sort direction") + * @QueryParam(name="sort", requirements="(asc|desc)", allowBlank=false, default="asc", description="Sort direction") * * Will look for a firstname request parameters, ie. firstname=foo in POST data. * If not passed it will error out when read out of the ParamFetcher since RequestParam defaults to strict=true diff --git a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Tests/Normalizer/CamelKeysNormalizerTest.php b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Tests/Normalizer/CamelKeysNormalizerTest.php index 2f90e8f919..0cdc5ceadb 100644 --- a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Tests/Normalizer/CamelKeysNormalizerTest.php +++ b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/Tests/Normalizer/CamelKeysNormalizerTest.php @@ -12,6 +12,7 @@ namespace FOS\RestBundle\Tests\Normalizer; use FOS\RestBundle\Normalizer\CamelKeysNormalizer; +use FOS\RestBundle\Normalizer\CamelKeysNormalizerWithLeadingUnderscore; class CamelKeysNormalizerTest extends \PHPUnit_Framework_TestCase { @@ -52,4 +53,21 @@ class CamelKeysNormalizerTest extends \PHPUnit_Framework_TestCase ), ); } + + /** + * @dataProvider normalizeProvider + */ + public function testNormalizeLeadingUnderscore(array $array, array $expected) + { + $normalizer = new CamelKeysNormalizerWithLeadingUnderscore(); + $this->assertEquals($expected, $normalizer->normalize($array)); + } + + public function normalizeProviderLeadingUnderscore() + { + $array = $this->normalizeProvider(); + $array[] = array(array('__username' => 'foo', '_password' => 'bar', '_foo_bar' => 'foobar'), array('__username' => 'foo', '_password' => 'bar', '_fooBar' => 'foobar')); + + return $array; + } } diff --git a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/composer.json b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/composer.json index b567e284c8..46fd78401e 100644 --- a/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/composer.json +++ b/vendor/friendsofsymfony/rest-bundle/FOS/RestBundle/composer.json @@ -1,7 +1,7 @@ { "name": "friendsofsymfony/rest-bundle", "type": "symfony-bundle", - "description": "This Bundle provides various tools to rapidly develop RESTful API's with Symfony2", + "description": "This Bundle provides various tools to rapidly develop RESTful API's with Symfony", "keywords": ["rest"], "homepage": "http://friendsofsymfony.github.com", "license": "MIT",