From 76f6d164adb5b09c8d5c6102eff409595790e2bd Mon Sep 17 00:00:00 2001 From: Lewis Theobald Date: Fri, 15 Apr 2016 16:11:59 +0100 Subject: [PATCH 1/6] When you're calling onDuplicateKeyUpdate, passing in id = LAST_INSERT_ID(id) is returning null, as 1 is not returned --- src/Pixie/QueryBuilder/QueryBuilderHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Pixie/QueryBuilder/QueryBuilderHandler.php b/src/Pixie/QueryBuilder/QueryBuilderHandler.php index 134fba0..3058abe 100644 --- a/src/Pixie/QueryBuilder/QueryBuilderHandler.php +++ b/src/Pixie/QueryBuilder/QueryBuilderHandler.php @@ -324,7 +324,7 @@ private function doInsert($data, $type) list($result, $executionTime) = $this->statement($queryObject->getSql(), $queryObject->getBindings()); - $return = $result->rowCount() === 1 ? $this->pdo->lastInsertId() : null; + $return = $result->rowCount() >= 1 ? $this->pdo->lastInsertId() : null; } else { // Its a batch insert $return = array(); @@ -335,7 +335,7 @@ private function doInsert($data, $type) list($result, $time) = $this->statement($queryObject->getSql(), $queryObject->getBindings()); $executionTime += $time; - if ($result->rowCount() === 1) { + if ($result->rowCount() >= 1) { $return[] = $this->pdo->lastInsertId(); } } From 8693f6ed28151d1c1164feadef37d323f4a3bcbc Mon Sep 17 00:00:00 2001 From: Lewis Theobald Date: Mon, 9 May 2016 14:03:23 +0100 Subject: [PATCH 2/6] Implemented the on duplicate (assume the data set is the same length) --- src/Pixie/QueryBuilder/QueryBuilderHandler.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Pixie/QueryBuilder/QueryBuilderHandler.php b/src/Pixie/QueryBuilder/QueryBuilderHandler.php index 3058abe..b992a18 100644 --- a/src/Pixie/QueryBuilder/QueryBuilderHandler.php +++ b/src/Pixie/QueryBuilder/QueryBuilderHandler.php @@ -329,7 +329,22 @@ private function doInsert($data, $type) // Its a batch insert $return = array(); $executionTime = 0; - foreach ($data as $subData) { + + // We want to check if they're an array + $onDuplicate = $this->statements['onduplicate']; + + // Loop over the data + foreach ($data as $index => $subData) { + + // Assume the data is the same size + if (is_array(current($onDuplicate))) { + if (!empty($onDuplicate[$index])) { + $this->statements['onduplicate'] = $onDuplicate[$index]; + } else { + $this->statements['onduplicate'] = null; + } + } + $queryObject = $this->getQuery($type, $subData); list($result, $time) = $this->statement($queryObject->getSql(), $queryObject->getBindings()); From e7b74127fc1a5dd9d4a104639c14a7a8dd1796e8 Mon Sep 17 00:00:00 2001 From: Pavel Puchkin Date: Wed, 18 May 2016 16:40:09 +0200 Subject: [PATCH 3/6] Speedup wrapSanitizer --- src/Pixie/QueryBuilder/Adapters/BaseAdapter.php | 14 +------------- tests/Pixie/QueryBuilderBehaviorTest.php | 6 +++--- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php b/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php index ade1a1b..37ce5cb 100644 --- a/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php +++ b/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php @@ -446,24 +446,12 @@ protected function buildCriteria($statements, $bindValues = true) */ public function wrapSanitizer($value) { - // Its a raw query, just cast as string, object has __toString() if ($value instanceof Raw) { return (string)$value; } elseif ($value instanceof \Closure) { return $value; } - - // Separate our table and fields which are joined with a ".", - // like my_table.id - $valueArr = explode('.', $value, 2); - - foreach ($valueArr as $key => $subValue) { - // Don't wrap if we have *, which is not a usual field - $valueArr[$key] = trim($subValue) == '*' ? $subValue : $this->sanitizer . $subValue . $this->sanitizer; - } - - // Join these back with "." and return - return implode('.', $valueArr); + return preg_replace('/([\w\s-]+)/', "{$this->sanitizer}\\1{$this->sanitizer}", $value, 2); } /** diff --git a/tests/Pixie/QueryBuilderBehaviorTest.php b/tests/Pixie/QueryBuilderBehaviorTest.php index 40030d9..e053ff5 100644 --- a/tests/Pixie/QueryBuilderBehaviorTest.php +++ b/tests/Pixie/QueryBuilderBehaviorTest.php @@ -16,12 +16,12 @@ public function setUp() public function testSelectFlexibility() { $query = $this->builder - ->select('foo') - ->select(array('bar', 'baz')) + ->select('foo1') + ->select(array('bar-2', 'baz_3')) ->select('qux', 'lol', 'wut') ->from('t'); $this->assertEquals( - 'SELECT `foo`, `bar`, `baz`, `qux`, `lol`, `wut` FROM `cb_t`', + 'SELECT `foo1`, `bar-2`, `baz_3`, `qux`, `lol`, `wut` FROM `cb_t`', $query->getQuery()->getRawSql(), 'SELECT is pretty flexible!' ); From 777f0037eac3cbcc23f60aba5d1057b9a47ef1ab Mon Sep 17 00:00:00 2001 From: Pavel Puchkin Date: Wed, 18 May 2016 18:12:23 +0200 Subject: [PATCH 4/6] Speedup concatinateQuery --- src/Pixie/QueryBuilder/Adapters/BaseAdapter.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php b/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php index 37ce5cb..fdc3b54 100644 --- a/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php +++ b/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php @@ -344,11 +344,7 @@ protected function arrayStr(array $pieces, $glue, $wrapSanitizer = true) */ protected function concatenateQuery(array $pieces) { - $str = ''; - foreach ($pieces as $piece) { - $str = trim($str) . ' ' . trim($piece); - } - return trim($str); + return implode(' ', array_filter($pieces)); } /** From 6d07d8ab6506e2d578f005ee789c42a228284ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Thu, 2 Jun 2016 20:07:30 +0200 Subject: [PATCH 5/6] [FEATURE] Removed support for not defining table. --- .../QueryBuilder/Adapters/BaseAdapter.php | 26 ++++++--------- tests/Pixie/NoTableSubQueryTest.php | 33 +++++++++++++++++++ tests/Pixie/QueryBuilderTest.php | 9 +---- 3 files changed, 44 insertions(+), 24 deletions(-) create mode 100644 tests/Pixie/NoTableSubQueryTest.php diff --git a/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php b/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php index ade1a1b..90a3844 100644 --- a/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php +++ b/src/Pixie/QueryBuilder/Adapters/BaseAdapter.php @@ -32,14 +32,18 @@ public function __construct(Connection $connection) */ public function select($statements) { - if (!array_key_exists('tables', $statements)) { - throw new Exception('No table specified.', 3); - } elseif (!array_key_exists('selects', $statements)) { + if (!array_key_exists('selects', $statements)) { $statements['selects'][] = '*'; } // From - $tables = $this->arrayStr($statements['tables'], ', '); + $fromEnabled = false; + $tables = ''; + + if(isset($statements['tables'])) { + $tables = $this->arrayStr($statements['tables'], ', '); + $fromEnabled = true; + } // Select $selects = $this->arrayStr($statements['selects'], ', '); @@ -77,7 +81,7 @@ public function select($statements) $sqlArray = array( 'SELECT' . (isset($statements['distinct']) ? ' DISTINCT' : ''), $selects, - 'FROM', + (($fromEnabled) ? 'FROM' : ''), $tables, $joinString, $whereCriteria, @@ -129,10 +133,6 @@ public function criteriaOnly($statements, $bindValues = true) */ private function doInsert($statements, array $data, $type) { - if (!isset($statements['tables'])) { - throw new Exception('No table specified', 3); - } - $table = end($statements['tables']); $bindings = $keys = $values = array(); @@ -247,9 +247,7 @@ private function getUpdateStatement($data) */ public function update($statements, array $data) { - if (!isset($statements['tables'])) { - throw new Exception('No table specified', 3); - } elseif (count($data) < 1) { + if (count($data) < 1) { throw new Exception('No data given.', 4); } @@ -288,10 +286,6 @@ public function update($statements, array $data) */ public function delete($statements) { - if (!isset($statements['tables'])) { - throw new Exception('No table specified', 3); - } - $table = end($statements['tables']); // Wheres diff --git a/tests/Pixie/NoTableSubQueryTest.php b/tests/Pixie/NoTableSubQueryTest.php new file mode 100644 index 0000000..9dc0b92 --- /dev/null +++ b/tests/Pixie/NoTableSubQueryTest.php @@ -0,0 +1,33 @@ +builder = new QueryBuilderHandler($this->mockConnection); + } + + public function testRawQuery() + { + + $subQuery1 = $this->builder->table('mail')->select($this->builder->raw('COUNT(*)')); + $subQuery2 = $this->builder->table('event_message')->select($this->builder->raw('COUNT(*)')); + + $count = $this->builder->select($this->builder->subQuery($subQuery1, 'row1'), $this->builder->subQuery($subQuery2, 'row2'))->first(); + + $this->assertEquals('SELECT (SELECT COUNT(*) FROM `cb_mail`) as row1, (SELECT COUNT(*) FROM `cb_event_message`) as row2 LIMIT 1', $count); + + } + +} \ No newline at end of file diff --git a/tests/Pixie/QueryBuilderTest.php b/tests/Pixie/QueryBuilderTest.php index ec0ec73..224fb56 100644 --- a/tests/Pixie/QueryBuilderTest.php +++ b/tests/Pixie/QueryBuilderTest.php @@ -86,12 +86,5 @@ public function testInsertQueryReturnsNullForIgnoredInsert() $this->assertEquals(null, $id); } - - /** - * @expectedException \Pixie\Exception - * @expectedExceptionCode 3 - */ - public function testTableNotSpecifiedException(){ - $this->builder->where('a', 'b')->get(); - } + } \ No newline at end of file From e6ee96f407d6b78e7f0eb278cfd34047c292071c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Thu, 2 Jun 2016 20:35:01 +0200 Subject: [PATCH 6/6] Added section in readme --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index d280e5a..782b0b9 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ Library on [Packagist](https://packagist.org/packages/usmanhalalit/pixie). - [Get All](#get-all) - [Get First Row](#get-first-row) - [Get Rows Count](#get-rows-count) + - [Selects With Sub-Queries](#select-with-sub-queries) - [**Where**](#where) - [Where In](#where-in) - [Where Between](#where-between) @@ -258,6 +259,21 @@ $query = QB::table('my_table')->where('name', '=', 'Sana'); $query->count(); ``` +#### Select With Sub-Queries + +```PHP +$subQuery1 = $this->builder->table('mail')->select($this->builder->raw('COUNT(*)')); +$subQuery2 = $this->builder->table('event_message')->select($this->builder->raw('COUNT(*)')); + +$count = $this->builder->select($this->builder->subQuery($subQuery1, 'row1'), $this->builder->subQuery($subQuery2, 'row2'))->first(); +``` + +Will produce the following query: + +```sql +SELECT (SELECT COUNT(*) FROM `cb_mail`) as row1, (SELECT COUNT(*) FROM `cb_event_message`) as row2 LIMIT 1 +``` + ### Where Basic syntax is `(fieldname, operator, value)`, if you give two parameters then `=` operator is assumed. So `where('name', 'usman')` and `where('name', '=', 'usman')` is the same.