diff --git a/.gitignore b/.gitignore index 30a257d..066b6d0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ /cache /vendor jssearch.index.js -errors.txt \ No newline at end of file +errors.txt +/tests/arraysubset.php +/tests/unit/FixErrorTests.php +/tests/unit/DynamicActiveRecordTestPgJson11.php \ No newline at end of file diff --git a/DynamicActiveQuery.php b/DynamicActiveQuery.php index 11ac0d0..8d82a6b 100644 --- a/DynamicActiveQuery.php +++ b/DynamicActiveQuery.php @@ -4,7 +4,6 @@ * @copyright Copyright (c) 2015 Spinitron LLC * @license http://opensource.org/licenses/ISC */ - namespace spinitron\dynamicAr; use Yii; @@ -46,6 +45,7 @@ */ class DynamicActiveQuery extends ActiveQuery { + /** * @var string name of the DynamicActiveRecord's column storing serialized dynamic attributes */ @@ -103,7 +103,7 @@ public function prepare($builder) if (empty($this->_dynamicColumn)) { /** @var string $modelClass */ throw new \yii\base\InvalidConfigException( - $modelClass . '::dynamicColumn() must return an attribute name' + $modelClass . '::dynamicColumn() must return an attribute name' ); } @@ -211,8 +211,8 @@ public function createCommand($db = null) $type = !empty($matches[3]) ? $matches[3] : 'CHAR'; return $encoder->dynamicAttributeExpression($matches[2], $type); }; - - $pattern = <<<'REGEXP' + $driver = $db->getDriverName(); + $patternmaria = <<<'REGEXP' % (`?) \(! \s*? ( [a-z_\x7f-\xff][a-z0-9_\x7f-\xff]* (?: \. [^.|\s]+)* ) (?: \| (binary (?:\(\d+\))? | char (?:\(\d+\))? | time (?:\(\d+\))? | datetime (?:\(\d+\))? | date @@ -220,8 +220,22 @@ public function createCommand($db = null) | int(eger)? | (?:un)? signed (?:\s+int(eger)?)?) )? \s*? !\) \1 %ix REGEXP; + $patternpostgres = <<<'REGEXP' + % (`?) \(! \s*? + ( [a-z_\x7f-\xff][a-z0-9_\x7f-\xff]* (?: \. [^.|\s]+)* ) + (?: \| (char (?:\(\d+\))? | numeric | jsonb | text | boolean + | NUMERIC | JSONB | TEXT | BOOLEAN ?) )? + \s*? !\) \1 %ix +REGEXP; + if ($driver == 'mysql' || $driver == 'mysqli') { + $pattern = $patternmaria; + } else if ($driver == 'pgsql') { + $pattern = $patternpostgres; + } else { + throw new \yii\base\NotSupportedException("DynamicActiveRecord does not support '$driver' DBMS."); + } $sql = preg_replace_callback($pattern, $callback, $sql); - + // print_r($sql); return $db->createCommand($sql, $params); } diff --git a/DynamicActiveRecord.php b/DynamicActiveRecord.php index a35c14f..478596e 100644 --- a/DynamicActiveRecord.php +++ b/DynamicActiveRecord.php @@ -154,9 +154,9 @@ public function getAttribute($name) return null; } $ref = &$ref[$key]; - } - - return $ref; + } + + return $ref; } /** diff --git a/composer.lock b/composer.lock index b05597c..99d2b71 100644 --- a/composer.lock +++ b/composer.lock @@ -1,27 +1,27 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "92323596367c876525cb0933bc88c274", + "content-hash": "c47f9caac4490ddcf6f218cd941a5a55", "packages": [ { "name": "bower-asset/bootstrap", - "version": "v3.3.5", + "version": "v3.3.7", "source": { "type": "git", "url": "https://github.com/twbs/bootstrap.git", - "reference": "16b48259a62f576e52c903c476bd42b90ab22482" + "reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twbs/bootstrap/zipball/16b48259a62f576e52c903c476bd42b90ab22482", - "reference": "16b48259a62f576e52c903c476bd42b90ab22482", + "url": "https://api.github.com/repos/twbs/bootstrap/zipball/0b9c4a4007c44201dce9a6cc1a38407005c26c86", + "reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86", "shasum": "" }, "require": { - "bower-asset/jquery": ">=1.9.1" + "bower-asset/jquery": ">=1.9.1,<4.0" }, "type": "bower-asset-library", "extra": { @@ -57,36 +57,22 @@ }, { "name": "bower-asset/jquery", - "version": "2.1.4", + "version": "2.2.4", "source": { "type": "git", - "url": "https://github.com/jquery/jquery.git", - "reference": "7751e69b615c6eca6f783a81e292a55725af6b85" + "url": "https://github.com/jquery/jquery-dist.git", + "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jquery/jquery/zipball/7751e69b615c6eca6f783a81e292a55725af6b85", - "reference": "7751e69b615c6eca6f783a81e292a55725af6b85", + "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/c0185ab7c75aab88762c5aae780b9d83b80eda72", + "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72", "shasum": "" }, - "require-dev": { - "bower-asset/qunit": "1.14.0", - "bower-asset/requirejs": "2.1.10", - "bower-asset/sinon": "1.8.1", - "bower-asset/sizzle": "2.1.1-patch2" - }, "type": "bower-asset-library", "extra": { "bower-asset-main": "dist/jquery.js", "bower-asset-ignore": [ - "**/.*", - "build", - "dist/cdn", - "speed", - "test", - "*.md", - "AUTHORS.txt", - "Gruntfile.js", "package.json" ] }, @@ -94,6 +80,7 @@ "MIT" ], "keywords": [ + "browser", "javascript", "jquery", "library" @@ -101,16 +88,16 @@ }, { "name": "bower-asset/jquery.inputmask", - "version": "3.1.63", + "version": "3.3.4", "source": { "type": "git", - "url": "https://github.com/RobinHerbots/jquery.inputmask.git", - "reference": "c40c7287eadc31e341ebbf0c02352eb55b9cbc48" + "url": "https://github.com/RobinHerbots/Inputmask.git", + "reference": "8a882bc471ba4077c4f8ecbe3d9d61c7558f3ef2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/RobinHerbots/jquery.inputmask/zipball/c40c7287eadc31e341ebbf0c02352eb55b9cbc48", - "reference": "c40c7287eadc31e341ebbf0c02352eb55b9cbc48", + "url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/8a882bc471ba4077c4f8ecbe3d9d61c7558f3ef2", + "reference": "8a882bc471ba4077c4f8ecbe3d9d61c7558f3ef2", "shasum": "" }, "require": { @@ -119,23 +106,24 @@ "type": "bower-asset-library", "extra": { "bower-asset-main": [ - "./dist/inputmask/jquery.inputmask.js", - "./dist/inputmask/jquery.inputmask.extensions.js", - "./dist/inputmask/jquery.inputmask.date.extensions.js", - "./dist/inputmask/jquery.inputmask.numeric.extensions.js", - "./dist/inputmask/jquery.inputmask.phone.extensions.js", - "./dist/inputmask/jquery.inputmask.regex.extensions.js" + "./dist/inputmask/inputmask.dependencyLib", + "./dist/inputmask/inputmask", + "./dist/inputmask/inputmask.extensions", + "./dist/inputmask/inputmask.date.extensions", + "./dist/inputmask/inputmask.numeric.extensions", + "./dist/inputmask/inputmask.phone.extensions", + "./dist/inputmask/inputmask.regex.extensions", + "./dist/inputmask/jquery.inputmask" ], "bower-asset-ignore": [ - "**/.*", - "qunit/", - "nuget/", - "tools/", - "js/", - "*.md", - "build.properties", - "build.xml", - "jquery.inputmask.jquery.json" + "**/*", + "!dist/*", + "!dist/inputmask/*", + "!dist/min/*", + "!dist/min/inputmask/*", + "!extra/bindings/*", + "!extra/dependencyLibs/*", + "!extra/phone-codes/*" ] }, "license": [ @@ -181,16 +169,16 @@ }, { "name": "bower-asset/yii2-pjax", - "version": "v2.0.4", + "version": "v2.0.6", "source": { "type": "git", "url": "https://github.com/yiisoft/jquery-pjax.git", - "reference": "3f20897307cca046fca5323b318475ae9dac0ca0" + "reference": "60728da6ade5879e807a49ce59ef9a72039b8978" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/3f20897307cca046fca5323b318475ae9dac0ca0", - "reference": "3f20897307cca046fca5323b318475ae9dac0ca0", + "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/60728da6ade5879e807a49ce59ef9a72039b8978", + "reference": "60728da6ade5879e807a49ce59ef9a72039b8978", "shasum": "" }, "require": { @@ -203,6 +191,7 @@ ".travis.yml", "Gemfile", "Gemfile.lock", + "CONTRIBUTING.md", "vendor/", "script/", "test/" @@ -214,16 +203,16 @@ }, { "name": "cebe/js-search", - "version": "0.9.2", + "version": "0.9.3", "source": { "type": "git", "url": "https://github.com/cebe/js-search.git", - "reference": "db807790032146beb2e5624fc38799d126720200" + "reference": "3756a8b3387f3f7e5c778b964ec681dcf110b098" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cebe/js-search/zipball/db807790032146beb2e5624fc38799d126720200", - "reference": "db807790032146beb2e5624fc38799d126720200", + "url": "https://api.github.com/repos/cebe/js-search/zipball/3756a8b3387f3f7e5c778b964ec681dcf110b098", + "reference": "3756a8b3387f3f7e5c778b964ec681dcf110b098", "shasum": "" }, "require": { @@ -249,7 +238,7 @@ } ], "description": "A client side search engine for use on static pages.", - "time": "2015-05-06 22:41:18" + "time": "2016-11-22T12:11:39+00:00" }, { "name": "cebe/markdown", @@ -309,20 +298,20 @@ "markdown", "markdown-extra" ], - "time": "2015-03-06 05:21:16" + "time": "2015-03-06T05:21:16+00:00" }, { "name": "cebe/markdown-latex", - "version": "1.0.0", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/cebe/markdown-latex.git", - "reference": "9ba3e0d629aa3a3e61cc159a999209ab54e3ef43" + "reference": "1707d27f3e980e5fbd65fed6e750d4c6bed7b060" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cebe/markdown-latex/zipball/9ba3e0d629aa3a3e61cc159a999209ab54e3ef43", - "reference": "9ba3e0d629aa3a3e61cc159a999209ab54e3ef43", + "url": "https://api.github.com/repos/cebe/markdown-latex/zipball/1707d27f3e980e5fbd65fed6e750d4c6bed7b060", + "reference": "1707d27f3e980e5fbd65fed6e750d4c6bed7b060", "shasum": "" }, "require": { @@ -369,25 +358,28 @@ "markdown", "markdown-extra" ], - "time": "2014-10-20 23:24:21" + "time": "2016-08-23T08:32:49+00:00" }, { "name": "ezyang/htmlpurifier", - "version": "v4.6.0", + "version": "v4.9.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "6f389f0f25b90d0b495308efcfa073981177f0fd" + "reference": "a1c09b09e398687deeb8e309a6305def4b43439b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/6f389f0f25b90d0b495308efcfa073981177f0fd", - "reference": "6f389f0f25b90d0b495308efcfa073981177f0fd", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/a1c09b09e398687deeb8e309a6305def4b43439b", + "reference": "a1c09b09e398687deeb8e309a6305def4b43439b", "shasum": "" }, "require": { "php": ">=5.2" }, + "require-dev": { + "simpletest/simpletest": "^1.1" + }, "type": "library", "autoload": { "psr-0": { @@ -413,20 +405,20 @@ "keywords": [ "html" ], - "time": "2013-11-30 08:25:19" + "time": "2017-01-13T12:31:37+00:00" }, { "name": "mikevanriel/text-to-latex", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/mvriel/TextToLatex.git", - "reference": "e654076192d73b829ac549041ac58ab08b7a2436" + "reference": "c9f3a4d6b89f9449782455c848d5fa3dd0e216ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mvriel/TextToLatex/zipball/e654076192d73b829ac549041ac58ab08b7a2436", - "reference": "e654076192d73b829ac549041ac58ab08b7a2436", + "url": "https://api.github.com/repos/mvriel/TextToLatex/zipball/c9f3a4d6b89f9449782455c848d5fa3dd0e216ba", + "reference": "c9f3a4d6b89f9449782455c848d5fa3dd0e216ba", "shasum": "" }, "require-dev": { @@ -452,36 +444,36 @@ } ], "description": "A converter class that converts normal ASCII text to valid LaTeX", - "time": "2013-12-20 21:34:24" + "time": "2015-12-13T07:33:35+00:00" }, { "name": "nikic/php-parser", - "version": "v0.9.5", + "version": "v1.4.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb" + "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ef70767475434bdb3615b43c327e2cae17ef12eb", - "reference": "ef70767475434bdb3615b43c327e2cae17ef12eb", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", + "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.2" + "php": ">=5.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.9-dev" + "dev-master": "1.4-dev" } }, "autoload": { - "psr-0": { - "PHPParser": "lib/" - } + "files": [ + "lib/bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -497,24 +489,24 @@ "parser", "php" ], - "time": "2014-07-23 18:24:17" + "time": "2015-09-19T14:15:08+00:00" }, { "name": "phpdocumentor/reflection", - "version": "1.0.7", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/Reflection.git", - "reference": "fc40c3f604ac2287eb5c314174d5109b2c699372" + "reference": "793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/fc40c3f604ac2287eb5c314174d5109b2c699372", - "reference": "fc40c3f604ac2287eb5c314174d5109b2c699372", + "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d", + "reference": "793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d", "shasum": "" }, "require": { - "nikic/php-parser": "~0.9.4", + "nikic/php-parser": "^1.0", "php": ">=5.3.3", "phpdocumentor/reflection-docblock": "~2.0", "psr/log": "~1.0" @@ -551,7 +543,7 @@ "reflection", "static analysis" ], - "time": "2014-11-14 11:43:04" + "time": "2016-05-21T08:42:32+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -600,26 +592,34 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2015-02-03 12:10:50" + "time": "2015-02-03T12:10:50+00:00" }, { "name": "psr/log", - "version": "1.0.0", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, + "require": { + "php": ">=5.3.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { - "psr-0": { - "Psr\\Log\\": "" + "psr-4": { + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -633,36 +633,73 @@ } ], "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ "log", "psr", "psr-3" ], - "time": "2012-12-21 11:40:51" + "time": "2016-10-10T12:19:37+00:00" + }, + { + "name": "scrivo/highlight.php", + "version": "v8.9.1", + "source": { + "type": "git", + "url": "https://github.com/scrivo/highlight.php.git", + "reference": "d861aee53999963aed4b742cfe21181bec178f35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/d861aee53999963aed4b742cfe21181bec178f35", + "reference": "d861aee53999963aed4b742cfe21181bec178f35", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Highlight\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Server side syntax highlighter that supports over 90 languages. It's a PHP port of highlight.js", + "keywords": [ + "code", + "highlight", + "highlight.js", + "highlight.php", + "syntax" + ], + "time": "2015-12-31T20:33:22+00:00" }, { "name": "yiisoft/yii2-apidoc", - "version": "2.0.4", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/yiisoft/yii2-apidoc.git", - "reference": "b8682e7ff092939f876fa1bcaf7505fea7c5b3cf" + "reference": "dd0918ccbce2c1bdea836667f54e8f8b99d27128" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yiisoft/yii2-apidoc/zipball/b8682e7ff092939f876fa1bcaf7505fea7c5b3cf", - "reference": "b8682e7ff092939f876fa1bcaf7505fea7c5b3cf", + "url": "https://api.github.com/repos/yiisoft/yii2-apidoc/zipball/dd0918ccbce2c1bdea836667f54e8f8b99d27128", + "reference": "dd0918ccbce2c1bdea836667f54e8f8b99d27128", "shasum": "" }, "require": { - "cebe/js-search": "*", + "cebe/js-search": "~0.9.3", "cebe/markdown": "~1.0.0 | ~1.1.0", - "cebe/markdown-latex": "~1.0.0", - "nikic/php-parser": "0.9.*", - "phpdocumentor/reflection": ">=1.0.3", - "phpdocumentor/reflection-docblock": ">2.0.1", - "yiisoft/yii2": ">=2.0.4", - "yiisoft/yii2-bootstrap": "*" + "cebe/markdown-latex": "~1.0", + "nikic/php-parser": "^1.0", + "php": ">=5.4", + "phpdocumentor/reflection": "^3.0.1", + "phpdocumentor/reflection-docblock": "^2.0.4", + "scrivo/highlight.php": "~8.0", + "yiisoft/yii2": "~2.0.4", + "yiisoft/yii2-bootstrap": "~2.0.0" }, "bin": [ "apidoc" @@ -700,25 +737,25 @@ "phpdoc", "yii2" ], - "time": "2015-05-10 22:07:34" + "time": "2016-11-22T15:29:55+00:00" }, { "name": "yiisoft/yii2-bootstrap", - "version": "2.0.4", + "version": "2.0.6", "source": { "type": "git", "url": "https://github.com/yiisoft/yii2-bootstrap.git", - "reference": "1b6b1e61cf91c3cdd517d6a7e71d30bb212e4af0" + "reference": "3fd2b8c950cce79d60e9702d6bcb24eb3c80f6c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yiisoft/yii2-bootstrap/zipball/1b6b1e61cf91c3cdd517d6a7e71d30bb212e4af0", - "reference": "1b6b1e61cf91c3cdd517d6a7e71d30bb212e4af0", + "url": "https://api.github.com/repos/yiisoft/yii2-bootstrap/zipball/3fd2b8c950cce79d60e9702d6bcb24eb3c80f6c5", + "reference": "3fd2b8c950cce79d60e9702d6bcb24eb3c80f6c5", "shasum": "" }, "require": { "bower-asset/bootstrap": "3.3.* | 3.2.* | 3.1.*", - "yiisoft/yii2": ">=2.0.4" + "yiisoft/yii2": ">=2.0.6" }, "type": "yii2-extension", "extra": { @@ -750,24 +787,27 @@ "bootstrap", "yii2" ], - "time": "2015-05-10 22:08:17" + "time": "2016-03-17T03:29:28+00:00" }, { "name": "yiisoft/yii2-composer", - "version": "2.0.3", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/yiisoft/yii2-composer.git", - "reference": "ca8d23707ae47d20b0454e4b135c156f6da6d7be" + "reference": "3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/ca8d23707ae47d20b0454e4b135c156f6da6d7be", - "reference": "ca8d23707ae47d20b0454e4b135c156f6da6d7be", + "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2", + "reference": "3f4923c2bde6caf3f5b88cc22fdd5770f52f8df2", "shasum": "" }, "require": { - "composer-plugin-api": "1.0.0" + "composer-plugin-api": "^1.0" + }, + "require-dev": { + "composer/composer": "^1.0" }, "type": "composer-plugin", "extra": { @@ -797,39 +837,40 @@ "extension installer", "yii2" ], - "time": "2015-03-01 06:22:44" + "time": "2016-12-20T13:26:02+00:00" }, { "name": "yiisoft/yii2-dev", - "version": "2.0.6", + "version": "2.0.11.2", "source": { "type": "git", "url": "https://github.com/yiisoft/yii2.git", - "reference": "89eb3dff144cffeb1b72107a235afc345ac2320e" + "reference": "278548029a071648c440670ebb16dca1b32421e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yiisoft/yii2/zipball/89eb3dff144cffeb1b72107a235afc345ac2320e", - "reference": "89eb3dff144cffeb1b72107a235afc345ac2320e", + "url": "https://api.github.com/repos/yiisoft/yii2/zipball/278548029a071648c440670ebb16dca1b32421e3", + "reference": "278548029a071648c440670ebb16dca1b32421e3", "shasum": "" }, "require": { - "bower-asset/jquery": "2.1.*@stable | 1.11.*@stable", - "bower-asset/jquery.inputmask": "3.1.*", + "bower-asset/jquery": "2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", + "bower-asset/jquery.inputmask": "~3.2.2 | ~3.3.3", "bower-asset/punycode": "1.3.*", - "bower-asset/yii2-pjax": ">=2.0.1", + "bower-asset/yii2-pjax": "~2.0.1", "cebe/markdown": "~1.0.0 | ~1.1.0", + "ext-ctype": "*", "ext-mbstring": "*", - "ezyang/htmlpurifier": "4.6.*", + "ezyang/htmlpurifier": "~4.6", "lib-pcre": "*", "php": ">=5.4.0", - "yiisoft/yii2-composer": "*" + "yiisoft/yii2-composer": "~2.0.4" }, "replace": { "yiisoft/yii2": "self.version" }, "require-dev": { - "cebe/indent": "*", + "cebe/indent": "~1.0.2", "phpunit/phpunit": "~4.4" }, "suggest": { @@ -846,7 +887,11 @@ "asset-installer-paths": { "npm-asset-library": "vendor/npm", "bower-asset-library": "vendor/bower" - } + }, + "asset-vcs-driver-options": { + "github-no-api": true + }, + "asset-pattern-skip-version": "(-build|-patch)" }, "autoload": { "psr-4": { @@ -891,6 +936,17 @@ "name": "Paul Klimov", "email": "klimov.paul@gmail.com", "role": "Core framework development" + }, + { + "name": "Dmitry Naumenko", + "email": "d.naumenko.a@gmail.com", + "role": "Core framework development" + }, + { + "name": "Boudewijn Vahrmeijer", + "email": "info@dynasource.eu", + "homepage": "http://dynasource.eu", + "role": "Core framework development" } ], "description": "Yii PHP Framework Version 2 - Development Package", @@ -899,7 +955,7 @@ "framework", "yii2" ], - "time": "2015-08-05 22:00:30" + "time": "2017-02-08T09:04:32+00:00" } ], "packages-dev": [ @@ -955,34 +1011,37 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.5.0", + "version": "v1.6.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", - "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "phpdocumentor/reflection-docblock": "~2.0", - "sebastian/comparator": "~1.1" + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0|^2.0" }, "require-dev": { - "phpspec/phpspec": "~2.0" + "phpspec/phpspec": "^2.0", + "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -1015,20 +1074,20 @@ "spy", "stub" ], - "time": "2015-08-13 10:07:40" + "time": "2016-11-21T14:58:47+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "2.2.2", + "version": "2.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c" + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2d7c03c0e4e080901b8f33b2897b0577be18a13c", - "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", "shasum": "" }, "require": { @@ -1077,20 +1136,20 @@ "testing", "xunit" ], - "time": "2015-08-04 03:42:39" + "time": "2015-10-06T15:47:00+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", "shasum": "" }, "require": { @@ -1124,7 +1183,7 @@ "filesystem", "iterator" ], - "time": "2015-06-21 13:08:43" + "time": "2016-10-03T07:40:28+00:00" }, { "name": "phpunit/php-text-template", @@ -1165,25 +1224,28 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", - "version": "1.0.7", + "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, "type": "library", "autoload": { "classmap": [ @@ -1206,20 +1268,20 @@ "keywords": [ "timer" ], - "time": "2015-06-21 08:01:12" + "time": "2016-05-12T18:03:57+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.6", + "version": "1.4.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b" + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3ab72c62e550370a6cd5dc873e1a04ab57562f5b", - "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", "shasum": "" }, "require": { @@ -1255,20 +1317,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-08-16 08:51:00" + "time": "2016-11-15T14:06:22+00:00" }, { "name": "phpunit/phpunit", - "version": "4.8.6", + "version": "4.8.35", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2246830f4a1a551c67933e4171bf2126dc29d357" + "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2246830f4a1a551c67933e4171bf2126dc29d357", - "reference": "2246830f4a1a551c67933e4171bf2126dc29d357", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87", + "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87", "shasum": "" }, "require": { @@ -1282,9 +1344,9 @@ "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": ">=1.0.6", + "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.1", + "sebastian/comparator": "~1.2.2", "sebastian/diff": "~1.2", "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", @@ -1327,20 +1389,20 @@ "testing", "xunit" ], - "time": "2015-08-24 04:09:38" + "time": "2017-02-06T05:18:07+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.7", + "version": "2.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "5e2645ad49d196e020b85598d7c97e482725786a" + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5e2645ad49d196e020b85598d7c97e482725786a", - "reference": "5e2645ad49d196e020b85598d7c97e482725786a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", "shasum": "" }, "require": { @@ -1383,26 +1445,26 @@ "mock", "xunit" ], - "time": "2015-08-19 09:14:08" + "time": "2015-10-02T06:51:40+00:00" }, { "name": "sebastian/comparator", - "version": "1.2.0", + "version": "1.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { "phpunit/phpunit": "~4.4" @@ -1447,32 +1509,32 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", - "version": "1.3.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "~4.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -1495,31 +1557,31 @@ } ], "description": "Diff implementation", - "homepage": "http://www.github.com/sebastianbergmann/diff", + "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ "diff" ], - "time": "2015-02-22 15:13:53" + "time": "2015-12-08T07:14:41+00:00" }, { "name": "sebastian/environment", - "version": "1.3.2", + "version": "1.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44" + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44", - "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^4.8 || ^5.0" }, "type": "library", "extra": { @@ -1549,20 +1611,20 @@ "environment", "hhvm" ], - "time": "2015-08-03 06:14:51" + "time": "2016-08-18T05:49:44+00:00" }, { "name": "sebastian/exporter", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", "shasum": "" }, "require": { @@ -1570,12 +1632,13 @@ "sebastian/recursion-context": "~1.0" }, "require-dev": { + "ext-mbstring": "*", "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -1615,20 +1678,20 @@ "export", "exporter" ], - "time": "2015-06-21 07:55:53" + "time": "2016-06-17T09:04:28+00:00" }, { "name": "sebastian/global-state", - "version": "1.0.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", - "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", "shasum": "" }, "require": { @@ -1666,20 +1729,20 @@ "keywords": [ "global state" ], - "time": "2014-10-06 09:23:50" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/recursion-context", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" + "reference": "913401df809e99e4f47b27cdd781f4a258d58791" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", - "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791", "shasum": "" }, "require": { @@ -1719,7 +1782,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-06-21 08:04:50" + "time": "2015-11-11T19:50:13+00:00" }, { "name": "sebastian/version", @@ -1754,38 +1817,44 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2015-06-21T13:59:46+00:00" }, { "name": "symfony/yaml", - "version": "v2.7.3", + "version": "v3.2.4", "source": { "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "71340e996171474a53f3d29111d046be4ad8a0ff" + "url": "https://github.com/symfony/yaml.git", + "reference": "9724c684646fcb5387d579b4bfaa63ee0b0c64c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/71340e996171474a53f3d29111d046be4ad8a0ff", - "reference": "71340e996171474a53f3d29111d046be4ad8a0ff", + "url": "https://api.github.com/repos/symfony/yaml/zipball/9724c684646fcb5387d579b4bfaa63ee0b0c64c8", + "reference": "9724c684646fcb5387d579b4bfaa63ee0b0c64c8", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5.9" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "3.2-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Yaml\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1803,7 +1872,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-07-28 14:07:07" + "time": "2017-02-16T22:46:52+00:00" } ], "aliases": [], diff --git a/encoder/EncoderInterface.php b/encoder/EncoderInterface.php index 85eaee6..6a7a86f 100644 --- a/encoder/EncoderInterface.php +++ b/encoder/EncoderInterface.php @@ -19,7 +19,7 @@ interface EncoderInterface * * @return string a SQL expression */ - public function dynamicAttributeExpression($name, $type = 'char'); + public function dynamicAttributeExpression($name, $type); /** * Generates an SQL expression to select value of the dynamic column. diff --git a/encoder/PgsqlEncoder.php b/encoder/PgsqlEncoder.php index a201bd3..84273e3 100644 --- a/encoder/PgsqlEncoder.php +++ b/encoder/PgsqlEncoder.php @@ -4,13 +4,13 @@ * @copyright Copyright (c) 2015 Spinitron LLC * @license http://opensource.org/licenses/ISC */ - namespace spinitron\dynamicAr\encoder; use spinitron\dynamicAr\ValueExpression; class PgsqlEncoder extends BaseEncoder { + /** * Generate an SQL expression referring to the given dynamic column. * @@ -22,12 +22,24 @@ class PgsqlEncoder extends BaseEncoder public function dynamicAttributeExpression($name, $type = 'char') { $modelClass = $this->modelClass; - $sql = '[[' . $modelClass::dynamicColumn() . ']]'; - foreach (explode('.', $name) as $column) { - $sql = "($sql->'$column' AS $type)"; - } + $sqlarray = explode('|', $name); - return $sql; + if (isset($sqlarray[1])) { + $type = $sqlarray[1]; + } + // $sql = '[[' . $modelClass::dynamicColumn() . ']]'; + $sql = str_replace(".", "','", $sqlarray[0]); + if ($type == 'char' || $type == 'CHAR' || $type == 'TEXT' || $type == 'text') { + return 'jsonb_extract_path_text(' . $modelClass::dynamicColumn() . ',\'' . $sql . '\')'; + } else if ($type == 'numeric' || $type == 'NUMERIC') { + return 'jsonb_extract_path_text(' . $modelClass::dynamicColumn() . ',\'' . $sql . '\')::numeric'; + } else if ($type == 'jsonb' || $type == 'JSONB') { + return 'jsonb_extract_path(' . $modelClass::dynamicColumn() . ',\'' . $sql . '\')::jsonb'; + } else if ($type == 'boolean' || $type == 'BOOLEAN') { + return 'jsonb_extract_path_text(' . $modelClass::dynamicColumn() . ',\'' . $sql . '\')::boolean'; + } else { + throw new \yii\base\NotSupportedException("'$type' is not supported.Supported types for postgresql jsonb: char,text,numeric,jsonb,boolean"); + } } /** @@ -44,11 +56,12 @@ public function dynamicColumnExpression() /** * Creates a dynamic column SQL expression representing the given attributes. * - * @param array $attributes the dynamic attributes, which may be nested + * @param array $attributes the dynamic attributes, which may be json encoded * * @return null|\yii\db\Expression */ - public function encodeDynamicColumn($attributes) { + public function encodeDynamicColumn($attributes) + { if (!$attributes) { return null; } @@ -57,9 +70,9 @@ public function encodeDynamicColumn($attributes) { // todo For now we only have Maria. Add PgSQL and generic JSON. static::encodeDynamicAttributeArray($attributes); - $sql = static::dynColSqlMaria($attributes, $params); - - return new \yii\db\Expression($sql, $params); + $sql = json_encode($attributes); //simply encode attributes + $sql = '\'' . $sql . '\''; //simply add ' ' before and after so pg accepts the value + return new \yii\db\Expression('(select CAST (' . $sql . ' AS JSONB))', $params); } /** @@ -74,15 +87,14 @@ public function encodeDynamicColumn($attributes) { */ public function decodeDynamicColumn($encoded) { - // Maria has a bug in its COLUMN_JSON funcion in which it fails to escape the - // control characters U+0000 through U+001F. This causes JSON decoders to fail. + // Postgress does not accept \u0000 on a unicode charser db and + // \u0000 - \u0007 on non unicode charset db's + // This causes JSON decoders to fail. // This workaround escapes those characters. $encoded = preg_replace_callback( - '/[\x00-\x1f]/', - function ($matches) { - return sprintf('\u00%02x', ord($matches[0])); - }, - $encoded + '/[\x00-\x07]/', function ($matches) { + return sprintf('\u00%02x', ord($matches[0])); + }, $encoded ); $decoded = json_decode($encoded, true); @@ -92,10 +104,9 @@ function ($matches) { return $decoded; } - /** * Creates the SQL and parameter bindings for setting dynamic attributes - * in a DB record as Dynamic Columns in Maria. + * in a DB record as Dynamic Columns in Postgres. * * @param array $attrs the dynamic attributes, which may be nested * @param array $params expression parameters for binding, passed by reference @@ -103,32 +114,35 @@ function ($matches) { * @return string SQL for a DB Expression * @throws \yii\base\Exception */ - private static function dynColSqlMaria(array $attrs, & $params) - { - $sql = []; - foreach ($attrs as $key => $value) { - if (is_object($value) && !($value instanceof ValueExpression)) { - $value = method_exists($value, 'toArray') ? $value->toArray() : (array) $value; - } - if ($value === [] || $value === null) { - continue; - } - - $phKey = static::placeholder(); - $phValue = static::placeholder(); - $sql[] = $phKey; - $params[$phKey] = $key; - - if ($value instanceof ValueExpression || is_float($value)) { - $sql[] = $value; - } elseif (is_scalar($value)) { - $sql[] = $phValue; - $params[$phValue] = $value; - } elseif (is_array($value)) { - $sql[] = static::dynColSqlMaria($value, $params); - } - } - - return $sql === [] ? 'null' : 'json_build_object(' . implode(',', $sql) . ')::jsonb'; - } -} \ No newline at end of file + //this function is unused for postgresql and may be removed when we make sure that + // such handling is indeed not needed + + /* private static function dynColSqlMaria(array $attrs, & $params) + { + $sql = []; + foreach ($attrs as $key => $value) { + if (is_object($value) && !($value instanceof ValueExpression)) { + $value = method_exists($value, 'toArray') ? $value->toArray() : (array) $value; + } + if ($value === [] || $value === null) { + continue; + } + $phKey = static::placeholder(); + $phValue = static::placeholder(); + $sql[] = $phKey; + $params[$phKey] = $key; + if ($value instanceof ValueExpression || is_float($value)) { + $sql[] = $value; + } elseif (is_scalar($value)) { + $sql[] = $phValue; + $params[$phValue] = $value; + } elseif (is_array($value)) { + $sql[] = static::dynColSqlMaria($value, $params); + } + } + return $sql === [] ? 'null' : 'json_build_object(' . implode(',', $sql) . ')::jsonb'; + + } + * + */ +} diff --git a/pgencoder7.xml b/pgencoder7.xml new file mode 100644 index 0000000..932ac91 --- /dev/null +++ b/pgencoder7.xml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tests\unit\DynamicActiveRecordPgsqlTest::testFindAsArray +Failed asserting that two arrays are equal. +--- Expected ++++ Actual +@@ @@ + Array ( + 'id' => 2 + 'name' => 'product2' +- 'dynamic_columns' => Array (...) ++ 'dynamic_columns' => '{"int": 456}' + ) + +/home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTestPgJson.php:413 +/usr/local/bin/phpunit:581 + + + + + + + + + + + + + + + + + + tests\unit\DynamicActiveRecordPgsqlTest::testBooleanAttribute +yii\db\Exception: SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for integer: "t" +The SQL being executed was: SELECT * FROM "customer" WHERE "status"=TRUE + +/home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636 +/home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917 +/home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:362 +/home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:213 +/home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:133 +/home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/tests/framework/ar/ActiveRecordTestTrait.php:1090 +/home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTestPgJson.php:714 +/usr/local/bin/phpunit:581 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pgtestresult_id_by_pg.teamcity b/pgtestresult_id_by_pg.teamcity new file mode 100644 index 0000000..0999715 --- /dev/null +++ b/pgtestresult_id_by_pg.teamcity @@ -0,0 +1,568 @@ + +##teamcity[testCount count='122' flowId='11505'] + +##teamcity[testSuiteStarted name='tests\unit\DynamicActiveRecordPgsqlTest' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest' flowId='11505'] + +##teamcity[testStarted name='testRead' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testRead' flowId='11505'] + +##teamcity[testFinished name='testRead' duration='6280' flowId='11505'] + +##teamcity[testStarted name='testTypes' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testTypes' flowId='11505'] + +##teamcity[testFinished name='testTypes' duration='5950' flowId='11505'] + +##teamcity[testStarted name='testAsArray' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testAsArray' flowId='11505'] + +##teamcity[testFailed name='testAsArray' message='Failed asserting that an array has the subset Array &0 (|n |'name|' => |'product1|'|n |'int|' => 123|n |'str|' => |'value1|'|n |'bool|' => 1|n |'float|' => 123.456|n |'children|' => Array &1 (|n |'int|' => 123|n |'str|' => |'value1|'|n |'bool|' => 1|n |'float|' => 123.456|n )|n).' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:114|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testAsArray' duration='5530' flowId='11505'] + +##teamcity[testSuiteStarted name='testWriteRead' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #0' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #0' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #0' duration='6440' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #1' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #1' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #1' duration='3410' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #2' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #2' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #2' duration='2980' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #3' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #3' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #3' duration='3160' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #4' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #4' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #4' duration='2980' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #5' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #5' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #5' duration='2850' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #6' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #6' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #6' duration='3070' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #7' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #7' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #7' duration='3250' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #8' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #8' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #8' duration='3070' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #9' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #9' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #9' duration='2870' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #10' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #10' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #10' duration='2970' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #11' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #11' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #11' duration='3540' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #12' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #12' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #12' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #13' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #13' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #13' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "quote"|nLINE 1: ...ALUES ((select CAST (|'{"string3":"string with a |' quote char...|n ^|nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'{"string3":"string with a |' quote char in it"}|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #13' duration='3160' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #14' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #14' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #14' duration='2890' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #15' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #15' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #15' duration='3370' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #16' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #16' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #16' duration='2920' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #17' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #17' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #17' duration='3340' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #18' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #18' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #18' duration='3230' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #19' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #19' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #19' duration='3200' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #20' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #20' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #20' duration='3140' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #21' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #21' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #21' duration='3160' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #22' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #22' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #22' duration='3570' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #23' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #23' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #23' message='data name: fakeoctet|nFailed asserting that two strings are equal.' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:250|n /usr/local/bin/phpunit:581|n ' type='comparisonFailure' actual='Binary String: 0x4e18ac8ac9b2b2dae29e' expected='|'data:application/octet-stream;base64,This is my string|'' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #23' duration='3520' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #24' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #24' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #24' message='data name: octet|nFailed asserting that two strings are equal.' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:250|n /usr/local/bin/phpunit:581|n ' type='comparisonFailure' actual='|'This is my string|'' expected='|'data:application/octet-stream;base64,VGhpcyBpcyBteSBzdHJpbmc=|'' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #24' duration='3050' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #25' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #25' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #25' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for type json|nLINE 1: ...roduct" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSON...|n ^|nDETAIL: The input string ended unexpectedly.|nCONTEXT: JSON data, line 1: |nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #25' duration='3020' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #26' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #26' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #26' message='data name: array0|n|'1|' does not match expected type "array".' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:250|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #26' duration='3020' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #27' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #27' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #27' duration='3170' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #28' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #28' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #28' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for type json|nLINE 1: ...roduct" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSON...|n ^|nDETAIL: The input string ended unexpectedly.|nCONTEXT: JSON data, line 1: |nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #28' duration='3070' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #29' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #29' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #29' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for type json|nLINE 1: ...roduct" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSON...|n ^|nDETAIL: The input string ended unexpectedly.|nCONTEXT: JSON data, line 1: |nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #29' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #30' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #30' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #30' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for type json|nLINE 1: ...roduct" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSON...|n ^|nDETAIL: The input string ended unexpectedly.|nCONTEXT: JSON data, line 1: |nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #30' duration='3090' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #31' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #31' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #31' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for type json|nLINE 1: ...roduct" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSON...|n ^|nDETAIL: The input string ended unexpectedly.|nCONTEXT: JSON data, line 1: |nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #31' duration='3390' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #32' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #32' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #32' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for type json|nLINE 1: ...roduct" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSON...|n ^|nDETAIL: The input string ended unexpectedly.|nCONTEXT: JSON data, line 1: |nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #32' duration='3050' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #33' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #33' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #33' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for type json|nLINE 1: ...roduct" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSON...|n ^|nDETAIL: The input string ended unexpectedly.|nCONTEXT: JSON data, line 1: |nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #33' duration='3000' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #34' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #34' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #34' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for type json|nLINE 1: ...roduct" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSON...|n ^|nDETAIL: The input string ended unexpectedly.|nCONTEXT: JSON data, line 1: |nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #34' duration='3510' flowId='11505'] + +##teamcity[testStarted name='testWriteRead with data set #35' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testWriteRead with data set #35' flowId='11505'] + +##teamcity[testFailed name='testWriteRead with data set #35' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for type json|nLINE 1: ...roduct" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSON...|n ^|nDETAIL: The input string ended unexpectedly.|nCONTEXT: JSON data, line 1: |nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:239|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testWriteRead with data set #35' duration='3100' flowId='11505'] + +##teamcity[testSuiteFinished name='testWriteRead' flowId='11505'] + +##teamcity[testStarted name='testDynamicValueObects' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testDynamicValueObects' flowId='11505'] + +##teamcity[testFailed name='testDynamicValueObects' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "str"|nLINE 1: ...olumns") VALUES ((select CAST (|'{"str":{"value":"|'str|'","typ...|n ^|nThe SQL being executed was: INSERT INTO "product" ("dynamic_columns") VALUES ((select CAST (|'{"str":{"value":"|'str|'","type":null},"char":{"value":"|'char|'","type":"CHAR"},"date":{"value":"|'1999-12-31|'","type":"DATE"},"datetime":{"value":"|'1999-12-31 23:59:59|'","type":"DATETIME"},"datetimeN":{"value":"\"1999-12-31 23:59:59.999999\"","type":"DATETIME(6)"},"time":{"value":"|'12:30:00|'","type":"TIME"},"timeD":{"value":"\"12:30:00.123456\"","type":"TIME(6)"},"int":{"value":432,"type":null},"integer":{"value":432,"type":"INTEGER"},"unsignedInt":{"value":321,"type":"UNSIGNED INTEGER"},"float":{"value":12.99,"type":null},"double":{"value":1.299e+31,"type":"DOUBLE"},"decimal":{"value":12.99,"type":"DECIMAL"},"decimalN":{"value":12.99,"type":"DECIMAL(6)"},"decimalND":{"value":12.99,"type":"DECIMAL(6,3)"}}|' AS JSONB))) RETURNING "id"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/pgsql/Schema.php:530|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:494|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveRecord.php:461|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:635|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:301|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testDynamicValueObects' duration='3060' flowId='11505'] + +##teamcity[testStarted name='testDotAttributes' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testDotAttributes' flowId='11505'] + +##teamcity[testIgnored name='testDotAttributes' message='need to write assertions' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:312|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testDotAttributes' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testCustomColumns' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testCustomColumns' flowId='11505'] + +##teamcity[testFailed name='testCustomColumns' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: SELECT *, ((("dynamic_columns"->|'children|' AS CHAR)->|'int|' A...|n ^|nThe SQL being executed was: SELECT *, ((("dynamic_columns"->|'children|' AS CHAR)->|'int|' AS CHAR)*2) AS customColumn, "dynamic_columns" AS "dynamic_columns" FROM "product" WHERE "name"=|'product1|'' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:253|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:295|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:321|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testCustomColumns' duration='3030' flowId='11505'] + +##teamcity[testStarted name='testCustomColumnsExpression' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testCustomColumnsExpression' flowId='11505'] + +##teamcity[testFailed name='testCustomColumnsExpression' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: SELECT *, ((("dynamic_columns"->|'children|' AS char)->|'int|' A...|n ^|nThe SQL being executed was: SELECT *, ((("dynamic_columns"->|'children|' AS char)->|'int|' AS char)*2) AS customColumn, "dynamic_columns" AS "dynamic_columns" FROM "product" WHERE "name"=|'product1|'' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:253|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:295|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:332|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testCustomColumnsExpression' duration='3210' flowId='11505'] + +##teamcity[testStarted name='testStatisticalFind' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testStatisticalFind' flowId='11505'] + +##teamcity[testFailed name='testStatisticalFind' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: ...*) FROM "product" WHERE ("dynamic_columns"->|'int|' AS CHAR) =...|n ^|nThe SQL being executed was: SELECT COUNT(*) FROM "product" WHERE ("dynamic_columns"->|'int|' AS CHAR) = 123 OR ("dynamic_columns"->|'int|' AS CHAR) = 456' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:388|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:431|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:334|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:319|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:341|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testStatisticalFind' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testFindScalar' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindScalar' flowId='11505'] + +##teamcity[testFailed name='testFindScalar' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: SELECT (("dynamic_columns"->|'children|' AS CHAR)->|'str|' AS CH...|n ^|nThe SQL being executed was: SELECT (("dynamic_columns"->|'children|' AS CHAR)->|'str|' AS CHAR) FROM "product" WHERE "id"=1' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:388|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:269|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:352|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testFindScalar' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testFindColumn' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindColumn' flowId='11505'] + +##teamcity[testFailed name='testFindColumn' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: SELECT ("dynamic_columns"->|'int|' AS int) FROM "product"|n ^|nThe SQL being executed was: SELECT ("dynamic_columns"->|'int|' AS int) FROM "product"' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:405|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:285|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:366|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testFindColumn' duration='2980' flowId='11505'] + +##teamcity[testStarted name='testFindBySql' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindBySql' flowId='11505'] + +##teamcity[testFailed name='testFindBySql' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 2: ...ROM product WHERE (("dynamic_columns"->|'children|' AS CHAR)->...|n ^|nThe SQL being executed was: SELECT *, COLUMN_JSON(dynamic_columns) AS dynamic_columns|n FROM product WHERE (("dynamic_columns"->|'children|' AS CHAR)->|'str|' AS CHAR)=|'value1|'' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:253|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:295|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:382|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testFindBySql' duration='3480' flowId='11505'] + +##teamcity[testStarted name='testFind' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFind' flowId='11505'] + +##teamcity[testFailed name='testFind' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: ...t" WHERE ("id"=$1) AND (("dynamic_columns"->|'str|' AS CHAR)=$...|n ^|nThe SQL being executed was: SELECT *, "dynamic_columns" AS "dynamic_columns" FROM "product" WHERE ("id"=1) AND (("dynamic_columns"->|'str|' AS CHAR)=|'value1|')' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:376|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:253|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:295|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/BaseActiveRecord.php:107|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:393|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testFind' duration='3150' flowId='11505'] + +##teamcity[testStarted name='testFindAsArray' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindAsArray' flowId='11505'] + +##teamcity[testFailed name='testFindAsArray' message='Failed asserting that two arrays are equal.' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/tests/framework/ar/ActiveRecordTestTrait.php:127|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:410|n /usr/local/bin/phpunit:581|n ' type='comparisonFailure' actual='Array (|n |'id|' => 2|n |'email|' => |'user2@example.com|'|n |'name|' => |'user2|'|n |'address|' => |'address2|'|n |'status|' => 1|n |'profile_id|' => null|n |'bool_status|' => true|n)' expected='Array (|n |'id|' => 2|n |'email|' => |'user2@example.com|'|n |'name|' => |'user2|'|n |'address|' => |'address2|'|n |'status|' => 1|n |'profile_id|' => null|n)' flowId='11505'] + +##teamcity[testFinished name='testFindAsArray' duration='3100' flowId='11505'] + +##teamcity[testStarted name='testFindIndexBy' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindIndexBy' flowId='11505'] + +##teamcity[testFinished name='testFindIndexBy' duration='3180' flowId='11505'] + +##teamcity[testStarted name='testFindIndexByAsArray' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindIndexByAsArray' flowId='11505'] + +##teamcity[testFinished name='testFindIndexByAsArray' duration='3120' flowId='11505'] + +##teamcity[testStarted name='testRefresh' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testRefresh' flowId='11505'] + +##teamcity[testFinished name='testRefresh' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testEquals' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testEquals' flowId='11505'] + +##teamcity[testFinished name='testEquals' duration='3030' flowId='11505'] + +##teamcity[testStarted name='testFindCount' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindCount' flowId='11505'] + +##teamcity[testFailed name='testFindCount' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: ...*) FROM "product" WHERE ("dynamic_columns"->|'int|' AS CHAR)=$...|n ^|nThe SQL being executed was: SELECT COUNT(*) FROM "product" WHERE ("dynamic_columns"->|'int|' AS CHAR)=123' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:388|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:431|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:334|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:319|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:531|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testFindCount' duration='3050' flowId='11505'] + +##teamcity[testStarted name='testFindComplexCondition' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindComplexCondition' flowId='11505'] + +##teamcity[testFailed name='testFindComplexCondition' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: ...) FROM "product" WHERE (("dynamic_columns"->|'int|' AS CHAR)=$...|n ^|nThe SQL being executed was: SELECT COUNT(*) FROM "product" WHERE (("dynamic_columns"->|'int|' AS CHAR)=|'123|') OR (("dynamic_columns"->|'int|' AS CHAR)=|'456|')' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:388|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:431|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:334|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:319|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:541|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testFindComplexCondition' duration='3390' flowId='11505'] + +##teamcity[testStarted name='testFindNullValues' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindNullValues' flowId='11505'] + +##teamcity[testFailed name='testFindNullValues' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: ...s" FROM "product" WHERE ("dynamic_columns"->|'int|' AS CHAR) I...|n ^|nThe SQL being executed was: SELECT *, "dynamic_columns" AS "dynamic_columns" FROM "product" WHERE ("dynamic_columns"->|'int|' AS CHAR) IS NULL' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:362|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:213|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:133|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:568|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testFindNullValues' duration='3020' flowId='11505'] + +##teamcity[testStarted name='testExists' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testExists' flowId='11505'] + +##teamcity[testFailed name='testExists' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: ...M "product" WHERE (("dynamic_columns"->|'children|' AS CHAR)->...|n ^|nThe SQL being executed was: SELECT EXISTS(SELECT *, "dynamic_columns" AS "dynamic_columns" FROM "product" WHERE (("dynamic_columns"->|'children|' AS CHAR)->|'int|' AS CHAR)=123)' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:388|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:395|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:577|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testExists' duration='3260' flowId='11505'] + +##teamcity[testStarted name='testFindLazy' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindLazy' flowId='11505'] + +##teamcity[testFinished name='testFindLazy' duration='3440' flowId='11505'] + +##teamcity[testStarted name='testFindEager' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindEager' flowId='11505'] + +##teamcity[testFinished name='testFindEager' duration='2940' flowId='11505'] + +##teamcity[testStarted name='testRelationsWhereDynamicColumnMissing' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testRelationsWhereDynamicColumnMissing' flowId='11505'] + +##teamcity[testFinished name='testRelationsWhereDynamicColumnMissing' duration='2990' flowId='11505'] + +##teamcity[testStarted name='testInsert' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testInsert' flowId='11505'] + +##teamcity[testFinished name='testInsert' duration='3080' flowId='11505'] + +##teamcity[testStarted name='testUpdate' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUpdate' flowId='11505'] + +##teamcity[testFinished name='testUpdate' duration='2990' flowId='11505'] + +##teamcity[testStarted name='testUpdateAttributes' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUpdateAttributes' flowId='11505'] + +##teamcity[testFinished name='testUpdateAttributes' duration='3070' flowId='11505'] + +##teamcity[testStarted name='testBooleanAttribute' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testBooleanAttribute' flowId='11505'] + +##teamcity[testFailed name='testBooleanAttribute' message='SQLSTATE|[22P02|]: Invalid text representation: 7 ERROR: invalid input syntax for integer: "t"|nThe SQL being executed was: SELECT * FROM "customer" WHERE "status"=TRUE' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:362|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:213|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:133|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/tests/framework/ar/ActiveRecordTestTrait.php:1090|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:718|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testBooleanAttribute' duration='2910' flowId='11505'] + +##teamcity[testStarted name='testFindEmptyInCondition' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindEmptyInCondition' flowId='11505'] + +##teamcity[testFailed name='testFindEmptyInCondition' message='SQLSTATE|[42601|]: Syntax error: 7 ERROR: syntax error at or near "AS"|nLINE 1: ...s" FROM "product" WHERE ("dynamic_columns"->|'int|' AS CHAR)=$...|n ^|nThe SQL being executed was: SELECT *, "dynamic_columns" AS "dynamic_columns" FROM "product" WHERE ("dynamic_columns"->|'int|' AS CHAR)=123' details=' /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Schema.php:636|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:917|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Command.php:362|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/Query.php:213|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/vendor/yiisoft/yii2-dev/framework/db/ActiveQuery.php:133|n /home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordTest.php:742|n /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testFindEmptyInCondition' duration='3800' flowId='11505'] + +##teamcity[testStarted name='testFindExists' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindExists' flowId='11505'] + +##teamcity[testFinished name='testFindExists' duration='3080' flowId='11505'] + +##teamcity[testStarted name='testCountWithFindBySql' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testCountWithFindBySql' flowId='11505'] + +##teamcity[testIgnored name='testCountWithFindBySql' message='This test depends on "tests\unit\DynamicActiveRecordPgsqlTest::testFindBySql" to pass.' details=' /usr/local/bin/phpunit:581|n ' flowId='11505'] + +##teamcity[testFinished name='testCountWithFindBySql' duration='0' flowId='11505'] + +##teamcity[testStarted name='testFindLazyViaTable' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindLazyViaTable' flowId='11505'] + +##teamcity[testFinished name='testFindLazyViaTable' duration='3560' flowId='11505'] + +##teamcity[testStarted name='testFindEagerViaTable' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindEagerViaTable' flowId='11505'] + +##teamcity[testFinished name='testFindEagerViaTable' duration='3750' flowId='11505'] + +##teamcity[testStarted name='testDeeplyNestedTableRelation' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testDeeplyNestedTableRelation' flowId='11505'] + +##teamcity[testFinished name='testDeeplyNestedTableRelation' duration='3350' flowId='11505'] + +##teamcity[testStarted name='testDeeplyNestedTableRelation2' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testDeeplyNestedTableRelation2' flowId='11505'] + +##teamcity[testFinished name='testDeeplyNestedTableRelation2' duration='3070' flowId='11505'] + +##teamcity[testStarted name='testStoreNull' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testStoreNull' flowId='11505'] + +##teamcity[testFinished name='testStoreNull' duration='2850' flowId='11505'] + +##teamcity[testStarted name='testStoreEmpty' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testStoreEmpty' flowId='11505'] + +##teamcity[testFinished name='testStoreEmpty' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testIsPrimaryKey' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testIsPrimaryKey' flowId='11505'] + +##teamcity[testFinished name='testIsPrimaryKey' duration='2860' flowId='11505'] + +##teamcity[testStarted name='testJoinWith' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testJoinWith' flowId='11505'] + +##teamcity[testFinished name='testJoinWith' duration='3060' flowId='11505'] + +##teamcity[testStarted name='testJoinWithAndScope' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testJoinWithAndScope' flowId='11505'] + +##teamcity[testFinished name='testJoinWithAndScope' duration='3130' flowId='11505'] + +##teamcity[testStarted name='testJoinWithVia' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testJoinWithVia' flowId='11505'] + +##teamcity[testFinished name='testJoinWithVia' duration='3380' flowId='11505'] + +##teamcity[testSuiteStarted name='testJoinWithAlias' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testJoinWithAlias' flowId='11505'] + +##teamcity[testStarted name='testJoinWithAlias with data set #0' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testJoinWithAlias with data set #0' flowId='11505'] + +##teamcity[testFinished name='testJoinWithAlias with data set #0' duration='3290' flowId='11505'] + +##teamcity[testSuiteFinished name='testJoinWithAlias' flowId='11505'] + +##teamcity[testStarted name='testJoinWithSameTable' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testJoinWithSameTable' flowId='11505'] + +##teamcity[testFinished name='testJoinWithSameTable' duration='3880' flowId='11505'] + +##teamcity[testStarted name='testFindCompositeRelationWithJoin' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindCompositeRelationWithJoin' flowId='11505'] + +##teamcity[testFinished name='testFindCompositeRelationWithJoin' duration='2850' flowId='11505'] + +##teamcity[testStarted name='testFindSimpleRelationWithJoin' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindSimpleRelationWithJoin' flowId='11505'] + +##teamcity[testFinished name='testFindSimpleRelationWithJoin' duration='3050' flowId='11505'] + +##teamcity[testSuiteStarted name='testRelationWhereParams' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testRelationWhereParams' flowId='11505'] + +##teamcity[testStarted name='testRelationWhereParams with data set #0' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testRelationWhereParams with data set #0' flowId='11505'] + +##teamcity[testFinished name='testRelationWhereParams with data set #0' duration='2910' flowId='11505'] + +##teamcity[testStarted name='testRelationWhereParams with data set #1' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testRelationWhereParams with data set #1' flowId='11505'] + +##teamcity[testFinished name='testRelationWhereParams with data set #1' duration='3110' flowId='11505'] + +##teamcity[testStarted name='testRelationWhereParams with data set #2' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testRelationWhereParams with data set #2' flowId='11505'] + +##teamcity[testFinished name='testRelationWhereParams with data set #2' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testRelationWhereParams with data set #3' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testRelationWhereParams with data set #3' flowId='11505'] + +##teamcity[testFinished name='testRelationWhereParams with data set #3' duration='3000' flowId='11505'] + +##teamcity[testSuiteFinished name='testRelationWhereParams' flowId='11505'] + +##teamcity[testStarted name='testAlias' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testAlias' flowId='11505'] + +##teamcity[testFinished name='testAlias' duration='3410' flowId='11505'] + +##teamcity[testStarted name='testInverseOf' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testInverseOf' flowId='11505'] + +##teamcity[testFinished name='testInverseOf' duration='3140' flowId='11505'] + +##teamcity[testStarted name='testInverseOfDynamic' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testInverseOfDynamic' flowId='11505'] + +##teamcity[testFinished name='testInverseOfDynamic' duration='3190' flowId='11505'] + +##teamcity[testStarted name='testDefaultValues' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testDefaultValues' flowId='11505'] + +##teamcity[testFinished name='testDefaultValues' duration='3060' flowId='11505'] + +##teamcity[testStarted name='testUnlinkAllViaTable' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUnlinkAllViaTable' flowId='11505'] + +##teamcity[testFinished name='testUnlinkAllViaTable' duration='3100' flowId='11505'] + +##teamcity[testStarted name='testCastValues' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testCastValues' flowId='11505'] + +##teamcity[testFinished name='testCastValues' duration='3570' flowId='11505'] + +##teamcity[testStarted name='testIssues' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testIssues' flowId='11505'] + +##teamcity[testFinished name='testIssues' duration='4750' flowId='11505'] + +##teamcity[testStarted name='testPopulateRecordCallWhenQueryingOnParentClass' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testPopulateRecordCallWhenQueryingOnParentClass' flowId='11505'] + +##teamcity[testFinished name='testPopulateRecordCallWhenQueryingOnParentClass' duration='2930' flowId='11505'] + +##teamcity[testStarted name='testSaveEmpty' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testSaveEmpty' flowId='11505'] + +##teamcity[testFinished name='testSaveEmpty' duration='2840' flowId='11505'] + +##teamcity[testStarted name='testOptimisticLock' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testOptimisticLock' flowId='11505'] + +##teamcity[testFinished name='testOptimisticLock' duration='3380' flowId='11505'] + +##teamcity[testStarted name='testPopulateWithoutPk' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testPopulateWithoutPk' flowId='11505'] + +##teamcity[testFinished name='testPopulateWithoutPk' duration='3270' flowId='11505'] + +##teamcity[testStarted name='testBit' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testBit' flowId='11505'] + +##teamcity[testFinished name='testBit' duration='3260' flowId='11505'] + +##teamcity[testStarted name='testLinkWhenRelationIsIndexed2' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testLinkWhenRelationIsIndexed2' flowId='11505'] + +##teamcity[testFinished name='testLinkWhenRelationIsIndexed2' duration='2890' flowId='11505'] + +##teamcity[testStarted name='testLinkWhenRelationIsIndexed3' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testLinkWhenRelationIsIndexed3' flowId='11505'] + +##teamcity[testFinished name='testLinkWhenRelationIsIndexed3' duration='2910' flowId='11505'] + +##teamcity[testStarted name='testEmulateExecution' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testEmulateExecution' flowId='11505'] + +##teamcity[testFinished name='testEmulateExecution' duration='3620' flowId='11505'] + +##teamcity[testStarted name='testUnlinkAllOnCondition' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUnlinkAllOnCondition' flowId='11505'] + +##teamcity[testFinished name='testUnlinkAllOnCondition' duration='3420' flowId='11505'] + +##teamcity[testStarted name='testUnlinkAllOnConditionViaTable' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUnlinkAllOnConditionViaTable' flowId='11505'] + +##teamcity[testFinished name='testUnlinkAllOnConditionViaTable' duration='2960' flowId='11505'] + +##teamcity[testStarted name='testHasAttribute' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testHasAttribute' flowId='11505'] + +##teamcity[testFinished name='testHasAttribute' duration='2890' flowId='11505'] + +##teamcity[testStarted name='testFindLimit' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindLimit' flowId='11505'] + +##teamcity[testFinished name='testFindLimit' duration='2890' flowId='11505'] + +##teamcity[testStarted name='testFindLazyVia' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindLazyVia' flowId='11505'] + +##teamcity[testFinished name='testFindLazyVia' duration='3180' flowId='11505'] + +##teamcity[testStarted name='testFindLazyVia2' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindLazyVia2' flowId='11505'] + +##teamcity[testFinished name='testFindLazyVia2' duration='3000' flowId='11505'] + +##teamcity[testStarted name='testFindEagerViaRelation' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindEagerViaRelation' flowId='11505'] + +##teamcity[testFinished name='testFindEagerViaRelation' duration='3000' flowId='11505'] + +##teamcity[testStarted name='testFindNestedRelation' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindNestedRelation' flowId='11505'] + +##teamcity[testFinished name='testFindNestedRelation' duration='3200' flowId='11505'] + +##teamcity[testStarted name='testFindEagerViaRelationPreserveOrder' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindEagerViaRelationPreserveOrder' flowId='11505'] + +##teamcity[testFinished name='testFindEagerViaRelationPreserveOrder' duration='3050' flowId='11505'] + +##teamcity[testStarted name='testFindEagerViaRelationPreserveOrderB' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindEagerViaRelationPreserveOrderB' flowId='11505'] + +##teamcity[testFinished name='testFindEagerViaRelationPreserveOrderB' duration='3050' flowId='11505'] + +##teamcity[testStarted name='testLink' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testLink' flowId='11505'] + +##teamcity[testFinished name='testLink' duration='3580' flowId='11505'] + +##teamcity[testStarted name='testUnlink' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUnlink' flowId='11505'] + +##teamcity[testFinished name='testUnlink' duration='3020' flowId='11505'] + +##teamcity[testStarted name='testUnlinkAll' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUnlinkAll' flowId='11505'] + +##teamcity[testFinished name='testUnlinkAll' duration='3120' flowId='11505'] + +##teamcity[testStarted name='testUnlinkAllAndConditionSetNull' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUnlinkAllAndConditionSetNull' flowId='11505'] + +##teamcity[testFinished name='testUnlinkAllAndConditionSetNull' duration='3830' flowId='11505'] + +##teamcity[testStarted name='testUnlinkAllAndConditionDelete' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUnlinkAllAndConditionDelete' flowId='11505'] + +##teamcity[testFinished name='testUnlinkAllAndConditionDelete' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testExplicitPkOnAutoIncrement' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testExplicitPkOnAutoIncrement' flowId='11505'] + +##teamcity[testFinished name='testExplicitPkOnAutoIncrement' duration='3050' flowId='11505'] + +##teamcity[testStarted name='testUpdateCounters' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testUpdateCounters' flowId='11505'] + +##teamcity[testFinished name='testUpdateCounters' duration='3090' flowId='11505'] + +##teamcity[testStarted name='testDelete' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testDelete' flowId='11505'] + +##teamcity[testFinished name='testDelete' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testAfterFind' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testAfterFind' flowId='11505'] + +##teamcity[testFinished name='testAfterFind' duration='3100' flowId='11505'] + +##teamcity[testStarted name='testAfterRefresh' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testAfterRefresh' flowId='11505'] + +##teamcity[testFinished name='testAfterRefresh' duration='3140' flowId='11505'] + +##teamcity[testStarted name='testFindEagerIndexBy' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testFindEagerIndexBy' flowId='11505'] + +##teamcity[testFinished name='testFindEagerIndexBy' duration='3040' flowId='11505'] + +##teamcity[testStarted name='testAttributeAccess' locationHint='php_qn:///home/nexus/NetBeansProjects/yii2-dynamic-ar/tests/unit/DynamicActiveRecordPgsqlTest.php::\tests\unit\DynamicActiveRecordPgsqlTest::testAttributeAccess' flowId='11505'] + +##teamcity[testFinished name='testAttributeAccess' duration='3380' flowId='11505'] + +##teamcity[testSuiteFinished name='tests\unit\DynamicActiveRecordPgsqlTest' flowId='11505'] diff --git a/tests/unit/DynamicActiveRecordPgsqlTest.php b/tests/unit/DynamicActiveRecordPgsqlTest.php index 1ecfb3b..d5877c3 100644 --- a/tests/unit/DynamicActiveRecordPgsqlTest.php +++ b/tests/unit/DynamicActiveRecordPgsqlTest.php @@ -8,12 +8,8 @@ namespace tests\unit; use Yii; - -/** - * @author Tom Worster - * @author Danil Zakablukovskii danil.kabluk@gmail.com - */ -class DynamicActiveRecordPgsqlTest extends DynamicActiveRecordTest +// use tests\unit\data\dar\Product; +class DynamicActiveRecordPgsqlTest extends DynamicActiveRecordTestPgJson { protected $driverName = 'pgsql'; } diff --git a/tests/unit/DynamicActiveRecordTestJson.php b/tests/unit/DynamicActiveRecordTestJson.php new file mode 100644 index 0000000..42ca91f --- /dev/null +++ b/tests/unit/DynamicActiveRecordTestJson.php @@ -0,0 +1,759 @@ + + * @author Danil Zakablukovskii danil.kabluk@gmail.com + */ +class DynamicActiveRecordTestJson extends ActiveRecordTest +{ + /** @var Connection */ + protected $db; + + const BINARY_STRING = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; + + protected static $resetFixture = true; + + protected function setUp() + { + static::$params = require(__DIR__ . '/data/config.php'); + parent::setUp(); + + $this->db = BaseRecord::$db = $this->getConnection(self::$resetFixture); + } + + protected static function hexDump($data, $newline = "\n") + { + static $from = ''; + static $to = ''; + static $width = 16; # number of bytes per line + static $pad = '.'; # padding for non-visible characters + + if ($from === '') { + for ($i = 0; $i <= 0xFF; $i++) { + $from .= chr($i); + $to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad; + } + } + + $hex = str_split(bin2hex($data), $width * 2); + $chars = str_split(strtr($data, $from, $to), $width); + + $offset = 0; + foreach ($hex as $i => $line) { + echo sprintf('%6X', $offset) . ' : ' + . implode(' ', str_split(str_pad($line, 2 * $width), 2)) + . ' [' . str_pad($chars[$i], $width) . ']' . $newline; + $offset += $width; + } + } + + public function testRead() + { + $query = Product::find(); + $this->assertTrue($query instanceof DynamicActiveQuery); + /** @var Product */ + $product = $query->one(); + $this->assertTrue($product instanceof Product); + } + + public function testTypes() + { + /** @var Product */ + $product = Product::find()->one(); + $this->assertInternalType('string', $product->str); + $this->assertInternalType('integer', $product->int); + $this->assertInternalType('float', $product->float); + $this->assertInternalType('integer', $product->bool); + $this->assertEmpty($product->null); + $this->assertInternalType('string', $product->children['str']); + $this->assertInternalType('integer', $product->children['int']); + $this->assertInternalType('float', $product->children['float']); + $this->assertInternalType('integer', $product->children['bool']); + $this->assertFalse(isset($product->children['null'])); + } + + public function testAsArray() + { + /** @var Product $product */ + $product = Product::findOne(1); + $expect = [ + 'name' => 'product1', + 'int' => 123, + 'str' => 'value1', + 'bool' => true, + 'float' => 123.456, + 'children' => [ + 'int' => 123, + 'str' => 'value1', + 'bool' => true, + 'float' => 123.456, + ], + ]; + $this->assertArraySubset($expect, $product->toArray(), true); + + $product->float = new ValueExpression(123.456); + + $product->save(false); + $product2 = Product::findOne($product->id); + $this->assertArraySubset($expect, $product2->toArray(), true); + } + +/* public function dataProviderTestMariaArrayEncoding() + { + $tests = [ + [[1]], + [['x' => 'asd']], + [['x' => "asd\xC1\xC2\xC3asd"]], + [["asd\xC1\xC2\xC3asd" => 'qwert']], + [[1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true]], + [[[[1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true]]]], + [[1, [2, [3, [4, [1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true]]]]]], + [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true], + 3, + 'four' => true, + ], + [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true], + 3, + 'four' => true, + ], + 3, + 'four' => true, + ], + [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true], + 3, + 'four' => true, + ], + 3, + "asd\xC1\xC2\xC3asd" => false, + ], + 3, + "qwert\xD1\xD2\xD3" => self::BINARY_STRING, + ], + 3, + "_x\xE1" => false, + ], + ]; + + return array_merge($tests); + } +*/ + public function dataProviderTestWriteRead() + { + $data = [ + ['int', 1234], + ['neg', -4321], + // ['octal', 076543], base 10 numbers only in json + // ['hex', 0xbada55], + ['largeint', 2147483647], + ['largerin', 9223372036854775807], + ['neglargein', -2147483648], + ['neglargerin', -9223372036854775807], + ['float', 1.1234], + ['morefloat', 1.123456789012345], + ['evenmorefloat', 1.123456789012345678901234567890], + // https://mariadb.atlassian.net/browse/MDEV-8521 + // ['bigfloat', 1.123456789012345e+300], + // ['bignegfloat', -1.123456789012345e+300], + ['string1', "this is a simple string"], //all strings should be double quoted + ['string2', "string with a \\ backslash in it"], + ['string3', "string with a \' quote char in it"], + ['string4', "string with a \" doublequote char in it"], + ['string5', "string with a / slash in it"], + ['string5', "string with a \n newline in it"], + ['string5', "string with a \r return in it"], + ['string5', "string with a \t tab in it"], + ['string5', "string with a \v vertical tab in it"], + ['string5', "string with a \e escape in it"], + ['string5', "string with a \f form feed in it"], + [ + 'newlines', + "You can also have embedded newlines in + strings this way as it is + okay to do" + ], + ['fakeoctet', BaseEncoder::DATA_URI_PREFIX . "This is my string"], + ['octet', BaseEncoder::DATA_URI_PREFIX . base64_encode("This is my string")], + ]; + + //$data = array_merge($data, include(__DIR__ . '/unicodeStrings.php')); + + $data[] = ['binarystring', self::BINARY_STRING]; + + foreach ($this->dataProviderTestMariaArrayEncoding() as $i => $array) { + $data[] = ['array' . $i, $array]; + } + + return $data; + } + + /** + * @dataProvider dataProviderTestWriteRead + * + * @param string $name + * @param mixed $value + */ + public function testWriteRead($name, $value) + { + self::$resetFixture = false; + $product = new Product(); + /** @var string $product->$name */ + $product->$name = $value; + + $product->save(false); + $id = $product->primaryKey; + unset($product); + + $product = Product::findOne($id); + + $this->assertEquals( + $value, + $product->$name, + 'data name: ' . $name, + is_float($value) ? abs($value) / 10e+12 : 0 + ); + unset($product); + } + + public function testDynamicValueObects() + { + $expected = [ + 'str' => 'str', + // 'char' => 'char', // all these are strings in json. + // 'date' => '1999-12-31', + // 'datetime' => '1999-12-31 23:59:59', + // 'datetimeN' => '1999-12-31 23:59:59.999999', + // 'time' => '12:30:00', + // 'timeD' => '12:30:00.123456', + 'int' => 432, + // 'integer' => 432, + // 'unsignedInt' => 321, + 'float' => 12.99, + // https://mariadb.atlassian.net/browse/MDEV-8521 + // 'double' => '1.3e31', + // 'decimal' => 12.99, + // 'decimalN' => 12.99, + // 'decimalND' => 12.99, + ]; + + $p = new Product([ + 'str' => new ValueExpression("'str'"), + // 'char' => new ValueExpression("'char'", 'CHAR'), + // 'date' => new ValueExpression("'1999-12-31'", 'DATE'), + // 'datetime' => new ValueExpression("'1999-12-31 23:59:59'", 'DATETIME'), + // 'datetimeN' => new ValueExpression('"1999-12-31 23:59:59.999999"', 'DATETIME(6)'), + // 'time' => new ValueExpression("'12:30:00'", 'TIME'), + // 'timeD' => new ValueExpression('"12:30:00.123456"', 'TIME(6)'), + 'int' => new ValueExpression(432), + // 'integer' => new ValueExpression(432, 'INTEGER'), + // 'unsignedInt' => new ValueExpression(321, 'UNSIGNED INTEGER'), + // 'float' => new ValueExpression(12.99), + // 'double' => new ValueExpression(12.99E+30, 'DOUBLE'), + // 'decimal' => new ValueExpression(12.99, 'DECIMAL'), + // 'decimalN' => new ValueExpression(12.99, 'DECIMAL(6)'), + // 'decimalND' => new ValueExpression(12.99, 'DECIMAL(6,3)'), +// https://mariadb.atlassian.net/browse/MDEV-8526 +// 'charN' => new ValueExpression("'charN'", 'CHAR(10)'), +// 'bin' => new ValueExpression('unhex("cafebabebada55")', 'BINARY'), +// 'binN' => new ValueExpression('unhex("cafebabebada55")', 'BINARY(10)'), +// 'doubleN' => new ValueExpression(12.99E+30, 'DOUBLE(6)'), +// 'doubleND' => new ValueExpression(12.99E+30, 'DOUBLE(6,3)'), +// 'signed' => new ValueExpression(-432, 'SIGNED'), +// 'signedInt' => new ValueExpression(-432, 'SIGNED INTEGER'), +// 'unsigned' => new ValueExpression(321, 'UNSIGNED'), + ]); + $p->save(false); + + $actual = Product::findOne($p->id)->toArray(); + + $this->assertArraySubset($expected, $actual); + } + + public function testDotAttributes() + { + /** @var Product $p */ + $p = Product::findOne(1); + $this->markTestIncomplete('need to write assertions'); + } + + public function testCustomColumns() + { + parent::testCustomColumns(); + + // find custom column + $customer = Product::find()->select(['*', '((!children.int!)*2) AS customColumn']) + ->where(['name' => 'product1'])->one(); + $this->assertEquals(1, $customer->id); + $this->assertEquals(246, $customer->customColumn); + } + + public function testCustomColumnsExpression() + { + // find custom column + $customer = Product::find() + ->select(['*', '(' . Product::columnExpression('children.int') . '*2) AS customColumn']) + ->where(['name' => 'product1']) + ->one(); + $this->assertEquals(1, $customer->id); + $this->assertEquals(246, $customer->customColumn); + } + + public function testStatisticalFind() + { + parent::testStatisticalFind(); + + $this->assertEquals(2, Product::find()->where('(!int!) = 123 OR (!int!) = 456')->count()); + $this->assertEquals(123, Product::find()->min('(!int|int!)')); + $this->assertEquals(792, Product::find()->max('(!int|int!)')); + $this->assertEquals(457, Product::find()->average('(!int|int!)')); + } + + public function testFindScalar() + { + parent::testFindScalar(); + + // query scalar + $val = Product::find()->where(['id' => 1])->select(['(!children.str!)'])->scalar(); + $this->assertEquals('value1', $val); + + $val = Product::find()->where(['id' => 1])->select(['(!children.bool!)'])->scalar(); + $this->assertEquals(1, $val); + + $val = Product::find()->where(['id' => 1])->select(['(!children.null!)'])->scalar(); + $this->assertNull($val); + } + + public function testFindColumn() + { + parent::testFindColumn(); + + $this->assertEquals([123, 456, 792], Product::find()->select(['(!int|int!)'])->column()); + $this->assertEquals([792, 456, 123], + Product::find()->orderBy(['(!int|int!)' => SORT_DESC])->select(['(!int|int!)']) + ->column()); + } + + public function testFindBySql() + { //this will not work, to use where in a jsonb column you have to practicaly + //create a temp table and search within + //------------------- something like this will work-------- + //select * from product where id IN( + //with myproduct as (select "id", dynamic_columns::jsonb#>>'{"path","path","element"}' as "myvar" from product) + //select person_id from myproduct where "myvar" =:v) + parent::testFindBySql(); + + // find with parameter binding + $product = + Product::findBySql( + 'SELECT *, COLUMN_JSON(dynamic_columns) AS dynamic_columns + FROM product WHERE (! children.str !)=:v', + [':v' => 'value1']) + ->one(); + $this->assertTrue($product instanceof Product); + $this->assertEquals('product1', $product->name); + $this->assertEquals('value1', $product->children['str']); + } + + public function testFind() + { + parent::testFind(); + + // find by column values + $product = Product::findOne(['id' => 1, '(!str!)' => 'value1']); + $this->assertTrue($product instanceof Product); + $this->assertEquals('value1', $product->str); + $product = Product::findOne(['id' => 1, '(!str!)' => 'value2']); + $this->assertNull($product); + $product = Product::findOne(['(!children.str!)' => 'value5']); + $this->assertNull($product); + + // find by attributes + $product = Product::find()->where(['(!children.str!)' => 'value1'])->one(); + $this->assertTrue($product instanceof Product); + $this->assertEquals('value1', $product->children['str']); + $this->assertEquals(1, $product->id); + } + + public function testFindAsArray() + { + parent::testFindAsArray(); + + // asArray + $product = Product::find()->where(['id' => 2])->asArray()->one(); + $this->assertEquals([ + 'id' => 2, + 'name' => 'product2', + Product::dynamicColumn() => json_encode(['int' => 456]), + ], $product); + + // find all asArray + $products = Product::find()->asArray()->all(); + $this->assertEquals(3, count($products)); + + $this->assertArrayHasKey('id', $products[0]); + $this->assertArrayHasKey('name', $products[0]); + $this->assertArrayHasKey('dynamic_columns', $products[2]); + + $this->assertArrayHasKey('id', $products[1]); + $this->assertArrayHasKey('name', $products[1]); + $this->assertArrayHasKey('dynamic_columns', $products[2]); + + $this->assertArrayHasKey('id', $products[2]); + $this->assertArrayHasKey('name', $products[2]); + $this->assertArrayHasKey('dynamic_columns', $products[2]); + } + + public function testFindIndexBy() + { + parent::testFindIndexBy(); + + // indexBy + $products = Product::find()->indexBy('int')->orderBy('id')->all(); + $this->assertEquals(3, count($products)); + $this->assertTrue($products['123'] instanceof Product); + $this->assertTrue($products['456'] instanceof Product); + $this->assertTrue($products['792'] instanceof Product); + + // indexBy callable + $products = Product::find()->indexBy(function ($product) { + return $product->id . '-' . $product->int; + })->orderBy('id')->all(); + $this->assertEquals(3, count($products)); + $this->assertTrue($products['1-123'] instanceof Product); + $this->assertTrue($products['2-456'] instanceof Product); + $this->assertTrue($products['3-792'] instanceof Product); + } + + public function testFindIndexByAsArray() + { + parent::testFindIndexByAsArray(); + + // indexBy + asArray + $products = Product::find()->asArray()->indexBy('int')->all(); + $this->assertEquals(3, count($products)); + $this->assertArrayHasKey('id', $products['123']); + $this->assertArrayHasKey('name', $products['123']); + $this->assertArrayHasKey('dynamic_columns', $products['123']); + + $this->assertArrayHasKey('id', $products['456']); + $this->assertArrayHasKey('name', $products['456']); + $this->assertArrayHasKey('dynamic_columns', $products['456']); + + $this->assertArrayHasKey('id', $products['792']); + $this->assertArrayHasKey('name', $products['792']); + $this->assertArrayHasKey('dynamic_columns', $products['792']); + + // indexBy + asArray + not existed nested column + $products = Product::find()->asArray()->indexBy('children.str')->all(); + $this->assertEquals(3, count($products)); + $this->assertArrayHasKey('id', $products['value1']); + $this->assertArrayHasKey('name', $products['value1']); + $this->assertArrayHasKey('dynamic_columns', $products['value1']); + + // column missing - pk should be used + $this->assertArrayHasKey('id', $products['']); + $this->assertArrayHasKey('name', $products['']); + $this->assertArrayHasKey('dynamic_columns', $products['']); + + $this->assertArrayHasKey('id', $products['value3']); + $this->assertArrayHasKey('name', $products['value3']); + $this->assertArrayHasKey('dynamic_columns', $products['value3']); + } + + public function testRefresh() + { + parent::testRefresh(); + + $product = Product::findOne(1); + $product->str = 'to be refreshed'; + $this->assertTrue($product->refresh()); + $this->assertEquals('value1', $product->str); + + $product = Product::findOne(1); + $product->children = ['str' => 'to be refreshed']; + $this->assertTrue($product->refresh()); + $this->assertEquals('value1', $product->children['str']); + } + + public function testEquals() + { + parent::testEquals(); + + $productA = new Product(); + $productB = new Product(); + $this->assertFalse($productA->equals($productB)); + + $productA = Product::findOne(1); + $productB = Product::findOne(2); + $this->assertFalse($productA->equals($productB)); + + $productB = Product::findOne(1); + $this->assertTrue($productA->equals($productB)); + } + + public function testFindCount() + { + parent::testFindCount(); + + $this->assertEquals(3, Product::find()->count()); + + $this->assertEquals(1, Product::find()->where(['(!int!)' => 123])->count()); + $this->assertEquals(2, Product::find()->where(['(!int!)' => [123, 456]])->count()); + $this->assertEquals(2, Product::find()->where(['(!int!)' => [123, 456]])->offset(1)->count()); + $this->assertEquals(2, Product::find()->where(['(!int!)' => [123, 456]])->offset(2)->count()); + } + + public function testFindComplexCondition() + { + parent::testFindComplexCondition(); + + $this->assertEquals(2, Product::find()->where(['OR', ['(!int!)' => '123'], ['(!int!)' => '456']])->count()); + $this->assertEquals(2, + count(Product::find()->where(['OR', ['(!int!)' => '123'], ['(!int!)' => '456']])->all())); + + $this->assertEquals(2, Product::find()->where(['(!children.str!)' => ['value1', 'value3']])->count()); + $this->assertEquals(2, count(Product::find()->where(['(!children.str!)' => ['value1', 'value3']])->all())); + + $this->assertEquals(1, Product::find()->where([ + 'AND', + ['(!children.str!)' => ['value1', 'value3']], + ['BETWEEN', '(!int!)', 122, 124] + ])->count()); + $this->assertEquals(1, count(Product::find()->where([ + 'AND', + ['(!children.str!)' => ['value1', 'value3']], + ['BETWEEN', '(!int!)', 122, 124] + ])->all())); + } + + public function testFindNullValues() + { + parent::testFindNullValues(); + + $product = Product::findOne(2); + $product->int = null; + $product->save(false); + + $result = Product::find()->where(['(!int!)' => null])->all(); + $this->assertEquals(1, count($result)); + $this->assertEquals(2, reset($result)->primaryKey); + } + + public function testExists() + { + parent::testExists(); + + $this->assertTrue(Product::find()->where(['(!children.int!)' => 123])->exists()); + $this->assertFalse(Product::find()->where(['(!int!)' => 555])->exists()); + $this->assertTrue(Product::find()->where(['(!children.str!)' => 'value3'])->exists()); + $this->assertFalse(Product::find()->where(['(!children.str!)' => 123])->exists()); + } + + public function testFindLazy() + { + parent::testFindLazy(); + + $product = Product::findOne(1); + $this->assertFalse($product->isRelationPopulated('supplier')); + $supplier = $product->supplier; + $this->assertTrue($product->isRelationPopulated('supplier')); + $this->assertEquals(1, $supplier->primaryKey); + + $product = Product::findOne(1); + $this->assertFalse($product->isRelationPopulated('supplier')); + $suppliers = $product->getSupplier()->all(); + $this->assertFalse($product->isRelationPopulated('supplier')); + $this->assertEquals(0, count($product->relatedRecords)); + + $this->assertEquals(1, count($suppliers)); + $this->assertEquals(1, $suppliers[0]->id); + } + + public function testFindEager() + { + parent::testFindEager(); + + $products = Product::find()->with('supplier')->all(); + $this->assertEquals(3, count($products)); + $this->assertTrue($products[0]->isRelationPopulated('supplier')); + $this->assertTrue($products[1]->isRelationPopulated('supplier')); + $this->assertTrue($products[2]->isRelationPopulated('supplier')); + $this->assertEquals(1, count($products[0]->supplier)); + $this->assertEquals(0, count($products[1]->supplier)); + $this->assertEquals(0, count($products[2]->supplier)); + } + + public function testRelationsWhereDynamicColumnMissing() + { + $product = Product::findOne(1); + $this->assertNotNull($product->getSupplier()); + + // product without supplier_id dynamic column + $product = Product::findOne(2); + $this->assertNull($product->getSupplier()->one()); + } + + public function testInsert() + { + parent::testInsert(); + + $product = new Product(); + $product->name = 'test'; + $product->str = 'value test'; + $product->children = [ + 'string1' => 'children string', + 'integer' => 1234, + ]; + + $this->assertNull($product->id); + $this->assertTrue($product->isNewRecord); + + $this->assertTrue($product->save()); + + $this->assertNotNull($product->id); + $this->assertFalse($product->isNewRecord); + + $this->assertEquals('test', $product->name); + $this->assertEquals('value test', $product->str); + $this->assertEquals([ + 'string1' => 'children string', + 'integer' => 1234, + ], $product->children); + } + + public function testUpdate() + { + parent::testUpdate(); + + $product = Product::findOne(1); + $this->assertTrue($product instanceof Product); + $this->assertEquals('123', $product->int); + $this->assertFalse($product->isNewRecord); + $this->assertEmpty($product->dirtyAttributes); + + $product->int = 567; + $product->save(); + $this->assertEquals('567', $product->int); + $product2 = Product::findOne(1); + $this->assertEquals('567', $product2->int); + + // updateAll + // todo need to create new DynamicQueryBuilder to override update() +// $product = Product::findOne(3); +// $this->assertEquals('value3', $product->children['str']); +// $ret = Product::updateAll(['(!children.str!)' => 'temp'], ['id' => 3]); +// $this->assertEquals(1, $ret); +// $product = Product::findOne(3); +// $this->assertEquals('temp', $product->children['str']); +// +// $ret = Product::updateAll(['(!children.str!)' => 'tempX']); +// $this->assertEquals(3, $ret); +// +// $ret = Product::updateAll(['(!children.str!)' => 'tempp'], ['name' => 'product6']); +// $this->assertEquals(0, $ret); + } + + public function testUpdateAttributes() + { + parent::testUpdateAttributes(); + + $product = Product::findOne(2); + $this->assertTrue($product instanceof Product); + $this->assertEquals(456, $product->int); + $this->assertFalse($product->isNewRecord); + +// $product->updateAttributes(['(!int!)' => 777]); +// $this->assertEquals(777, $product->int); +// $this->assertFalse($product->isNewRecord); +// $product2 = Product::findOne(2); +// $this->assertEquals(777, $product2->int); +// $this->assertInternalType('integer', $product2->int); +// +// // update not eisting dynamic attribute +// $product = Product::findOne(3); +// $product->updateAttributes(['(!custom!)' => 'value']); +// $this->assertEquals('value', $product->custom); +// $this->assertFalse($product->isNewRecord); +// $product2 = Product::findOne(3); +// $this->assertEquals('value', $product2->custom); + } + + /** + * Some PDO implementations(e.g. cubrid) do not support boolean values. + * Make sure this does not affect AR layer. + */ + public function testBooleanAttribute() + { + parent::testBooleanAttribute(); + + $product = new Product(); + $product->name = 'boolean customer'; + $product->boolean_dynamic = true; + $product->save(false); + + $product->refresh(); + $this->assertEquals(1, $product->boolean_dynamic); + + $product->boolean_dynamic = false; + $product->save(false); + + $product->refresh(); + $this->assertEquals(0, $product->boolean_dynamic); + + $products = Product::find()->where(['(!boolean_dynamic!)' => false])->all(); + $this->assertEquals(1, count($products)); + } + + public function testFindEmptyInCondition() + { + parent::testFindEmptyInCondition(); + + $products = Product::find()->where(['(!int!)' => [123]])->all(); + $this->assertEquals(1, count($products)); + + $products = Product::find()->where(['(!int!)' => []])->all(); + $this->assertEquals(0, count($products)); + + $products = Product::find()->where(['IN', '(!int!)', [123]])->all(); + $this->assertEquals(1, count($products)); + + $products = Product::find()->where(['IN', '(!int!)', []])->all(); + $this->assertEquals(0, count($products)); + } +} diff --git a/tests/unit/DynamicActiveRecordTestPgJson.php b/tests/unit/DynamicActiveRecordTestPgJson.php new file mode 100644 index 0000000..c2e74a9 --- /dev/null +++ b/tests/unit/DynamicActiveRecordTestPgJson.php @@ -0,0 +1,813 @@ + + * @author Danil Zakablukovskii danil.kabluk@gmail.com + */ +class DynamicActiveRecordTestPgJson extends ActiveRecordTest +{ + + /** @var Connection */ + protected $db; + + const BINARY_STRING = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; + + protected static $resetFixture = true; + + protected function setUp() + { + static::$params = require(__DIR__ . '/data/config.php'); + parent::setUp(); + + $this->db = BaseRecord::$db = $this->getConnection(self::$resetFixture); + } + + protected static function hexDump($data, $newline = "\n") + { + static $from = ''; + static $to = ''; + static $width = 16; # number of bytes per line + static $pad = '.'; # padding for non-visible characters + + if ($from === '') { + for ($i = 0; $i <= 0xFF; $i++) { + $from .= chr($i); + $to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad; + } + } + + $hex = str_split(bin2hex($data), $width * 2); + $chars = str_split(strtr($data, $from, $to), $width); + + $offset = 0; + foreach ($hex as $i => $line) { + echo sprintf('%6X', $offset) . ' : ' + . implode(' ', str_split(str_pad($line, 2 * $width), 2)) + . ' [' . str_pad($chars[$i], $width) . ']' . $newline; + $offset += $width; + } + } + + public function testRead() + { + $query = Product::find(); + $this->assertTrue($query instanceof DynamicActiveQuery); + /** @var Product */ + $product = $query->one(); + $this->assertTrue($product instanceof Product); + } + + public function testTypes() + { + /** @var Product */ + $product = Product::find()->one(); + $this->assertInternalType('string', $product->str); + $this->assertInternalType('integer', $product->int); + $this->assertInternalType('float', $product->float); + $this->assertInternalType('boolean', $product->bool); //not tiny int + $this->assertEmpty($product->null); + $this->assertInternalType('string', $product->children['str']); + $this->assertInternalType('integer', $product->children['int']); + $this->assertInternalType('float', $product->children['float']); + $this->assertInternalType('boolean', $product->children['bool']); //json bool is either + $this->assertFalse(isset($product->children['null'])); // true or false lowercase + } + + public function testAsArray() + { + /** @var Product $product */ + $product = Product::findOne(1); + $expect = [ + 'name' => 'product1', + 'int' => 123, + 'str' => 'value1', + 'bool' => 1, + 'float' => 123.456, + 'children' => [ + 'int' => 123, + 'str' => 'value1', + 'bool' => 1, + 'float' => 123.456, + ], + ]; + + $this->assertArraySubset($expect, $product->toArray(), false); + //see https://github.com/sebastianbergmann/phpunit/issues/2069 + $product->setAttribute('float', 123.456); + + $product->save(false); + $product2 = Product::findOne($product->id); + $this->assertArraySubset($expect, $product2->toArray(), false); + } + + public function testAsJsonArray() + { + /** @var Product $product */ + $product = Product::findOne(11); + $expect = [ + 'name' => 'product1', + 'int' => 1234, + 'str' => 'value11', + 'bool' => 1, + 'float' => 123.456, + 'json_array' => [123, "string 1", true], + 'children' => [ + 'int' => 123, + 'str' => 'value11', + 'bool' => 1, + 'float' => 123.456, + ], + ]; + + $this->assertArraySubset($expect, $product->toArray(), false); + //see https://github.com/sebastianbergmann/phpunit/issues/2069 + $product->setAttribute('float', 123.456); + $product->setAttribute('json_array', [123, "string 1", true]); + + $product->save(false); + $product2 = Product::findOne($product->id); + $this->assertArraySubset($expect, $product2->toArray(), false); + } + + public function testComplexJsonStructure() + { + $product = Product::findOne(12); + $expect = [ + 'name' => 'product12', + 'jsonid' => '0001', + 'type' => 'donut', + 'batters' => ['batter' => [ + [ "id" => "1001", "type" => "Regular", "quantity" => 5], + [ "id" => "1002", "type" => "Chocolate", "quantity" => 3.2], + [ "id" => "1003", "type" => "Blueberry", "quantity" => 0.89], + [ "id" => "1004", "type" => "Devil's Food", "quantity" => 3223432234423321], + ] + ], + "topping" => + [ + [ "id" => "5001", "type" => "None"], + [ "id" => "5002", "type" => "Glazed"], + [ "id" => "5005", "type" => "Sugar"], + [ "id" => "5007", "type" => "Powdered Sugar"], + [ "id" => "5006", "type" => "Chocolate with Sprinkles"], + [ "id" => "5003", "type" => "Chocolate"], + [ "id" => "5004", "type" => "Maple"] + ] + ]; + //print_r($product->batters->batter); + $this->assertArraySubset($expect, $product->toArray(), false); + } + + public function testComplexJsonArray() + { + $this->markTestIncomplete($message = 'not ready yet'); + } + + public function dataProviderTestMariaArrayEncoding() + { + $tests = [ + ['one', [1]], + // [[1]], failure point + ['keymepleae', ['x' => 'asd']], + [['x' => "asd\xC1\xC2\xC3asd"]], + [["asd\xC1\xC2\xC3asd" => 'qwert']], + [["string_keys_only_in_json", "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true]], + [[[[1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true]]]], + [[1, [2, [3, [4, [1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true]]]]]], + [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true], + 3, + 'four' => true, + ], + [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true], + 3, + 'four' => true, + ], + 3, + 'four' => true, + ], + [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [ + 1, + "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", + "_x\xE1" => [1, "asd\xC1\xC2\xC3asd" => "qwert\xD1\xD2\xD3", 3, 'four' => true], + 3, + 'four' => true, + ], + 3, + "asd\xC1\xC2\xC3asd" => false, + ], + 3, + "qwert\xD1\xD2\xD3" => self::BINARY_STRING, + ], + 3, + "_x\xE1" => false, + ], + ]; + + return array_merge($tests); + } + + public function dataProviderTestWriteRead() + { + $data = [ + ['int', 1234], + ['neg', -4321], + ['octal', 076543], //this will become integer + ['hex', 0xbada55], // this will become text + ['largeint', 2147483647], + ['largerin', 9223372036854775807], + ['neglargein', -2147483648], + ['neglargerin', -9223372036854775807], + ['float', 1.1234], + ['morefloat', 1.123456789012345], + ['evenmorefloat', 1.123456789012345678901234567890], + // https://mariadb.atlassian.net/browse/MDEV-8521 + // ['bigfloat', 1.123456789012345e+300], + // ['bignegfloat', -1.123456789012345e+300], + ['string1', 'this is a simple string'], + ['string2', 'string with a \\ backslash in it'], +//this is not accepted in json ['string3', 'string with a \' quote char in it'], + ['string4', 'string with a \" doublequote char in it'], + ['string5', 'string with a / slash in it'], + ['string5', "string with a \n newline in it"], + ['string5', "string with a \r return in it"], + ['string5', "string with a \t tab in it"], + ['string5', "string with a \v vertical tab in it"], + ['string5', "string with a \e escape in it"], + ['string5', "string with a \f form feed in it"], + [ + 'newlines', + 'You can also have embedded newlines in + strings this way as it is + okay to do' + ], + ['fakeoctet', BaseEncoder::DATA_URI_PREFIX . 'This is my string'], + ['octet', BaseEncoder::DATA_URI_PREFIX . base64_encode('This is my string')], + ]; + + //$data = array_merge($data, include(__DIR__ . '/unicodeStrings.php')); + + $data[] = ['binarystring', self::BINARY_STRING]; +//--- the code bellow fails lines 220-222 + + foreach ($this->dataProviderTestMariaArrayEncoding() as $i => $array) { + $data[] = ['array' . $i, $array]; + } + + return $data; + } + + /** + * @dataProvider dataProviderTestWriteRead + * + * @param string $name + * @param mixed $value + */ + public function testWriteRead($name, $value) + { + self::$resetFixture = false; + $product = new Product(); + /** @var string $product->$name */ + $product->$name = $value; + + $product->save(false); + $id = $product->primaryKey; + unset($product); + + $product = Product::findOne($id); + + $this->assertEquals( + $value, $product->$name, 'data name: ' . $name, is_float($value) ? abs($value) / 10e+12 : 0 + ); + unset($product); + } + + public function testDynamicValueObects() + { + $expected = [ + 'str' => 'str', + 'char' => 'char', + 'date' => '1999-12-31', + 'datetime' => '1999-12-31 23:59:59', + 'datetimeN' => '1999-12-31 23:59:59.999999', + 'time' => '12:30:00', + 'timeD' => '12:30:00.123456', + 'int' => 432, + 'integer' => 432, + 'unsignedInt' => 321, + 'float' => 12.99, + 'double' => 9.8989894384938E+16, //see https://www.postgresql.org/docs/9.4/static/datatype-json.html section 8.14.1 + 'decimal' => 12.99, + 'decimalN' => 12.99, + 'decimalND' => 12.99, + ]; + + $p = new Product([ + 'str' => 'str', + 'char' => 'char', + 'date' => '1999-12-31', + 'datetime' => '1999-12-31 23:59:59', + 'datetimeN' => '1999-12-31 23:59:59.999999', + 'time' => '12:30:00', + 'timeD' => '12:30:00.123456', + 'int' => 432, + 'integer' => 432, + 'unsignedInt' => 321, + 'float' => 12.99, + 'double' => 98989894384938492, + 'decimal' => 12.99, + 'decimalN' => 12.99, + 'decimalND' => 12.99, +// https://mariadb.atlassian.net/browse/MDEV-8526 +// 'charN' => new ValueExpression("'charN'", 'CHAR(10)'), +// 'bin' => new ValueExpression('unhex("cafebabebada55")', 'BINARY'), +// 'binN' => new ValueExpression('unhex("cafebabebada55")', 'BINARY(10)'), +// 'doubleN' => new ValueExpression(12.99E+30, 'DOUBLE(6)'), +// 'doubleND' => new ValueExpression(12.99E+30, 'DOUBLE(6,3)'), +// 'signed' => new ValueExpression(-432, 'SIGNED'), +// 'signedInt' => new ValueExpression(-432, 'SIGNED INTEGER'), +// 'unsigned' => new ValueExpression(321, 'UNSIGNED'), + ]); + $p->save(false); + + $actual = Product::findOne($p->id)->toArray(); + $this->assertArraySubset($expected, $actual, false); + } + + public function testDotAttributes() + { + /** @var Product $p */ + $p = Product::findOne(1); + $this->markTestIncomplete('need to write assertions'); + } + + public function testCustomColumns() + { + parent::testCustomColumns(); + + // find custom column + $customer = Product::find()->select(['*', '((!children.int|numeric!) *2) AS [[customColumn]]']) + ->where(['name' => 'product1'])->one(); + $this->assertEquals(1, $customer->id); + $this->assertEquals(246, $customer->customColumn); + } + + public function testCustomColumnsExpression() + { + // find custom column + $customer = Product::find() + ->select(['*', '(' . Product::columnExpression('children.int|numeric') . ' *2) AS [[customColumn]]']) + ->where(['name' => 'product1']) + ->one(); + $this->assertEquals(1, $customer->id); + $this->assertEquals(246, $customer->customColumn); + } + + public function testStatisticalFind() + { + parent::testStatisticalFind(); + + $this->assertEquals(2, Product::find()->where('(!int|numeric!) = 123 OR (!int|numeric!) = 456')->count()); + $this->assertEquals(123, Product::find()->min('(!int|numeric!)')); + $this->assertEquals(1234, Product::find()->max('(!int|numeric!)')); + $this->assertEquals(651.25, Product::find()->average('(!int|numeric!)')); + } + + public function testFindScalar() + { + parent::testFindScalar(); + + // query scalar + $val = Product::find()->where(['id' => 1])->select(['(!children.str!)'])->scalar(); + $this->assertEquals('value1', $val); + + $val = Product::find()->where(['id' => 1])->select(['(!children.bool|boolean!)'])->scalar(); + $this->assertEquals(1, $val); //'true' either that or expect true/1 compared with json_encode ($val) + + $val = Product::find()->where(['id' => 1])->select(['(!children.null!)'])->scalar(); + $this->assertNull($val); + } + + public function testFindColumn() + { + parent::testFindColumn(); + + $this->assertEquals([123, 456, 792, 1234], Product::find()->select(['(!int|numeric!)'])->column()); + $this->assertEquals([1234, 792, 456, 123], Product::find()->orderBy(['(!int|numeric!)' => SORT_DESC])->select(['(!int|numeric!)']) + ->column()); + } + + public function testFindBySql() + { + parent::testFindBySql(); + + // find with parameter binding + $product = Product::findBySql( + 'SELECT *, "dynamic_columns" AS dynamic_columns + FROM product WHERE (! children.str|text !)=:v', [':v' => 'value1']) //when querying pg we should json_encode or double quote the string + ->one(); + $this->assertTrue($product instanceof Product); + $this->assertEquals('product1', $product->name); + $this->assertEquals('value1', $product->children['str']); + } + + public function testFind() + { + parent::testFind(); + //every string that gets searched against the db in jsonb column has to be either '"double quoted"', or json_encoded + // same goes for strings that get returned from the db, they have to be json_decoded + // find by column values + $product = Product::findOne(['id' => 1, '(!str|char!)' => 'value1']); + $this->assertTrue($product instanceof Product); + $this->assertEquals('value1', $product->str); + $product = Product::findOne(['id' => 1, '(!str!)' => 'value2']); + $this->assertNull($product); + $product = Product::findOne(['(!children.str!)' => 'value5']); + $this->assertNull($product); + + // find by attributes + $product = Product::find()->where(['(!children.str!)' => 'value1'])->one(); + $this->assertTrue($product instanceof Product); + $this->assertEquals('value1', $product->children['str']); + $this->assertEquals(1, $product->id); + } + + public function testFindAsArray() + { //----- parent test fails have to reasearch reasons, asArray does not decode json + // parent::testFindAsArray(); + // asArray + $product = Product::find()->where(['id' => 2])->asArray()->one(); + // print_r($product); + $this->assertEquals([ + 'id' => 2, + 'name' => 'product2', + Product::dynamicColumn() => ['int' => 456], //this returns json '{"int": 456} + ], $product); + // print_r($product); + // find all asArray + $products = Product::find()->asArray()->all(); + $this->assertEquals(3, count($products)); + + $this->assertArrayHasKey('id', $products[0]); + $this->assertArrayHasKey('name', $products[0]); + $this->assertArrayHasKey('dynamic_columns', $products[2]); + + $this->assertArrayHasKey('id', $products[1]); + $this->assertArrayHasKey('name', $products[1]); + $this->assertArrayHasKey('dynamic_columns', $products[2]); + + $this->assertArrayHasKey('id', $products[2]); + $this->assertArrayHasKey('name', $products[2]); + $this->assertArrayHasKey('dynamic_columns', $products[2]); + } + + public function testFindIndexBy() + { + parent::testFindIndexBy(); + + // indexBy + $products = Product::find()->indexBy('int')->orderBy('id')->all(); + $this->assertEquals(4, count($products)); + $this->assertTrue($products['123'] instanceof Product); + $this->assertTrue($products['456'] instanceof Product); + $this->assertTrue($products['792'] instanceof Product); + + // indexBy callable + $products = Product::find()->indexBy(function ($product) { + return $product->id . '-' . $product->int; + })->orderBy('id')->all(); + $this->assertEquals(4, count($products)); + $this->assertTrue($products['1-123'] instanceof Product); + $this->assertTrue($products['2-456'] instanceof Product); + $this->assertTrue($products['3-792'] instanceof Product); + } + + public function testFindIndexByAsArray() + { + parent::testFindIndexByAsArray(); + + // indexBy + asArray + $products = Product::find()->asArray()->indexBy('int')->all(); + $this->assertEquals(4, count($products)); + $this->assertArrayHasKey('id', $products['123']); + $this->assertArrayHasKey('name', $products['123']); + $this->assertArrayHasKey('dynamic_columns', $products['123']); + + $this->assertArrayHasKey('id', $products['456']); + $this->assertArrayHasKey('name', $products['456']); + $this->assertArrayHasKey('dynamic_columns', $products['456']); + + $this->assertArrayHasKey('id', $products['792']); + $this->assertArrayHasKey('name', $products['792']); + $this->assertArrayHasKey('dynamic_columns', $products['792']); + + // indexBy + asArray + not existed nested column + $products = Product::find()->asArray()->indexBy('children.str')->all(); + $this->assertEquals(4, count($products)); + $this->assertArrayHasKey('id', $products['value1']); + $this->assertArrayHasKey('name', $products['value1']); + $this->assertArrayHasKey('dynamic_columns', $products['value1']); + + // column missing - pk should be used + $this->assertArrayHasKey('id', $products['']); + $this->assertArrayHasKey('name', $products['']); + $this->assertArrayHasKey('dynamic_columns', $products['']); + + $this->assertArrayHasKey('id', $products['value3']); + $this->assertArrayHasKey('name', $products['value3']); + $this->assertArrayHasKey('dynamic_columns', $products['value3']); + } + + public function testRefresh() + { + parent::testRefresh(); + + $product = Product::findOne(1); + $product->str = 'to be refreshed'; + $this->assertTrue($product->refresh()); + $this->assertEquals('value1', $product->str); + + $product = Product::findOne(1); + $product->children = ['str' => 'to be refreshed']; + $this->assertTrue($product->refresh()); + $this->assertEquals('value1', $product->children['str']); + } + + public function testEquals() + { + parent::testEquals(); + + $productA = new Product(); + $productB = new Product(); + $this->assertFalse($productA->equals($productB)); + + $productA = Product::findOne(1); + $productB = Product::findOne(2); + $this->assertFalse($productA->equals($productB)); + + $productB = Product::findOne(1); + $this->assertTrue($productA->equals($productB)); + } + + public function testFindCount() + { + parent::testFindCount(); + + $this->assertEquals(4, Product::find()->count()); + + $this->assertEquals(1, Product::find()->where(['(!int|numeric!)' => 123])->count()); + $this->assertEquals(2, Product::find()->where(['(!int|numeric!)' => [123, 456]])->count()); + $this->assertEquals(2, Product::find()->where(['(!int|numeric!)' => [123, 456]])->offset(1)->count()); + $this->assertEquals(2, Product::find()->where(['(!int|numeric!)' => [123, 456]])->offset(2)->count()); + } + + public function testFindComplexCondition() + { + parent::testFindComplexCondition(); + + $this->assertEquals(2, Product::find()->where(['OR', ['(!int|numeric!)' => 123], ['(!int|numeric!)' => 456]])->count()); + $this->assertEquals(2, count(Product::find()->where(['OR', ['(!int|numeric!)' => 123], ['(!int|numeric!)' => 456]])->all())); + + $this->assertEquals(2, Product::find()->where(['(!children.str!)' => ['value1', 'value3']])->count()); + $this->assertEquals(2, count(Product::find()->where(['(!children.str!)' => ['value1', 'value3']])->all())); + + $this->assertEquals(1, Product::find()->where([ + 'AND', + ['(!children.str!)' => ['value1', 'value3']], + ['BETWEEN', '(!int|numeric!)', 122, 124] + ])->count()); + $this->assertEquals(1, count(Product::find()->where([ + 'AND', + ['(!children.str!)' => ['value1', 'value3']], + ['BETWEEN', '(!int|numeric!)', 122, 124] + ])->all())); + } + + public function testFindNullValues() + { + parent::testFindNullValues(); + + $product = Product::findOne(2); + $product->int = null; + $product->save(false); + + $result = Product::find()->where(['(!int!)' => null])->all(); //or we can check against json null which is 'null' + $this->assertEquals(1, count($result)); + $this->assertEquals(2, reset($result)->primaryKey); + } + + public function testExists() + { + parent::testExists(); + + $this->assertTrue(Product::find()->where(['(!children.int|numeric!)' => 123])->exists()); + $this->assertFalse(Product::find()->where(['(!int|numeric!)' => 555])->exists()); + $this->assertTrue(Product::find()->where(['(!children.str!)' => 'value3'])->exists()); + $this->assertFalse(Product::find()->where(['(!children.str!)' => 123])->exists()); + } + +//the above throws sql exception if not quoted, I think this is normal + + public function testFindLazy() + { + parent::testFindLazy(); + + $product = Product::findOne(1); + $this->assertFalse($product->isRelationPopulated('supplier')); + $supplier = $product->supplier; + $this->assertTrue($product->isRelationPopulated('supplier')); + $this->assertEquals(1, $supplier->primaryKey); + + $product = Product::findOne(1); + $this->assertFalse($product->isRelationPopulated('supplier')); + $suppliers = $product->getSupplier()->all(); + $this->assertFalse($product->isRelationPopulated('supplier')); + $this->assertEquals(0, count($product->relatedRecords)); + + $this->assertEquals(1, count($suppliers)); + $this->assertEquals(1, $suppliers[0]->id); + } + + public function testFindEager() + { + parent::testFindEager(); + + $products = Product::find()->with('supplier')->all(); + $this->assertEquals(4, count($products)); + $this->assertTrue($products[0]->isRelationPopulated('supplier')); + $this->assertTrue($products[1]->isRelationPopulated('supplier')); + $this->assertTrue($products[2]->isRelationPopulated('supplier')); + $this->assertEquals(1, count($products[0]->supplier)); + $this->assertEquals(0, count($products[1]->supplier)); + $this->assertEquals(0, count($products[2]->supplier)); + } + + public function testRelationsWhereDynamicColumnMissing() + { + $product = Product::findOne(1); + $this->assertNotNull($product->getSupplier()); + + // product without supplier_id dynamic column + $product = Product::findOne(2); + $this->assertNull($product->getSupplier()->one()); + } + + public function testInsert() + { + parent::testInsert(); + + $product = new Product(); + $product->name = 'test'; + $product->str = 'value test'; + $product->children = [ + 'string1' => 'children string', + 'integer' => 1234, + ]; + + $this->assertNull($product->id); + $this->assertTrue($product->isNewRecord); + + $this->assertTrue($product->save()); + + $this->assertNotNull($product->id); + $this->assertFalse($product->isNewRecord); + + $this->assertEquals('test', $product->name); + $this->assertEquals('value test', $product->str); + $this->assertEquals([ + 'string1' => 'children string', + 'integer' => 1234, + ], $product->children); + } + + public function testUpdate() + { + parent::testUpdate(); + + $product = Product::findOne(1); + $this->assertTrue($product instanceof Product); + $this->assertEquals('123', $product->int); + $this->assertFalse($product->isNewRecord); + $this->assertEmpty($product->dirtyAttributes); + + $product->int = 567; + $product->save(); + $this->assertEquals('567', $product->int); + $product2 = Product::findOne(1); + $this->assertEquals('567', $product2->int); + + // updateAll + // todo need to create new DynamicQueryBuilder to override update() +// $product = Product::findOne(3); +// $this->assertEquals('value3', $product->children['str']); +// $ret = Product::updateAll(['(!children.str!)' => 'temp'], ['id' => 3]); +// $this->assertEquals(1, $ret); +// $product = Product::findOne(3); +// $this->assertEquals('temp', $product->children['str']); +// +// $ret = Product::updateAll(['(!children.str!)' => 'tempX']); +// $this->assertEquals(3, $ret); +// +// $ret = Product::updateAll(['(!children.str!)' => 'tempp'], ['name' => 'product6']); +// $this->assertEquals(0, $ret); + } + + public function testUpdateAttributes() + { + parent::testUpdateAttributes(); + + $product = Product::findOne(2); + $this->assertTrue($product instanceof Product); + $this->assertEquals(456, $product->int); + $this->assertFalse($product->isNewRecord); + +// $product->updateAttributes(['(!int!)' => 777]); +// $this->assertEquals(777, $product->int); +// $this->assertFalse($product->isNewRecord); +// $product2 = Product::findOne(2); +// $this->assertEquals(777, $product2->int); +// $this->assertInternalType('integer', $product2->int); +// +// // update not eisting dynamic attribute +// $product = Product::findOne(3); +// $product->updateAttributes(['(!custom!)' => 'value']); +// $this->assertEquals('value', $product->custom); +// $this->assertFalse($product->isNewRecord); +// $product2 = Product::findOne(3); +// $this->assertEquals('value', $product2->custom); + } + + /** + * Some PDO implementations(e.g. cubrid) do not support boolean values. + * Make sure this does not affect AR layer. + */ + public function testBooleanAttribute() + { + parent::testBooleanAttribute(); + + $product = new Product(); + $product->name = 'boolean customer'; + $product->boolean_dynamic = true; + $product->save(false); + + $product->refresh(); + $this->assertEquals('true', $product->boolean_dynamic); + + $product->boolean_dynamic = false; + $product->save(false); + + $product->refresh(); + $this->assertEquals('false', $product->boolean_dynamic); + + $products = Product::find()->where(['(!boolean_dynamic!)' => false])->all(); + $this->assertEquals(1, count($products)); + } + + public function testFindEmptyInCondition() + { + parent::testFindEmptyInCondition(); + + $products = Product::find()->where(['(!int!)' => [123]])->all(); + $this->assertEquals(1, count($products)); + + $products = Product::find()->where(['(!int!)' => []])->all(); + $this->assertEquals(0, count($products)); + + $products = Product::find()->where(['IN', '(!int!)', [123]])->all(); + $this->assertEquals(1, count($products)); + + $products = Product::find()->where(['IN', '(!int!)', []])->all(); + $this->assertEquals(0, count($products)); + } +} diff --git a/tests/unit/data/config.php b/tests/unit/data/config.php index 4d667ea..9a99084 100644 --- a/tests/unit/data/config.php +++ b/tests/unit/data/config.php @@ -38,10 +38,10 @@ // 'fixture' => __DIR__ . '/mssql.sql', // ], 'pgsql' => [ - 'dsn' => 'pgsql:host=localhost;dbname=yiitest;port=5432;', + 'dsn' => 'pgsql:host=localhost;dbname=myyiitest;port=5432;', 'username' => 'postgres', - 'password' => 'postgres', - 'fixture' => __DIR__ . '/pgsql.sql', + 'password' => '#postgres#', + 'fixture' => __DIR__ . '/postgres.sql', ], ], ]; diff --git a/tests/unit/data/postgres.sql b/tests/unit/data/postgres.sql new file mode 100644 index 0000000..d084274 --- /dev/null +++ b/tests/unit/data/postgres.sql @@ -0,0 +1,395 @@ +/** + * This is the database schema for testing PostgreSQL support of yii Active Record. + * To test this feature, you need to create a database named 'yiitest' on 'localhost' + * and create an account 'postgres/postgres' which owns this test database. + */ + +DROP TABLE IF EXISTS "composite_fk" CASCADE; +DROP TABLE IF EXISTS "order_item" CASCADE; +DROP TABLE IF EXISTS "item" CASCADE; +DROP TABLE IF EXISTS "order_item_with_null_fk" CASCADE; +DROP TABLE IF EXISTS "order" CASCADE; +DROP TABLE IF EXISTS "order_with_null_fk" CASCADE; +DROP TABLE IF EXISTS "category" CASCADE; +DROP TABLE IF EXISTS "customer" CASCADE; +DROP TABLE IF EXISTS "profile" CASCADE; +DROP TABLE IF EXISTS "type" CASCADE; +DROP TABLE IF EXISTS "null_values" CASCADE; +DROP TABLE IF EXISTS "negative_default_values" CASCADE; +DROP TABLE IF EXISTS "constraints" CASCADE; +DROP TABLE IF EXISTS "bool_values" CASCADE; +DROP TABLE IF EXISTS "animal" CASCADE; +DROP TABLE IF EXISTS "default_pk" CASCADE; +DROP TABLE IF EXISTS "document" CASCADE; +DROP TABLE IF EXISTS "comment" CASCADE; +DROP VIEW IF EXISTS "animal_view"; +DROP SCHEMA IF EXISTS "schema1" CASCADE; +DROP SCHEMA IF EXISTS "schema2" CASCADE; + +CREATE SCHEMA "schema1"; +CREATE SCHEMA "schema2"; + +CREATE TABLE "constraints" +( + id integer not null, + field1 varchar(255) +); + +CREATE TABLE "profile" ( + id serial not null primary key, + description varchar(128) NOT NULL +); + +CREATE TABLE "schema1"."profile" ( + id serial not null primary key, + description varchar(128) NOT NULL +); + +CREATE TABLE "customer" ( + id serial not null primary key, + email varchar(128) NOT NULL, + name varchar(128), + address text, + status integer DEFAULT 0, + bool_status boolean DEFAULT FALSE, + profile_id integer +); + +comment on column public.customer.email is 'someone@example.com'; + +CREATE TABLE "category" ( + id serial not null primary key, + name varchar(128) NOT NULL +); + +CREATE TABLE "item" ( + id serial not null primary key, + name varchar(128) NOT NULL, + category_id integer NOT NULL references "category"(id) on UPDATE CASCADE on DELETE CASCADE +); + +CREATE TABLE "order" ( + id serial not null primary key, + customer_id integer NOT NULL references "customer"(id) on UPDATE CASCADE on DELETE CASCADE, + created_at integer NOT NULL, + total decimal(10,0) NOT NULL +); + +CREATE TABLE "order_with_null_fk" ( + id serial not null primary key, + customer_id integer, + created_at integer NOT NULL, + total decimal(10,0) NOT NULL +); + +CREATE TABLE "order_item" ( + order_id integer NOT NULL references "order"(id) on UPDATE CASCADE on DELETE CASCADE, + item_id integer NOT NULL references "item"(id) on UPDATE CASCADE on DELETE CASCADE, + quantity integer NOT NULL, + subtotal decimal(10,0) NOT NULL, + PRIMARY KEY (order_id,item_id) +); + +CREATE TABLE "order_item_with_null_fk" ( + order_id integer, + item_id integer, + quantity integer NOT NULL, + subtotal decimal(10,0) NOT NULL +); + +CREATE TABLE "composite_fk" ( + id integer NOT NULL, + order_id integer NOT NULL, + item_id integer NOT NULL, + PRIMARY KEY (id), + CONSTRAINT FK_composite_fk_order_item FOREIGN KEY (order_id, item_id) REFERENCES "order_item" (order_id, item_id) ON DELETE CASCADE +); + +CREATE TABLE "null_values" ( + id serial NOT NULL, + var1 INT NULL, + var2 INT NULL, + var3 INT DEFAULT NULL, + stringcol VARCHAR(32) DEFAULT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE "type" ( + int_col integer NOT NULL, + int_col2 integer DEFAULT '1', + smallint_col smallint DEFAULT '1', + char_col char(100) NOT NULL, + char_col2 varchar(100) DEFAULT 'something', + char_col3 text, + float_col double precision NOT NULL, + float_col2 double precision DEFAULT '1.23', + blob_col bytea, + numeric_col decimal(5,2) DEFAULT '33.22', + time timestamp NOT NULL DEFAULT '2002-01-01 00:00:00', + bool_col boolean NOT NULL, + bool_col2 boolean DEFAULT TRUE, + ts_default TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + bit_col BIT(8) NOT NULL DEFAULT B'10000010', + bigint_col BIGINT +); + +CREATE TABLE "bool_values" ( + id serial not null primary key, + bool_col bool, + default_true bool not null default true, + default_false boolean not null default false +); + +CREATE TABLE "negative_default_values" ( + smallint_col smallint default '-123', + int_col integer default '-123', + bigint_col bigint default '-123', + float_col double precision default '-12345.6789', + numeric_col decimal(5,2) default '-33.22' +); + +CREATE TABLE "animal" ( + id serial primary key, + type varchar(255) not null +); + +CREATE TABLE "default_pk" ( + id integer not null default 5 primary key, + type varchar(255) not null +); + +CREATE TABLE "document" ( + id serial primary key, + title varchar(255) not null, + content text not null, + version integer not null default 0 +); + +CREATE TABLE "comment" ( + id serial primary key, + name varchar(255) not null, + message text not null +); + +CREATE VIEW "animal_view" AS SELECT * FROM "animal"; + +INSERT INTO "animal" (type) VALUES ('yiiunit\data\ar\Cat'); +INSERT INTO "animal" (type) VALUES ('yiiunit\data\ar\Dog'); + + +INSERT INTO "profile" (description) VALUES ('profile customer 1'); +INSERT INTO "profile" (description) VALUES ('profile customer 3'); + +INSERT INTO "schema1"."profile" (description) VALUES ('profile customer 1'); +INSERT INTO "schema1"."profile" (description) VALUES ('profile customer 3'); + +INSERT INTO "customer" (email, name, address, status, bool_status, profile_id) VALUES ('user1@example.com', 'user1', 'address1', 1, true, 1); +INSERT INTO "customer" (email, name, address, status, bool_status) VALUES ('user2@example.com', 'user2', 'address2', 1, true); +INSERT INTO "customer" (email, name, address, status, bool_status, profile_id) VALUES ('user3@example.com', 'user3', 'address3', 2, false, 2); + +INSERT INTO "category" (name) VALUES ('Books'); +INSERT INTO "category" (name) VALUES ('Movies'); + +INSERT INTO "item" (name, category_id) VALUES ('Agile Web Application Development with Yii1.1 and PHP5', 1); +INSERT INTO "item" (name, category_id) VALUES ('Yii 1.1 Application Development Cookbook', 1); +INSERT INTO "item" (name, category_id) VALUES ('Ice Age', 2); +INSERT INTO "item" (name, category_id) VALUES ('Toy Story', 2); +INSERT INTO "item" (name, category_id) VALUES ('Cars', 2); + +INSERT INTO "order" (customer_id, created_at, total) VALUES (1, 1325282384, 110.0); +INSERT INTO "order" (customer_id, created_at, total) VALUES (2, 1325334482, 33.0); +INSERT INTO "order" (customer_id, created_at, total) VALUES (2, 1325502201, 40.0); + +INSERT INTO "order_with_null_fk" (customer_id, created_at, total) VALUES (1, 1325282384, 110.0); +INSERT INTO "order_with_null_fk" (customer_id, created_at, total) VALUES (2, 1325334482, 33.0); +INSERT INTO "order_with_null_fk" (customer_id, created_at, total) VALUES (2, 1325502201, 40.0); + +INSERT INTO "order_item" (order_id, item_id, quantity, subtotal) VALUES (1, 1, 1, 30.0); +INSERT INTO "order_item" (order_id, item_id, quantity, subtotal) VALUES (1, 2, 2, 40.0); +INSERT INTO "order_item" (order_id, item_id, quantity, subtotal) VALUES (2, 4, 1, 10.0); +INSERT INTO "order_item" (order_id, item_id, quantity, subtotal) VALUES (2, 5, 1, 15.0); +INSERT INTO "order_item" (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0); +INSERT INTO "order_item" (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0); + +INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (1, 1, 1, 30.0); +INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (1, 2, 2, 40.0); +INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 4, 1, 10.0); +INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 5, 1, 15.0); +INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (2, 3, 1, 8.0); +INSERT INTO "order_item_with_null_fk" (order_id, item_id, quantity, subtotal) VALUES (3, 2, 1, 40.0); + +INSERT INTO "document" (title, content, version) VALUES ('Yii 2.0 guide', 'This is Yii 2.0 guide', 0); + +/** + * (Postgres-)Database Schema for validator tests + */ + +DROP TABLE IF EXISTS "validator_main" CASCADE; +DROP TABLE IF EXISTS "validator_ref" CASCADE; + +CREATE TABLE "validator_main" ( + id integer not null primary key, + field1 VARCHAR(255) +); + +CREATE TABLE "validator_ref" ( + id integer not null primary key, + a_field VARCHAR(255), + ref integer +); + +INSERT INTO "validator_main" (id, field1) VALUES (1, 'just a string1'); +INSERT INTO "validator_main" (id, field1) VALUES (2, 'just a string2'); +INSERT INTO "validator_main" (id, field1) VALUES (3, 'just a string3'); +INSERT INTO "validator_main" (id, field1) VALUES (4, 'just a string4'); +INSERT INTO "validator_ref" (id, a_field, ref) VALUES (1, 'ref_to_2', 2); +INSERT INTO "validator_ref" (id, a_field, ref) VALUES (2, 'ref_to_2', 2); +INSERT INTO "validator_ref" (id, a_field, ref) VALUES (3, 'ref_to_3', 3); +INSERT INTO "validator_ref" (id, a_field, ref) VALUES (4, 'ref_to_4', 4); +INSERT INTO "validator_ref" (id, a_field, ref) VALUES (5, 'ref_to_4', 4); +INSERT INTO "validator_ref" (id, a_field, ref) VALUES (6, 'ref_to_5', 5); + +/* bit test, see https://github.com/yiisoft/yii2/issues/9006 */ + +DROP TABLE IF EXISTS "bit_values" CASCADE; + +CREATE TABLE "bit_values" ( + id serial not null primary key, + val bit(1) not null +); + +INSERT INTO "bit_values" (id, val) VALUES (1, '0'), (2, '1'); +-- new rows for dynamic columns testing +DROP TABLE IF EXISTS "product" CASCADE; +DROP TABLE IF EXISTS "supplier" CASCADE; +DROP TABLE IF EXISTS "missing_dyn_column" CASCADE; + +CREATE TABLE "product" ( + "id" serial, + "name" VARCHAR(128), + "dynamic_columns" jsonb, + PRIMARY KEY ("id") +); + +CREATE TABLE "supplier" ( + "id" serial, + "name" VARCHAR(128), + "dynamic_columns" jsonb, + PRIMARY KEY ("id") +); + +CREATE TABLE "missing_dyn_column" ( + "id" serial, + "name" VARCHAR(128), + PRIMARY KEY ("id") +); + +INSERT INTO "product" (name, dynamic_columns) VALUES ( + 'product1', + '{ + "supplier_id": 1, + "str": "value1", + "int": 123, + "float": 123.456, + "bool": true, + "null": null, + "children": { + "str": "value1", + "int": 123, + "float": 123.456, + "bool": true, + "null": null + } + }'::jsonb); + +INSERT INTO "product" (name, dynamic_columns) VALUES ( + 'product2', + '{"int":456}'::jsonb); + +INSERT INTO "product" (name, dynamic_columns) VALUES ( + 'product3', + '{ + "int": 792, + "children": { + "str": "value3" + } + }'::jsonb); + +INSERT INTO "product" (id, name, dynamic_columns) VALUES ( + 11, + 'product11', + '{ + "supplier_id": 1, + "str": "value11", + "int": 1234, + "float": 123.456, + "bool": true, + "null": null, + "json_array": [123, "string 1", true], + "children": { + "str": "value11", + "int": 123, + "float": 123.456, + "bool": true, + "null": null + } + }'::jsonb); + +INSERT INTO "product" (id, name, dynamic_columns) VALUES ( + 12, + 'product12', + '{ + "jsonid": "0001", + "type": "donut", + "name": "Cake", + "ppu": 0.55, + "batters": + { + "batter": + [ + { "id": "1001", "type": "Regular", "quantity":5 }, + { "id": "1002", "type": "Chocolate", "quantity":3.2 }, + { "id": "1003", "type": "Blueberry", "quantity":0.89 }, + { "id": "1004", "type": "Devil''s Food","quantity":3223432234423321 } + ] + }, + "topping": + [ + { "id": "5001", "type": "None" }, + { "id": "5002", "type": "Glazed" }, + { "id": "5005", "type": "Sugar" }, + { "id": "5007", "type": "Powdered Sugar" }, + { "id": "5006", "type": "Chocolate with Sprinkles" }, + { "id": "5003", "type": "Chocolate" }, + { "id": "5004", "type": "Maple" } + ] + + + }'::jsonb); + +INSERT INTO "supplier" (name, dynamic_columns) VALUES ( + 'One', + '{ + "address": { + "line1": "Hoffmannstr. 51", + "line2": "D81379 München", + "country": "de" + } + }'::jsonb), ( + 'Two', + '{ + "address": { + "line1": "100 Foo St.", + "city": "Barton", + "state": "VT", + "country": "us" + } + }'::jsonb); + +INSERT INTO "supplier" (name, dynamic_columns) VALUES ( + 'three', + '{ + "address": { + "country": "england" + } + }'::jsonb); \ No newline at end of file