Skip to content

Commit 6d29fa7

Browse files
committed
Implement subquery support in joins
1 parent 6ca835b commit 6d29fa7

File tree

3 files changed

+63
-9
lines changed

3 files changed

+63
-9
lines changed

MysqliDb.php

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public function __construct($host = NULL, $username = NULL, $password = NULL, $d
117117
else
118118
$this->port = $port;
119119

120-
if ($host == null && $username == null && $db == null) {
120+
if ($username == null && $db == null) {
121121
$this->isSubQuery = true;
122122
return;
123123
}
@@ -427,12 +427,14 @@ public function join($joinTable, $joinCondition, $joinType = '')
427427
{
428428
$allowedTypes = array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER');
429429
$joinType = strtoupper (trim ($joinType));
430-
$joinTable = filter_var($joinTable, FILTER_SANITIZE_STRING);
431430

432431
if ($joinType && !in_array ($joinType, $allowedTypes))
433432
die ('Wrong JOIN type: '.$joinType);
434433

435-
$this->_join[$joinType . " JOIN " . self::$_prefix . $joinTable] = $joinCondition;
434+
if (!is_object ($joinTable))
435+
$joinTable = self::$_prefix . filter_var($joinTable, FILTER_SANITIZE_STRING);
436+
437+
$this->_join[] = Array ($joinType, $joinTable, $joinCondition);
436438

437439
return $this;
438440
}
@@ -587,7 +589,7 @@ protected function _buildPair ($operator, $value) {
587589
$subQuery = $value->getSubQuery ();
588590
$this->_bindParams ($subQuery['params']);
589591

590-
return " " . $operator . " (" . $subQuery['query'] . ")";
592+
return " " . $operator . " (" . $subQuery['query'] . ") " . $subQuery['alias'];
591593
}
592594

593595
/**
@@ -679,8 +681,16 @@ protected function _buildJoin () {
679681
if (empty ($this->_join))
680682
return;
681683

682-
foreach ($this->_join as $prop => $value)
683-
$this->_query .= " " . $prop . " on " . $value;
684+
foreach ($this->_join as $data) {
685+
list ($joinType, $joinTable, $joinCondition) = $data;
686+
687+
if (is_object ($joinTable))
688+
$joinStr = $this->_buildPair ("", $joinTable);
689+
else
690+
$joinStr = $joinTable;
691+
692+
$this->_query .= " " . $joinType. " JOIN " . $joinStr ." on " . $joinCondition;
693+
}
684694
}
685695

686696
/**
@@ -946,7 +956,8 @@ public function getSubQuery () {
946956

947957
array_shift ($this->_bindParams);
948958
$val = Array ('query' => $this->_query,
949-
'params' => $this->_bindParams
959+
'params' => $this->_bindParams,
960+
'alias' => $this->host
950961
);
951962
$this->reset();
952963
return $val;
@@ -1031,9 +1042,9 @@ public function func ($expr, $bindParams = null) {
10311042
/**
10321043
* Method creates new mysqlidb object for a subquery generation
10331044
*/
1034-
public static function subQuery()
1045+
public static function subQuery($subQueryAlias = "")
10351046
{
1036-
return new MysqliDb();
1047+
return new MysqliDb ($subQueryAlias);
10371048
}
10381049

10391050
/**

readme.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,20 @@ echo "total records found: " . $cnt;
307307
```
308308

309309
### Subqueries
310+
Subquery init
311+
312+
Subquery init without an alias to use in inserts/updates/where Eg. (select * from users)
313+
```php
314+
$sq = $db->subQuery();
315+
$sq->get ("users");
316+
```
317+
318+
A subquery with an alias specified to use in JOINs . Eg. (select * from users) sq
319+
```php
320+
$sq = $db->subQuery("sq");
321+
$sq->get ("users");
322+
```
323+
310324
Subquery in selects:
311325
```php
312326
$ids = $db->subQuery ();
@@ -333,6 +347,18 @@ $id = $db->insert ("products", $data);
333347
// Gives INSERT INTO PRODUCTS (productName, userId, lastUpdated) values ("test product", (SELECT name FROM users WHERE id = 6), NOW());
334348
```
335349

350+
Subquery in joins:
351+
```php
352+
$usersQ = $db->subQuery ("u");
353+
$usersQ->where ("active", 1);
354+
$usersQ->get ("users");
355+
356+
$db->join($usersQ, "p.userId=u.id", "LEFT");
357+
$products = $db->get ("products p", null, "u.login, p.productName");
358+
print_r ($products);
359+
// SELECT u.login, p.productName FROM products p LEFT JOIN (SELECT * FROM t_users WHERE active = 1) u on p.userId=u.id;
360+
```
361+
336362
###EXISTS / NOT EXISTS condition
337363
```php
338364
$sub = $db->subQuery();

tests.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,23 @@ function createTable ($name, $data) {
292292
echo "Invalid select result with subquery";
293293
exit;
294294
}
295+
296+
297+
$usersQ = $db->subQuery ("u");
298+
$usersQ->where ("active", 1);
299+
$usersQ->get("users");
300+
301+
$db->join($usersQ, "p.userId=u.id", "LEFT");
302+
$products = $db->get ("products p", null, "u.login, p.productName");
303+
if ($products[2]['login'] != 'user1' || $products[2]['productName'] != 'product3') {
304+
echo "invalid join with subquery";
305+
exit;
306+
}
307+
if ($db->count != 5) {
308+
echo "invalid join with subquery count";
309+
exit;
310+
}
311+
295312
//TODO: insert test
296313
$db->delete("users");
297314
$db->get("users");

0 commit comments

Comments
 (0)