Skip to content
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.

Expand Down
46 changes: 12 additions & 34 deletions src/Pixie/QueryBuilder/Adapters/BaseAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'], ', ');

Expand Down Expand Up @@ -77,7 +81,7 @@ public function select($statements)
$sqlArray = array(
'SELECT' . (isset($statements['distinct']) ? ' DISTINCT' : ''),
$selects,
'FROM',
(($fromEnabled) ? 'FROM' : ''),
$tables,
$joinString,
$whereCriteria,
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -344,11 +338,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));
}

/**
Expand Down Expand Up @@ -446,24 +436,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);
}

/**
Expand Down
21 changes: 18 additions & 3 deletions src/Pixie/QueryBuilder/QueryBuilderHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,18 +324,33 @@ 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();
$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());
$executionTime += $time;

if ($result->rowCount() === 1) {
if ($result->rowCount() >= 1) {
$return[] = $this->pdo->lastInsertId();
}
}
Expand Down
33 changes: 33 additions & 0 deletions tests/Pixie/NoTableSubQueryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php namespace Pixie;

use PDO;
use Mockery as m;
use Pixie\QueryBuilder\QueryBuilderHandler;

class NoTableSubQueryTest extends TestCase
{
/**
* @var QueryBuilderHandler
*/
protected $builder;

public function setUp()
{
parent::setUp();

$this->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);

}

}
6 changes: 3 additions & 3 deletions tests/Pixie/QueryBuilderBehaviorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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!'
);
Expand Down
9 changes: 1 addition & 8 deletions tests/Pixie/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

}