diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..82082eb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: php +php: + - '7.1' + - '7.2' +before_script: + - travis_retry composer self-update + - travis_retry composer install --no-interaction --prefer-source --dev + +script: + - vendor/bin/phpunit --coverage-clover=coverage.xml + - vendor/bin/phpcs -p --standard=PSR2 src/ + +after_success: + - travis_retry bash <(curl -s https://codecov.io/bash) diff --git a/README.md b/README.md index 900722b..4a4b36e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ Presto Query Builder =================== +This package provides a set of classes and methods that is able to programmatically build presto queries. + +[![Latest Stable Version](https://poser.pugx.org/moitran/package-presto-query-builder-php/v/stable)](https://packagist.org/packages/moitran/package-presto-query-builder-php) +[![Latest Unstable Version](https://poser.pugx.org/moitran/package-presto-query-builder-php/v/unstable)](https://packagist.org/packages/moitran/package-presto-query-builder-php) +[![Build Status](https://travis-ci.org/moitran/package-presto-query-builder-php.svg?branch=master)](https://travis-ci.org/moitran/package-presto-query-builder-php) +[![codecov](https://codecov.io/gh/moitran/package-presto-query-builder-php/branch/master/graphs/badge.svg)](https://codecov.io/gh/moitran/package-presto-query-builder-php) +[![License](https://poser.pugx.org/moitran/package-presto-query-builder-php/license)](https://packagist.org/packages/moitran/package-presto-query-builder-php) +[![composer.lock](https://poser.pugx.org/moitran/package-presto-query-builder-php/composerlock)](https://packagist.org/packages/moitran/package-presto-query-builder-php) + - [Installation](#installation) - [Usage](#usage) - [Testing](#testing) @@ -137,4 +146,4 @@ Contributing License ------- -[MIT](https://github.com/moitran/package-presto-query-builder-php/blob/master/LICENSE) \ No newline at end of file +This package is under [MIT License](https://github.com/moitran/package-presto-query-builder-php/blob/master/LICENSE) \ No newline at end of file diff --git a/composer.json b/composer.json index 638c3c2..0124cee 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "name": "moitran/package-presto-query-builder-php", "description": "Build presto query string", + "type": "package", "license": "MIT", "authors": [ { @@ -12,7 +13,10 @@ "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^7.3" + "phpunit/phpunit": "^7.3", + "symfony/var-dumper": "^4.2", + "phpmd/phpmd": "^2.6", + "squizlabs/php_codesniffer": "^3.3" }, "autoload": { "psr-4": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1414e67..1de3be7 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -5,12 +5,12 @@ verbose="true"> - tests + ./tests - src + ./src/ - \ No newline at end of file + diff --git a/src/Base.php b/src/Base.php index 82ca915..f1bc37f 100644 --- a/src/Base.php +++ b/src/Base.php @@ -59,7 +59,7 @@ private function removeSpecialCharsFromStr($str) $str = str_replace( ['\\', "\0", "\n", "\r", "'", '"', "\x1a"], - ['\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'], + ['\\\\', '\\0', '\\n', '\\r', "''", '\\"', '\\Z'], $str ); diff --git a/src/Query.php b/src/Query.php index fdd03ee..15e42ca 100644 --- a/src/Query.php +++ b/src/Query.php @@ -22,6 +22,10 @@ class Query extends Base * @var bool */ private $isFirstUnionAll = true; + /** + * @var bool + */ + private $isFirstHaving = true; const SORT_DESC = 'DESC'; const SORT_ASC = 'ASC'; @@ -195,8 +199,12 @@ public function whereAndGroup(WhereGroup $whereGroup) { $whereStr = $whereGroup->getWhereConditions(); + if ($whereStr == '') { + return $this; + } + if ($this->isFirstWhere) { - $whereStr = sprintf(' WHERE AND (%s)', $whereStr); + $whereStr = sprintf(' WHERE (%s)', $whereStr); $this->isFirstWhere = false; } else { $whereStr = sprintf(' AND (%s)', $whereStr); @@ -216,8 +224,12 @@ public function whereOrGroup(WhereGroup $whereGroup) { $whereStr = $whereGroup->getWhereConditions(); + if ($whereStr == '') { + return $this; + } + if ($this->isFirstWhere) { - $whereStr = sprintf(' WHERE OR (%s)', $whereStr); + $whereStr = sprintf(' WHERE (%s)', $whereStr); $this->isFirstWhere = false; } else { $whereStr = sprintf(' OR (%s)', $whereStr); @@ -228,6 +240,32 @@ public function whereOrGroup(WhereGroup $whereGroup) return $this; } + /** + * @param $column + * @param $condition + * @param $value + * + * @return $this + * @throws InvalidArgumentException + */ + public function andHaving($column, $condition, $value) + { + return $this->having($column, $condition, $this->removeSpecialChars($value), 'AND'); + } + + /** + * @param $column + * @param $condition + * @param $value + * + * @return $this + * @throws InvalidArgumentException + */ + public function orHaving($column, $condition, $value) + { + return $this->having($column, $condition, $this->removeSpecialChars($value), 'OR'); + } + /** * @param Query $query * @@ -349,6 +387,44 @@ private function where($column, $condition, $value, $whereType) return $this; } + /** + * @param $column + * @param $condition + * @param $value + * @param $havingType + * + * @return $this + * @throws InvalidArgumentException + */ + private function having($column, $condition, $value, $havingType) + { + if (!is_string($column) || !is_string($condition)) { + throw new InvalidArgumentException('$column and $condition argument must be a string'); + } + + if (!(is_string($value) || is_array($value) || is_null($value) || is_numeric($value))) { + throw new InvalidArgumentException('$value argument must be a string, a numeric or an array'); + } + + if (is_null($value)) { + $valueStr = 'NULL'; + } elseif (is_numeric($value)) { + $valueStr = $value; + } else { + $valueStr = is_string($value) ? sprintf("'%s'", $value) : sprintf("('%s')", implode("', '", $value)); + } + + if ($this->isFirstHaving) { + $havingType = 'HAVING'; + $this->isFirstHaving = false; + } + + $havingStr = sprintf(" %s %s %s %s", $havingType, $column, $condition, $valueStr); + $this->combineQueryStr($havingStr); + + return $this; + } + /** * @param $table * @param $alias diff --git a/src/Where.php b/src/Where.php index 9917e65..30d77ab 100644 --- a/src/Where.php +++ b/src/Where.php @@ -66,7 +66,7 @@ private function where($column, $condition, $value, $whereType) } elseif (is_numeric($value)) { $valueStr = $value; } else { - $valueStr = is_string($value) ? sprintf("'%s'", $value) : sprintf("('%s')", implode("','", $value)); + $valueStr = is_string($value) ? sprintf("'%s'", $value) : sprintf("('%s')", implode("', '", $value)); } $whereStr = sprintf(" %s %s %s %s", $whereType, $column, $condition, $valueStr); diff --git a/src/WhereGroup.php b/src/WhereGroup.php index 2513633..7524270 100644 --- a/src/WhereGroup.php +++ b/src/WhereGroup.php @@ -75,6 +75,10 @@ public function whereAndGroup(WhereGroup $whereGroup) { $whereStr = $whereGroup->getWhereConditions(); + if ($whereStr == '') { + return $this; + } + $whereStr = sprintf(' AND (%s)', $whereStr); if ($this->isFirstCondition) { @@ -96,6 +100,10 @@ public function whereOrGroup(WhereGroup $whereGroup) { $whereStr = $whereGroup->getWhereConditions(); + if ($whereStr == '') { + return $this; + } + $whereStr = sprintf(' OR (%s)', $whereStr); if ($this->isFirstCondition) { diff --git a/tests/BaseTest.php b/tests/BaseTest.php index 1dc4c94..f4c61a3 100644 --- a/tests/BaseTest.php +++ b/tests/BaseTest.php @@ -3,6 +3,7 @@ namespace MoiTran\PrestoQueryBuilder\Tests; use MoiTran\PrestoQueryBuilder\Base; +use MoiTran\PrestoQueryBuilder\Tests\Provider\BaseTestProvider; /** * Class BaseTest @@ -10,34 +11,7 @@ */ class BaseTest extends TestCases { - /** - * @return array - */ - public function providerRemoveSpecialChars() - { - return [ - 'numeric' => [ - 'input' => 111, - 'expected' => 111, - ], - 'special-char' => [ - 'input' => '"test"', - 'expected' => '\"test\"', - ], - 'percent-char' => [ - 'input' => '%test%', - 'expected' => '%test%', - ], - 'array-value' => [ - 'input' => [1, '"test"', "\n", "\r", "%test"], - 'expected' => ['1', '\"test\"', '\\n', '\\r', '%test'], - ], - 'not-accept-value-type' => [ - 'input' => new \stdClass(), - 'expected' => new \stdClass(), - ], - ]; - } + use BaseTestProvider; /** * @param $input diff --git a/tests/Provider/BaseTestProvider.php b/tests/Provider/BaseTestProvider.php new file mode 100644 index 0000000..0826225 --- /dev/null +++ b/tests/Provider/BaseTestProvider.php @@ -0,0 +1,39 @@ + [ + 'input' => 111, + 'expected' => 111, + ], + 'special-char' => [ + 'input' => '"test"', + 'expected' => '\"test\"', + ], + 'percent-char' => [ + 'input' => '%test%', + 'expected' => '%test%', + ], + 'array-value' => [ + 'input' => [1, '"test"', "\n", "\r", "%test"], + 'expected' => ['1', '\"test\"', '\\n', '\\r', '%test'], + ], + 'not-accept-value-type' => [ + 'input' => new \stdClass(), + 'expected' => new \stdClass(), + ], + ]; + } +} diff --git a/tests/Provider/QueryTestProvider.php b/tests/Provider/QueryTestProvider.php new file mode 100644 index 0000000..b4d7cf5 --- /dev/null +++ b/tests/Provider/QueryTestProvider.php @@ -0,0 +1,402 @@ + [ + 'select' => new \stdClass(), + 'expected' => '$select argument must be a string or an array', + ], + 'select-all' => [ + 'select' => '*', + 'expected' => 'SELECT *', + ], + 'select-columns' => [ + 'select' => ['query', 'page', 'country', 'device'], + 'expected' => "SELECT query, page, country, device", + ], + 'select-columns-with-alias' => [ + 'select' => [ + 'SUM(clicks)' => 'sumCLicks', + 'SUM(impressions)' => 'sumImpressions', + ], + 'expected' => "SELECT SUM(clicks) as sumCLicks, SUM(impressions) as sumImpressions", + ], + ]; + } + + /** + * @return array + */ + public function providerFrom() + { + return [ + 'in-valid-from' => [ + 'from' => new \stdClass(), + 'alias' => '', + 'expected' => '$from and $alias argument must be a string', + ], + 'in-valid-alias' => [ + 'from' => 'table1', + 'alias' => new \stdClass(), + 'expected' => '$from and $alias argument must be a string', + ], + 'no-alias' => [ + 'from' => 'table1', + 'alias' => '', + 'expected' => ' FROM (table1)', + ], + 'with-alias' => [ + 'from' => 'SELECT * FROM B', + 'alias' => 'a', + 'expected' => ' FROM (SELECT * FROM B) AS a', + ], + ]; + } + + /** + * @return array + */ + public function providerLeftJoin() + { + return [ + 'invalid-table' => [ + 'table' => ['table1'], + 'alias' => '', + 'expected' => '$table and $alias argument must be a string', + ], + 'invalid-alias' => [ + 'table' => 'table1', + 'alias' => ['a'], + 'expected' => '$table and $alias argument must be a string', + ], + 'no-alias' => [ + 'table' => 'table1', + 'alias' => '', + 'expected' => ' LEFT JOIN (table1)', + ], + 'with-alias' => [ + 'table' => 'SELECT * FROM B', + 'alias' => 'b', + 'expected' => ' LEFT JOIN (SELECT * FROM B) AS b', + ], + ]; + } + + /** + * @return array + */ + public function providerRightJoin() + { + return [ + 'invalid-table' => [ + 'table' => ['table1'], + 'alias' => '', + 'expected' => '$table and $alias argument must be a string', + ], + 'invalid-alias' => [ + 'table' => 'table1', + 'alias' => ['a'], + 'expected' => '$table and $alias argument must be a string', + ], + 'no-alias' => [ + 'table' => 'table1', + 'alias' => '', + 'expected' => ' RIGHT JOIN (table1)', + ], + 'with-alias' => [ + 'table' => 'SELECT * FROM B', + 'alias' => 'b', + 'expected' => ' RIGHT JOIN (SELECT * FROM B) AS b', + ], + ]; + } + + /** + * @return array + */ + public function providerInnerJoin() + { + return [ + 'invalid-table' => [ + 'table' => ['table1'], + 'alias' => '', + 'expected' => '$table and $alias argument must be a string', + ], + 'invalid-alias' => [ + 'table' => 'table1', + 'alias' => ['a'], + 'expected' => '$table and $alias argument must be a string', + ], + 'no-alias' => [ + 'table' => 'table1', + 'alias' => '', + 'expected' => ' INNER JOIN (table1)', + ], + 'with-alias' => [ + 'table' => 'SELECT * FROM B', + 'alias' => 'b', + 'expected' => ' INNER JOIN (SELECT * FROM B) AS b', + ], + ]; + } + + /** + * @return array + */ + public function providerFullJoin() + { + return [ + 'invalid-table' => [ + 'table' => ['table1'], + 'alias' => '', + 'expected' => '$table and $alias argument must be a string', + ], + 'invalid-alias' => [ + 'table' => 'table1', + 'alias' => ['a'], + 'expected' => '$table and $alias argument must be a string', + ], + 'no-alias' => [ + 'table' => 'table1', + 'alias' => '', + 'expected' => ' FULL JOIN (table1)', + ], + 'with-alias' => [ + 'table' => 'SELECT * FROM B', + 'alias' => 'b', + 'expected' => ' FULL JOIN (SELECT * FROM B) AS b', + ], + ]; + } + + /** + * @return array + */ + public function providerOn() + { + return [ + 'invalid-leftCol' => [ + 'leftCol' => ['table1'], + 'condition' => '=', + 'rightCol' => 'id', + 'expected' => '$leftCol, $condition and $rightCol argument must be a string', + ], + 'invalid-condition' => [ + 'leftCol' => 'id', + 'condition' => ['='], + 'rightCol' => 'id', + 'expected' => '$leftCol, $condition and $rightCol argument must be a string', + ], + 'invalid-rightCol' => [ + 'leftCol' => 'id', + 'condition' => '=', + 'rightCol' => ['id'], + 'expected' => '$leftCol, $condition and $rightCol argument must be a string', + ], + 'success' => [ + 'leftCol' => 'a.id', + 'condition' => '=', + 'rightCol' => 'b.id', + 'expected' => ' ON a.id = b.id', + ], + ]; + } + + /** + * @return array + */ + public function providerGroupBy() + { + return [ + 'invalid-columns' => [ + 'columns' => new \stdClass(), + 'expected' => '$columns argument must be an array or a string', + ], + 'string-column' => [ + 'columns' => 'id', + 'expected' => ' GROUP BY id', + ], + 'array-column' => [ + 'columns' => ['id', 'name'], + 'expected' => ' GROUP BY id, name', + ], + ]; + } + + /** + * @return array + */ + public function providerOrderBy() + { + return [ + 'invalid-column' => [ + 'columns' => new \stdClass(), + 'sortType' => '', + 'expected' => '$column and $sortType argument must be a string', + ], + 'invalid-sortType' => [ + 'columns' => 'id', + 'sortType' => [''], + 'expected' => '$column and $sortType argument must be a string', + ], + 'success' => [ + 'columns' => 'id', + 'sortType' => 'DESC', + 'expected' => ' ORDER BY id DESC, id DESC', + ], + ]; + } + + /** + * @return array + */ + public function providerLimit() + { + return [ + 'invalid-limit-object' => [ + 'limit' => new \stdClass(), + 'expected' => '$limit argument must be an integer', + ], + 'invalid-limit-string' => [ + 'limit' => 'limit', + 'expected' => '$limit argument must be an integer', + ], + 'invalid-limit-array' => [ + 'limit' => [1], + 'expected' => '$limit argument must be an integer', + ], + 'success' => [ + 'limit' => 10, + 'expected' => ' LIMIT 10', + ], + ]; + } + + /** + * @return array + */ + public function providerAndHaving() + { + return [ + 'column-type-invalid' => [ + 'column' => ['col1'], + 'condition' => '>', + 'value' => 1, + 'firstHaving' => true, + 'expected' => '$column and $condition argument must be a string', + ], + 'condition-type-invalid' => [ + 'column' => 'col1', + 'condition' => ['>'], + 'value' => 1, + 'firstHaving' => true, + 'expected' => '$column and $condition argument must be a string', + ], + 'value-type-invalid' => [ + 'column' => 'col1', + 'condition' => '>', + 'value' => new \stdClass(), + 'firstHaving' => true, + 'expected' => '$value argument must be a string, a numeric or an array', + ], + 'null-value' => [ + 'column' => 'col1', + 'condition' => '=', + 'value' => NULL, + 'firstHaving' => true, + 'expected' => ' HAVING col1 = NULL', + ], + 'int-value' => [ + 'column' => 'col1', + 'condition' => '>', + 'value' => 10, + 'firstHaving' => true, + 'expected' => ' HAVING col1 > 10', + ], + 'string-value' => [ + 'column' => 'col1', + 'condition' => '!=', + 'value' => 'str', + 'firstHaving' => true, + 'expected' => " HAVING col1 != 'str'", + ], + 'array-value' => [ + 'column' => 'col1', + 'condition' => 'IN', + 'value' => [1, 2, 3], + 'firstHaving' => false, + 'expected' => " AND col1 IN ('1', '2', '3')", + ], + ]; + } + + /** + * @return array + */ + public function providerOrHaving() + { + return [ + 'column-type-invalid' => [ + 'column' => ['col1'], + 'condition' => '>', + 'value' => 1, + 'firstHaving' => true, + 'expected' => '$column and $condition argument must be a string', + ], + 'condition-type-invalid' => [ + 'column' => 'col1', + 'condition' => ['>'], + 'value' => 1, + 'firstHaving' => true, + 'expected' => '$column and $condition argument must be a string', + ], + 'value-type-invalid' => [ + 'column' => 'col1', + 'condition' => '>', + 'value' => new \stdClass(), + 'firstHaving' => true, + 'expected' => '$value argument must be a string, a numeric or an array', + ], + 'null-value' => [ + 'column' => 'col1', + 'condition' => '=', + 'value' => NULL, + 'firstHaving' => true, + 'expected' => ' HAVING col1 = NULL', + ], + 'int-value' => [ + 'column' => 'col1', + 'condition' => '>', + 'value' => 10, + 'firstHaving' => true, + 'expected' => ' HAVING col1 > 10', + ], + 'string-value' => [ + 'column' => 'col1', + 'condition' => '!=', + 'value' => 'str', + 'firstHaving' => true, + 'expected' => " HAVING col1 != 'str'", + ], + 'array-value' => [ + 'column' => 'col1', + 'condition' => 'IN', + 'value' => [1, 2, 3], + 'firstHaving' => false, + 'expected' => " OR col1 IN ('1', '2', '3')", + ], + ]; + } +} diff --git a/tests/Provider/WhereTestProvider.php b/tests/Provider/WhereTestProvider.php new file mode 100644 index 0000000..935ac11 --- /dev/null +++ b/tests/Provider/WhereTestProvider.php @@ -0,0 +1,125 @@ + [ + 'column' => ['err'], + 'condition' => '=', + 'value' => 1, + 'expected' => '$column and $condition argument must be a string', + ], + 'condition-invalid' => [ + 'column' => 'a', + 'condition' => ['test'], + 'value' => 1, + 'expected' => '$column and $condition argument must be a string', + ], + 'value-invalid' => [ + 'column' => 'a', + 'condition' => '=', + 'value' => new \stdClass(), + 'expected' => '$value argument must be a string, a numeric or an array', + ], + ]; + } + + /** + * @return array + */ + public function providerGetWhereAndStr() + { + return [ + 'is-first-where' => [ + 'column' => 'col', + 'condition' => '=', + 'value' => 1, + 'isFirstWhere' => true, + 'expected' => ' WHERE col = 1', + ], + 'null-value' => [ + 'column' => 'col', + 'condition' => 'IS', + 'value' => null, + 'isFirstWhere' => false, + 'expected' => " AND col IS NULL", + ], + 'numeric-value' => [ + 'column' => 'col', + 'condition' => '>', + 'value' => 1.5, + 'isFirstWhere' => false, + 'expected' => " AND col > 1.5", + ], + 'string-value' => [ + 'column' => 'col', + 'condition' => '=', + 'value' => 'test', + 'isFirstWhere' => false, + 'expected' => " AND col = 'test'", + ], + 'array-value' => [ + 'column' => 'col', + 'condition' => 'IN', + 'value' => [1, 2, 3], + 'isFirstWhere' => false, + 'expected' => " AND col IN ('1', '2', '3')", + ], + ]; + } + + /** + * @return array + */ + public function providerGetWhereOrStr() + { + return [ + 'is-first-where' => [ + 'column' => 'col', + 'condition' => '=', + 'value' => 1, + 'isFirstWhere' => true, + 'expected' => ' WHERE col = 1', + ], + 'null-value' => [ + 'column' => 'col', + 'condition' => 'IS', + 'value' => null, + 'isFirstWhere' => false, + 'expected' => " OR col IS NULL", + ], + 'numeric-value' => [ + 'column' => 'col', + 'condition' => '>', + 'value' => 1.5, + 'isFirstWhere' => false, + 'expected' => " OR col > 1.5", + ], + 'string-value' => [ + 'column' => 'col', + 'condition' => '=', + 'value' => 'test', + 'isFirstWhere' => false, + 'expected' => " OR col = 'test'", + ], + 'array-value' => [ + 'column' => 'col', + 'condition' => 'IN', + 'value' => [1, 2, 3], + 'isFirstWhere' => false, + 'expected' => " OR col IN ('1', '2', '3')", + ], + ]; + } +} diff --git a/tests/QueryTest.php b/tests/QueryTest.php index b0791e0..0a2ecb0 100644 --- a/tests/QueryTest.php +++ b/tests/QueryTest.php @@ -5,6 +5,7 @@ use MoiTran\PrestoQueryBuilder\Exception\InvalidArgumentException; use MoiTran\PrestoQueryBuilder\Query; use MoiTran\PrestoQueryBuilder\WhereGroup; +use MoiTran\PrestoQueryBuilder\Tests\Provider\QueryTestProvider; /** * Class QueryTest @@ -12,33 +13,7 @@ */ class QueryTest extends TestCases { - /** - * @return array - */ - public function providerSelect() - { - return [ - 'in-valid' => [ - 'select' => new \stdClass(), - 'expected' => '$select argument must be a string or an array', - ], - 'select-all' => [ - 'select' => '*', - 'expected' => 'SELECT *', - ], - 'select-columns' => [ - 'select' => ['query', 'page', 'country', 'device'], - 'expected' => "SELECT query, page, country, device", - ], - 'select-columns-with-alias' => [ - 'select' => [ - 'SUM(clicks)' => 'sumCLicks', - 'SUM(impressions)' => 'sumImpressions', - ], - 'expected' => "SELECT SUM(clicks) as sumCLicks, SUM(impressions) as sumImpressions", - ], - ]; - } + use QueryTestProvider; /** * @param $select @@ -58,35 +33,6 @@ public function testSelect($select, $expected) } } - /** - * @return array - */ - public function providerFrom() - { - return [ - 'in-valid-from' => [ - 'from' => new \stdClass(), - 'alias' => '', - 'expected' => '$from and $alias argument must be a string', - ], - 'in-valid-alias' => [ - 'from' => 'table1', - 'alias' => new \stdClass(), - 'expected' => '$from and $alias argument must be a string', - ], - 'no-alias' => [ - 'from' => 'table1', - 'alias' => '', - 'expected' => ' FROM (table1)', - ], - 'with-alias' => [ - 'from' => 'SELECT * FROM B', - 'alias' => 'a', - 'expected' => ' FROM (SELECT * FROM B) AS a', - ], - ]; - } - /** * @param $from * @param @alias @@ -106,35 +52,6 @@ public function testFrom($from, $alias, $expected) } } - /** - * @return array - */ - public function providerLeftJoin() - { - return [ - 'invalid-table' => [ - 'table' => ['table1'], - 'alias' => '', - 'expected' => '$table and $alias argument must be a string', - ], - 'invalid-alias' => [ - 'table' => 'table1', - 'alias' => ['a'], - 'expected' => '$table and $alias argument must be a string', - ], - 'no-alias' => [ - 'table' => 'table1', - 'alias' => '', - 'expected' => ' LEFT JOIN (table1)', - ], - 'with-alias' => [ - 'table' => 'SELECT * FROM B', - 'alias' => 'b', - 'expected' => ' LEFT JOIN (SELECT * FROM B) AS b', - ], - ]; - } - /** * @param $table * @param $alias @@ -154,35 +71,6 @@ public function testLeftJoin($table, $alias, $expected) } } - /** - * @return array - */ - public function providerRightJoin() - { - return [ - 'invalid-table' => [ - 'table' => ['table1'], - 'alias' => '', - 'expected' => '$table and $alias argument must be a string', - ], - 'invalid-alias' => [ - 'table' => 'table1', - 'alias' => ['a'], - 'expected' => '$table and $alias argument must be a string', - ], - 'no-alias' => [ - 'table' => 'table1', - 'alias' => '', - 'expected' => ' RIGHT JOIN (table1)', - ], - 'with-alias' => [ - 'table' => 'SELECT * FROM B', - 'alias' => 'b', - 'expected' => ' RIGHT JOIN (SELECT * FROM B) AS b', - ], - ]; - } - /** * @param $table * @param $alias @@ -202,35 +90,6 @@ public function testRightJoin($table, $alias, $expected) } } - /** - * @return array - */ - public function providerInnerJoin() - { - return [ - 'invalid-table' => [ - 'table' => ['table1'], - 'alias' => '', - 'expected' => '$table and $alias argument must be a string', - ], - 'invalid-alias' => [ - 'table' => 'table1', - 'alias' => ['a'], - 'expected' => '$table and $alias argument must be a string', - ], - 'no-alias' => [ - 'table' => 'table1', - 'alias' => '', - 'expected' => ' INNER JOIN (table1)', - ], - 'with-alias' => [ - 'table' => 'SELECT * FROM B', - 'alias' => 'b', - 'expected' => ' INNER JOIN (SELECT * FROM B) AS b', - ], - ]; - } - /** * @param $table * @param $alias @@ -250,35 +109,6 @@ public function testInnerJoin($table, $alias, $expected) } } - /** - * @return array - */ - public function providerFullJoin() - { - return [ - 'invalid-table' => [ - 'table' => ['table1'], - 'alias' => '', - 'expected' => '$table and $alias argument must be a string', - ], - 'invalid-alias' => [ - 'table' => 'table1', - 'alias' => ['a'], - 'expected' => '$table and $alias argument must be a string', - ], - 'no-alias' => [ - 'table' => 'table1', - 'alias' => '', - 'expected' => ' FULL JOIN (table1)', - ], - 'with-alias' => [ - 'table' => 'SELECT * FROM B', - 'alias' => 'b', - 'expected' => ' FULL JOIN (SELECT * FROM B) AS b', - ], - ]; - } - /** * @param $table * @param $alias @@ -298,39 +128,6 @@ public function testFullJoin($table, $alias, $expected) } } - /** - * @return array - */ - public function providerOn() - { - return [ - 'invalid-leftCol' => [ - 'leftCol' => ['table1'], - 'condition' => '=', - 'rightCol' => 'id', - 'expected' => '$leftCol, $condition and $rightCol argument must be a string', - ], - 'invalid-condition' => [ - 'leftCol' => 'id', - 'condition' => ['='], - 'rightCol' => 'id', - 'expected' => '$leftCol, $condition and $rightCol argument must be a string', - ], - 'invalid-rightCol' => [ - 'leftCol' => 'id', - 'condition' => '=', - 'rightCol' => ['id'], - 'expected' => '$leftCol, $condition and $rightCol argument must be a string', - ], - 'success' => [ - 'leftCol' => 'a.id', - 'condition' => '=', - 'rightCol' => 'b.id', - 'expected' => ' ON a.id = b.id', - ], - ]; - } - /** * @param $leftCol * @param $condition @@ -381,7 +178,13 @@ public function testWhereAndGroup() ->whereAnd('name', '=', 'test'); $query = new Query(); $actual = $query->whereAndGroup($whereGroup)->whereAndGroup($whereGroup)->getQueryStr(); - $expected = " WHERE AND (id > 1 AND name = 'test') AND (id > 1 AND name = 'test')"; + $expected = " WHERE (id > 1 AND name = 'test') AND (id > 1 AND name = 'test')"; + $this->assertEquals($expected, $actual); + + $whereGroup = new WhereGroup(); + $query = new Query(); + $actual = $query->select('*')->from('db')->whereAndGroup($whereGroup)->getQueryStr(); + $expected = 'SELECT * FROM (db)'; $this->assertEquals($expected, $actual); } @@ -395,7 +198,13 @@ public function testWhereOrGroup() ->whereOr('name', '=', 'test'); $query = new Query(); $actual = $query->whereOrGroup($whereGroup)->whereOrGroup($whereGroup)->getQueryStr(); - $expected = " WHERE OR (id > 1 OR name = 'test') OR (id > 1 OR name = 'test')"; + $expected = " WHERE (id > 1 OR name = 'test') OR (id > 1 OR name = 'test')"; + $this->assertEquals($expected, $actual); + + $whereGroup = new WhereGroup(); + $query = new Query(); + $actual = $query->select('*')->from('db')->whereOrGroup($whereGroup)->getQueryStr(); + $expected = 'SELECT * FROM (db)'; $this->assertEquals($expected, $actual); } @@ -420,27 +229,6 @@ public function testUnionAll() $this->assertEquals($expected, $actual); } - /** - * @return array - */ - public function providerGroupBy() - { - return [ - 'invalid-columns' => [ - 'columns' => new \stdClass(), - 'expected' => '$columns argument must be an array or a string', - ], - 'string-column' => [ - 'columns' => 'id', - 'expected' => ' GROUP BY id', - ], - 'array-column' => [ - 'columns' => ['id', 'name'], - 'expected' => ' GROUP BY id, name', - ], - ]; - } - /** * @param $columns * @param $expected @@ -459,30 +247,6 @@ public function testGroupBy($columns, $expected) } } - /** - * @return array - */ - public function providerOrderBy() - { - return [ - 'invalid-column' => [ - 'columns' => new \stdClass(), - 'sortType' => '', - 'expected' => '$column and $sortType argument must be a string', - ], - 'invalid-sortType' => [ - 'columns' => 'id', - 'sortType' => [''], - 'expected' => '$column and $sortType argument must be a string', - ], - 'success' => [ - 'columns' => 'id', - 'sortType' => 'DESC', - 'expected' => ' ORDER BY id DESC, id DESC', - ], - ]; - } - /** * @param $column * @param $sortType @@ -503,41 +267,60 @@ public function testOrderBy($column, $sortType, $expected) } /** - * @return array + * @param $limit + * @param $expected + * + * @dataProvider providerLimit */ - public function providerLimit() + public function testLimit($limit, $expected) { - return [ - 'invalid-limit-object' => [ - 'limit' => new \stdClass(), - 'expected' => '$limit argument must be an integer', - ], - 'invalid-limit-string' => [ - 'limit' => 'limit', - 'expected' => '$limit argument must be an integer', - ], - 'invalid-limit-array' => [ - 'limit' => [1], - 'expected' => '$limit argument must be an integer', - ], - 'success' => [ - 'limit' => 10, - 'expected' => ' LIMIT 10', - ], - ]; + $query = new Query(); + try { + $actual = $query->limit($limit)->getQueryStr(); + $this->assertEquals($expected, $actual); + } catch (\Exception $e) { + $this->assertInstanceOf(InvalidArgumentException::class, $e); + $this->assertEquals($expected, $e->getMessage()); + } } /** - * @param $limit + * @param $column + * @param $condition + * @param $value + * @param $firstHaving * @param $expected * - * @dataProvider providerLimit + * @dataProvider providerAndHaving */ - public function testLimit($limit, $expected) + public function testAndHaving($column, $condition, $value, $firstHaving, $expected) { $query = new Query(); try { - $actual = $query->limit($limit)->getQueryStr(); + $this->setPrivateProp($query, 'isFirstHaving', $firstHaving); + $actual = $query->andHaving($column, $condition, $value)->getQueryStr(); + $this->assertEquals($expected, $actual); + } catch (\Exception $e) { + $this->assertInstanceOf(InvalidArgumentException::class, $e); + $this->assertEquals($expected, $e->getMessage()); + } + } + + /** + * @param $column + * @param $condition + * @param $value + * @param $firstHaving + * @param $expected + * + * @dataProvider providerOrHaving + */ + public function testOrHaving($column, $condition, $value, $firstHaving, $expected) + { + $query = new Query(); + try { + $this->setPrivateProp($query, 'isFirstHaving', $firstHaving); + $actual = $query->orHaving($column, $condition, $value)->getQueryStr(); $this->assertEquals($expected, $actual); } catch (\Exception $e) { $this->assertInstanceOf(InvalidArgumentException::class, $e); diff --git a/tests/TestCases.php b/tests/TestCases.php index f0fda4d..c3c2cce 100644 --- a/tests/TestCases.php +++ b/tests/TestCases.php @@ -8,4 +8,21 @@ */ class TestCases extends \PHPUnit\Framework\TestCase { + /** + * @param $object + * @param $property + * @param $value + * + * @return bool + * @throws \ReflectionException + */ + public function setPrivateProp(&$object, $property, $value) + { + $reflection = new \ReflectionClass(get_class($object)); + $prop = $reflection->getProperty($property); + $prop->setAccessible(true); + $prop->setValue($object, $value); + + return true; + } } diff --git a/tests/WhereGroupTest.php b/tests/WhereGroupTest.php index dc84304..788fdaa 100644 --- a/tests/WhereGroupTest.php +++ b/tests/WhereGroupTest.php @@ -21,7 +21,7 @@ public function testWhereAdd() ->whereAnd('col3', 'IN', [1, 2, 3, 4]) ->getWhereConditions(); - $expected = "col1 > 10 AND col2 IS NULL AND col3 IN ('1','2','3','4')"; + $expected = "col1 > 10 AND col2 IS NULL AND col3 IN ('1', '2', '3', '4')"; $this->assertEquals($expected, $actual); } @@ -36,7 +36,7 @@ public function testWhereOr() ->whereOr('col3', 'IN', [1, 2, 3, 4]) ->getWhereConditions(); - $expected = "col1 > 10 OR col2 IS NULL OR col3 IN ('1','2','3','4')"; + $expected = "col1 > 10 OR col2 IS NULL OR col3 IN ('1', '2', '3', '4')"; $this->assertEquals($expected, $actual); } @@ -52,6 +52,15 @@ public function testWhereOrGroup() $expected = "(col1 != 'not1' AND col1 != 'not2')"; $this->assertEquals($expected, $actual); + + $whereGroup = new WhereGroup(); + $actual = $whereGroup->whereOrGroup((new WhereGroup())) + ->whereAnd('col1', '!=', 'not2') + ->whereAnd('col2', '!=', 'not2') + ->getWhereConditions(); + + $expected = "col1 != 'not2' AND col2 != 'not2'"; + $this->assertEquals($expected, $actual); } /** @@ -66,5 +75,14 @@ public function testWhereAndGroup() $expected = "(col1 != 'not1' AND col1 != 'not2')"; $this->assertEquals($expected, $actual); + + $whereGroup = new WhereGroup(); + $actual = $whereGroup->whereAndGroup((new WhereGroup())) + ->whereAnd('col1', '!=', 'not2') + ->whereAnd('col2', '!=', 'not2') + ->getWhereConditions(); + + $expected = "col1 != 'not2' AND col2 != 'not2'"; + $this->assertEquals($expected, $actual); } } diff --git a/tests/WhereTest.php b/tests/WhereTest.php index e619b7f..e8afdc8 100644 --- a/tests/WhereTest.php +++ b/tests/WhereTest.php @@ -4,6 +4,7 @@ use MoiTran\PrestoQueryBuilder\Exception\InvalidArgumentException; use MoiTran\PrestoQueryBuilder\Where; +use MoiTran\PrestoQueryBuilder\Tests\Provider\WhereTestProvider; /** * Class ExampleTest @@ -11,33 +12,7 @@ class WhereTest extends TestCases { use Where; - - /** - * @return array - */ - public function providerWhereThrowException() - { - return [ - 'column-invalid' => [ - 'column' => ['err'], - 'condition' => '=', - 'value' => 1, - 'expected' => '$column and $condition argument must be a string', - ], - 'condition-invalid' => [ - 'column' => 'a', - 'condition' => ['test'], - 'value' => 1, - 'expected' => '$column and $condition argument must be a string', - ], - 'value-invalid' => [ - 'column' => 'a', - 'condition' => '=', - 'value' => new \stdClass(), - 'expected' => '$value argument must be a string, a numeric or an array', - ], - ]; - } + use WhereTestProvider; /** * @param $column @@ -57,50 +32,6 @@ public function testWhereThrowException($column, $condition, $value, $expected) } } - /** - * @return array - */ - public function providerGetWhereAndStr() - { - return [ - 'is-first-where' => [ - 'column' => 'col', - 'condition' => '=', - 'value' => 1, - 'isFirstWhere' => true, - 'expected' => ' WHERE col = 1', - ], - 'null-value' => [ - 'column' => 'col', - 'condition' => 'IS', - 'value' => NULL, - 'isFirstWhere' => false, - 'expected' => " AND col IS NULL", - ], - 'numeric-value' => [ - 'column' => 'col', - 'condition' => '>', - 'value' => 1.5, - 'isFirstWhere' => false, - 'expected' => " AND col > 1.5", - ], - 'string-value' => [ - 'column' => 'col', - 'condition' => '=', - 'value' => 'test', - 'isFirstWhere' => false, - 'expected' => " AND col = 'test'", - ], - 'array-value' => [ - 'column' => 'col', - 'condition' => 'IN', - 'value' => [1, 2, 3], - 'isFirstWhere' => false, - 'expected' => " AND col IN ('1','2','3')", - ], - ]; - } - /** * @param $column * @param $condition @@ -117,50 +48,6 @@ public function testGetWhereAndStr($column, $condition, $value, $isFirstWhere, $ $this->assertEquals($expected, $actual); } - /** - * @return array - */ - public function providerGetWhereOrStr() - { - return [ - 'is-first-where' => [ - 'column' => 'col', - 'condition' => '=', - 'value' => 1, - 'isFirstWhere' => true, - 'expected' => ' WHERE col = 1', - ], - 'null-value' => [ - 'column' => 'col', - 'condition' => 'IS', - 'value' => NULL, - 'isFirstWhere' => false, - 'expected' => " OR col IS NULL", - ], - 'numeric-value' => [ - 'column' => 'col', - 'condition' => '>', - 'value' => 1.5, - 'isFirstWhere' => false, - 'expected' => " OR col > 1.5", - ], - 'string-value' => [ - 'column' => 'col', - 'condition' => '=', - 'value' => 'test', - 'isFirstWhere' => false, - 'expected' => " OR col = 'test'", - ], - 'array-value' => [ - 'column' => 'col', - 'condition' => 'IN', - 'value' => [1, 2, 3], - 'isFirstWhere' => false, - 'expected' => " OR col IN ('1','2','3')", - ], - ]; - } - /** * @param $column * @param $condition