Use State class to simplify management of query builder state

This commit is contained in:
Timothy Warren 2018-01-23 11:22:23 -05:00
parent 8401cceb0d
commit e4ca039b3d
4 changed files with 544 additions and 265 deletions

View File

@ -6,7 +6,7 @@
bootstrap="./../tests/bootstrap.php"> bootstrap="./../tests/bootstrap.php">
<filter> <filter>
<whitelist> <whitelist>
<directory suffix=".php">./../src/*</directory> <directory suffix=".php">./../src/</directory>
</whitelist> </whitelist>
</filter> </filter>
<testsuites> <testsuites>

View File

@ -27,119 +27,6 @@ use Query\Drivers\{
*/ */
class QueryBuilder implements QueryBuilderInterface { class QueryBuilder implements QueryBuilderInterface {
// --------------------------------------------------------------------------
// ! Constants
// --------------------------------------------------------------------------
const KEY = 0;
const VALUE = 1;
const BOTH = 2;
// --------------------------------------------------------------------------
// ! SQL Clause Strings
// --------------------------------------------------------------------------
/**
* Compiled 'select' clause
* @var string
*/
protected $selectString = '';
/**
* Compiled 'from' clause
* @var string
*/
protected $fromString = '';
/**
* Compiled arguments for insert / update
* @var string
*/
protected $setString;
/**
* Order by clause
* @var string
*/
protected $orderString;
/**
* Group by clause
* @var string
*/
protected $groupString;
// --------------------------------------------------------------------------
// ! SQL Clause Arrays
// --------------------------------------------------------------------------
/**
* Keys for insert/update statement
* @var array
*/
protected $setArrayKeys = [];
/**
* Key/val pairs for order by clause
* @var array
*/
protected $orderArray = [];
/**
* Key/val pairs for group by clause
* @var array
*/
protected $groupArray = [];
// --------------------------------------------------------------------------
// ! Other Class vars
// --------------------------------------------------------------------------
/**
* Values to apply to prepared statements
* @var array
*/
protected $values = [];
/**
* Values to apply to where clauses in prepared statements
* @var array
*/
protected $whereValues = [];
/**
* Value for limit string
* @var string
*/
protected $limit;
/**
* Value for offset in limit string
* @var integer
*/
protected $offset;
/**
* Query component order mapping
* for complex select queries
*
* Format:
* array(
* 'type' => 'where',
* 'conjunction' => ' AND ',
* 'string' => 'k=?'
* )
*
* @var array
*/
protected $queryMap = [];
/**
* Map for having clause
* @var array
*/
protected $havingMap;
/** /**
* Convenience property for connection management * Convenience property for connection management
* @var string * @var string
@ -156,7 +43,7 @@ class QueryBuilder implements QueryBuilderInterface {
* Whether to do only an explain on the query * Whether to do only an explain on the query
* @var boolean * @var boolean
*/ */
protected $explain; protected $explain = FALSE;
/** /**
* The current database driver * The current database driver
@ -183,35 +70,10 @@ class QueryBuilder implements QueryBuilderInterface {
protected $sql; protected $sql;
/** /**
* String class values to be reset * Query Builder state
* * @var State
* @var array
*/ */
private $stringVars = [ protected $state;
'selectString',
'fromString',
'setString',
'orderString',
'groupString',
'limit',
'offset',
'explain',
];
/**
* Array class variables to be reset
*
* @var array
*/
private $arrayVars = [
'setArrayKeys',
'orderArray',
'groupArray',
'values',
'whereValues',
'queryMap',
'havingMap'
];
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// ! Methods // ! Methods
@ -229,6 +91,9 @@ class QueryBuilder implements QueryBuilderInterface {
$this->driver = $driver; $this->driver = $driver;
$this->parser = $parser; $this->parser = $parser;
// Create new State object
$this->state = new State();
$this->queries['total_time'] = 0; $this->queries['total_time'] = 0;
// Alias driver sql and util classes // Alias driver sql and util classes
@ -313,9 +178,7 @@ class QueryBuilder implements QueryBuilderInterface {
} }
} }
$this->selectString .= implode(', ', $safeArray); $this->state->appendSelectString(implode(', ', $safeArray));
unset($safeArray);
return $this; return $this;
} }
@ -330,7 +193,7 @@ class QueryBuilder implements QueryBuilderInterface {
public function selectMax(string $field, $as=FALSE): QueryBuilderInterface public function selectMax(string $field, $as=FALSE): QueryBuilderInterface
{ {
// Create the select string // Create the select string
$this->selectString .= ' MAX'.$this->_select($field, $as); $this->state->appendSelectString(' MAX'.$this->_select($field, $as));
return $this; return $this;
} }
@ -344,7 +207,7 @@ class QueryBuilder implements QueryBuilderInterface {
public function selectMin(string $field, $as=FALSE): QueryBuilderInterface public function selectMin(string $field, $as=FALSE): QueryBuilderInterface
{ {
// Create the select string // Create the select string
$this->selectString .= ' MIN'.$this->_select($field, $as); $this->state->appendSelectString(' MIN'.$this->_select($field, $as));
return $this; return $this;
} }
@ -358,7 +221,7 @@ class QueryBuilder implements QueryBuilderInterface {
public function selectAvg(string $field, $as=FALSE): QueryBuilderInterface public function selectAvg(string $field, $as=FALSE): QueryBuilderInterface
{ {
// Create the select string // Create the select string
$this->selectString .= ' AVG'.$this->_select($field, $as); $this->state->appendSelectString(' AVG'.$this->_select($field, $as));
return $this; return $this;
} }
@ -372,7 +235,7 @@ class QueryBuilder implements QueryBuilderInterface {
public function selectSum(string $field, $as=FALSE): QueryBuilderInterface public function selectSum(string $field, $as=FALSE): QueryBuilderInterface
{ {
// Create the select string // Create the select string
$this->selectString .= ' SUM'.$this->_select($field, $as); $this->state->appendSelectString(' SUM'.$this->_select($field, $as));
return $this; return $this;
} }
@ -384,7 +247,7 @@ class QueryBuilder implements QueryBuilderInterface {
public function distinct(): QueryBuilderInterface public function distinct(): QueryBuilderInterface
{ {
// Prepend the keyword to the select string // Prepend the keyword to the select string
$this->selectString = ' DISTINCT '.$this->selectString; $this->state->setSelectString(' DISTINCT' . $this->state->getSelectString());
return $this; return $this;
} }
@ -416,7 +279,7 @@ class QueryBuilder implements QueryBuilderInterface {
$identArray = $this->driver->quoteIdent($identArray); $identArray = $this->driver->quoteIdent($identArray);
// Paste it back together // Paste it back together
$this->fromString = implode(' ', $identArray); $this->state->setFromString(implode(' ', $identArray));
return $this; return $this;
} }
@ -435,7 +298,7 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function like($field, $val, $pos='both'): QueryBuilderInterface public function like($field, $val, $pos='both'): QueryBuilderInterface
{ {
return $this->_like($field, $val, $pos, 'LIKE', 'AND'); return $this->_like($field, $val, $pos);
} }
/** /**
@ -521,7 +384,7 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function where($key, $val=[], $escape=NULL): QueryBuilderInterface public function where($key, $val=[], $escape=NULL): QueryBuilderInterface
{ {
return $this->_whereString($key, $val, 'AND'); return $this->_whereString($key, $val);
} }
/** /**
@ -597,16 +460,32 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function set($key, $val = NULL): QueryBuilderInterface public function set($key, $val = NULL): QueryBuilderInterface
{ {
$this->_mixedSet($this->setArrayKeys, $key, $val, self::KEY); if (is_scalar($key))
$this->_mixedSet($this->values, $key, $val, self::VALUE); {
$pairs = [$key => $val];
}
else
{
$pairs = $key;
}
$keys = array_keys($pairs);
$values = array_values($pairs);
$this->state->appendSetArrayKeys($keys);
$this->state->appendValues($values);
// Use the keys of the array to make the insert/update string // Use the keys of the array to make the insert/update string
// Escape the field names // Escape the field names
$this->setArrayKeys = array_map([$this->driver, '_quote'], $this->setArrayKeys); $this->state->setSetArrayKeys(
array_map([$this->driver, '_quote'], $this->state->getSetArrayKeys())
);
// Generate the "set" string // Generate the "set" string
$this->setString = implode('=?,', $this->setArrayKeys); $setString = implode('=?,', $this->state->getSetArrayKeys());
$this->setString .= '=?'; $setString .= '=?';
$this->state->setSetString($setString);
return $this; return $this;
} }
@ -631,7 +510,7 @@ class QueryBuilder implements QueryBuilderInterface {
$parsedCondition = $this->parser->compileJoin($condition); $parsedCondition = $this->parser->compileJoin($condition);
$condition = $table . ' ON ' . $parsedCondition; $condition = $table . ' ON ' . $parsedCondition;
$this->_appendMap("\n" . strtoupper($type) . ' JOIN ', $condition, 'join'); $this->state->appendMap("\n" . strtoupper($type) . ' JOIN ', $condition, 'join');
return $this; return $this;
} }
@ -647,14 +526,16 @@ class QueryBuilder implements QueryBuilderInterface {
if ( ! is_scalar($field)) if ( ! is_scalar($field))
{ {
$newGroupArray = array_map([$this->driver, 'quoteIdent'], $field); $newGroupArray = array_map([$this->driver, 'quoteIdent'], $field);
$this->groupArray = array_merge($this->groupArray, $newGroupArray); $this->state->setGroupArray(
array_merge($this->state->getGroupArray(), $newGroupArray)
);
} }
else else
{ {
$this->groupArray[] = $this->driver->quoteIdent($field); $this->state->appendGroupArray($this->driver->quoteIdent($field));
} }
$this->groupString = ' GROUP BY ' . implode(',', $this->groupArray); $this->state->setGroupString(' GROUP BY ' . implode(',', $this->state->getGroupArray()));
return $this; return $this;
} }
@ -678,21 +559,23 @@ class QueryBuilder implements QueryBuilderInterface {
// Set fields for later manipulation // Set fields for later manipulation
$field = $this->driver->quoteIdent($field); $field = $this->driver->quoteIdent($field);
$this->orderArray[$field] = $type; $this->state->setOrderArray($field, $type);
$orderClauses = []; $orderClauses = [];
// Flatten key/val pairs into an array of space-separated pairs // Flatten key/val pairs into an array of space-separated pairs
foreach($this->orderArray as $k => $v) foreach($this->state->getOrderArray() as $k => $v)
{ {
$orderClauses[] = $k . ' ' . strtoupper($v); $orderClauses[] = $k . ' ' . strtoupper($v);
} }
// Set the final string // Set the final string
$this->orderString = ( ! isset($rand)) $orderString = ( ! isset($rand))
? "\nORDER BY ".implode(', ', $orderClauses) ? "\nORDER BY ".implode(', ', $orderClauses)
: "\nORDER BY".$rand; : "\nORDER BY".$rand;
$this->state->setOrderString($orderString);
return $this; return $this;
} }
@ -705,8 +588,8 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function limit($limit, $offset=FALSE): QueryBuilderInterface public function limit($limit, $offset=FALSE): QueryBuilderInterface
{ {
$this->limit = (int) $limit; $this->state->setLimit($limit);
$this->offset = $offset; $this->state->setOffset($offset);
return $this; return $this;
} }
@ -722,9 +605,9 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function groupStart(): QueryBuilderInterface public function groupStart(): QueryBuilderInterface
{ {
$conj = empty($this->queryMap) ? ' WHERE ' : ' '; $conj = empty($this->state->getQueryMap()) ? ' WHERE ' : ' ';
$this->_appendMap($conj, '(', 'group_start'); $this->state->appendMap($conj, '(', 'group_start');
return $this; return $this;
} }
@ -737,9 +620,9 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function notGroupStart(): QueryBuilderInterface public function notGroupStart(): QueryBuilderInterface
{ {
$conj = empty($this->queryMap) ? ' WHERE ' : ' AND '; $conj = empty($this->state->getQueryMap()) ? ' WHERE ' : ' AND ';
$this->_appendMap($conj, ' NOT (', 'group_start'); $this->state->appendMap($conj, ' NOT (', 'group_start');
return $this; return $this;
} }
@ -752,7 +635,7 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function orGroupStart(): QueryBuilderInterface public function orGroupStart(): QueryBuilderInterface
{ {
$this->_appendMap('', ' OR (', 'group_start'); $this->state->appendMap('', ' OR (', 'group_start');
return $this; return $this;
} }
@ -765,7 +648,7 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function orNotGroupStart(): QueryBuilderInterface public function orNotGroupStart(): QueryBuilderInterface
{ {
$this->_appendMap('', ' OR NOT (', 'group_start'); $this->state->appendMap('', ' OR NOT (', 'group_start');
return $this; return $this;
} }
@ -777,7 +660,7 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function groupEnd(): QueryBuilderInterface public function groupEnd(): QueryBuilderInterface
{ {
$this->_appendMap('', ')', 'group_end'); $this->state->appendMap('', ')', 'group_end');
return $this; return $this;
} }
@ -894,7 +777,7 @@ class QueryBuilder implements QueryBuilderInterface {
// Get the generated values and sql string // Get the generated values and sql string
list($sql, $data) = $this->driver->insertBatch($table, $data); list($sql, $data) = $this->driver->insertBatch($table, $data);
return ( ! is_null($sql)) return $sql !== NULL
? $this->_run('', $table, $sql, $data) ? $this->_run('', $table, $sql, $data)
: NULL; : NULL;
} }
@ -930,7 +813,7 @@ class QueryBuilder implements QueryBuilderInterface {
// Get the generated values and sql string // Get the generated values and sql string
list($sql, $data) = $this->driver->updateBatch($table, $data, $where); list($sql, $data) = $this->driver->updateBatch($table, $data, $where);
return ( ! is_null($sql)) return $sql !== NULL
? $this->_run('', $table, $sql, $data) ? $this->_run('', $table, $sql, $data)
: NULL; : NULL;
} }
@ -1039,50 +922,11 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
public function resetQuery(): void public function resetQuery(): void
{ {
// Reset strings and booleans $this->state = new State();
foreach($this->stringVars as $var) $this->explain = FALSE;
{
$this->$var = NULL;
}
// Reset arrays
foreach($this->arrayVars as $var)
{
$this->$var = [];
}
} }
/**
* Set values in the class, with either an array or key value pair
*
* @param array $var
* @param mixed $key
* @param mixed $val
* @param int $valType
* @return array
*/
protected function _mixedSet(array &$var, $key, $val=NULL, int $valType=self::BOTH): array
{
$arg = (is_scalar($key) && is_scalar($val))
? [$key => $val]
: $key;
foreach($arg as $k => $v)
{
if (\in_array($valType, [self::KEY, self::VALUE], TRUE))
{
$var[] = ($valType === self::KEY)
? $k
: $v;
}
else
{
$var[$k] = $v;
}
}
return $var;
}
/** /**
* Method to simplify select_ methods * Method to simplify select_ methods
@ -1156,11 +1000,11 @@ class QueryBuilder implements QueryBuilderInterface {
$val = "%{$val}%"; $val = "%{$val}%";
} }
$conj = empty($this->queryMap) ? ' WHERE ' : " {$conj} "; $conj = empty($this->state->getQueryMap()) ? ' WHERE ' : " {$conj} ";
$this->_appendMap($conj, $like, 'like'); $this->state->appendMap($conj, $like, 'like');
// Add to the values array // Add to the values array
$this->whereValues[] = $val; $this->state->appendWhereValues($val);
return $this; return $this;
} }
@ -1190,10 +1034,12 @@ class QueryBuilder implements QueryBuilderInterface {
$item .= (count($fArray) === 1) ? '=?' : " {$fArray[1]} ?"; $item .= (count($fArray) === 1) ? '=?' : " {$fArray[1]} ?";
// Put in the having map // Put in the having map
$this->havingMap[] = [ $this->state->appendHavingMap([
'conjunction' => ( ! empty($this->havingMap)) ? " {$conj} " : ' HAVING ', 'conjunction' => empty($this->state->getHavingMap())
? ' HAVING '
: " {$conj} ",
'string' => $item 'string' => $item
]; ]);
} }
return $this; return $this;
@ -1209,8 +1055,23 @@ class QueryBuilder implements QueryBuilderInterface {
protected function _where($key, $val=[]): array protected function _where($key, $val=[]): array
{ {
$where = []; $where = [];
$this->_mixedSet($where, $key, $val); $pairs = [];
$this->_mixedSet($this->whereValues, $key, $val, self::VALUE);
if (is_scalar($key))
{
$pairs[$key] = $val;
}
else
{
$pairs = $key;
}
foreach($pairs as $k => $v)
{
$where[$k] = $v;
$this->state->appendWhereValues($v);
}
return $where; return $where;
} }
@ -1227,6 +1088,8 @@ class QueryBuilder implements QueryBuilderInterface {
// Create key/value placeholders // Create key/value placeholders
foreach($this->_where($key, $values) as $f => $val) foreach($this->_where($key, $values) as $f => $val)
{ {
$queryMap = $this->state->getQueryMap();
// Split each key by spaces, in case there // Split each key by spaces, in case there
// is an operator such as >, <, !=, etc. // is an operator such as >, <, !=, etc.
$fArray = explode(' ', trim($f)); $fArray = explode(' ', trim($f));
@ -1235,11 +1098,11 @@ class QueryBuilder implements QueryBuilderInterface {
// Simple key value, or an operator // Simple key value, or an operator
$item .= (count($fArray) === 1) ? '=?' : " {$fArray[1]} ?"; $item .= (count($fArray) === 1) ? '=?' : " {$fArray[1]} ?";
$lastItem = end($this->queryMap); $lastItem = end($queryMap);
// Determine the correct conjunction // Determine the correct conjunction
$conjunctionList = array_column($this->queryMap, 'conjunction'); $conjunctionList = array_column($queryMap, 'conjunction');
if (empty($this->queryMap) || ( ! regex_in_array($conjunctionList, "/^ ?\n?WHERE/i"))) if (empty($queryMap) || ( ! regex_in_array($conjunctionList, "/^ ?\n?WHERE/i")))
{ {
$conj = "\nWHERE "; $conj = "\nWHERE ";
} }
@ -1252,7 +1115,7 @@ class QueryBuilder implements QueryBuilderInterface {
$conj = " {$defaultConj} "; $conj = " {$defaultConj} ";
} }
$this->_appendMap($conj, $item, 'where'); $this->state->appendMap($conj, $item, 'where');
} }
return $this; return $this;
@ -1271,16 +1134,12 @@ class QueryBuilder implements QueryBuilderInterface {
{ {
$key = $this->driver->quoteIdent($key); $key = $this->driver->quoteIdent($key);
$params = array_fill(0, count($val), '?'); $params = array_fill(0, count($val), '?');
$this->state->appendWhereValues($val);
foreach($val as $v) $conjunction = empty($this->state->getQueryMap()) ? ' WHERE ' : " {$conj} ";
{
$this->whereValues[] = $v;
}
$conjunction = ( ! empty($this->queryMap)) ? " {$conj} " : ' WHERE ';
$str = $key . " {$in} (".implode(',', $params).') '; $str = $key . " {$in} (".implode(',', $params).') ';
$this->_appendMap($conjunction, $str, 'where_in'); $this->state->appendMap($conjunction, $str, 'where_in');
return $this; return $this;
} }
@ -1304,7 +1163,7 @@ class QueryBuilder implements QueryBuilderInterface {
if ($vals === NULL) if ($vals === NULL)
{ {
$vals = array_merge($this->values, (array) $this->whereValues); $vals = array_merge($this->state->getValues(), (array) $this->state->getWhereValues());
} }
$startTime = microtime(TRUE); $startTime = microtime(TRUE);
@ -1328,23 +1187,6 @@ class QueryBuilder implements QueryBuilderInterface {
return $res; return $res;
} }
/**
* Add an additional set of mapping pairs to a internal map
*
* @param string $conjunction
* @param string $string
* @param string $type
* @return void
*/
protected function _appendMap(string $conjunction = '', string $string = '', string $type = '')
{
$this->queryMap[] = [
'type' => $type,
'conjunction' => $conjunction,
'string' => $string
];
}
/** /**
* Convert the prepared statement into readable sql * Convert the prepared statement into readable sql
* *
@ -1391,18 +1233,20 @@ class QueryBuilder implements QueryBuilderInterface {
*/ */
protected function _compileType(string $type='', string $table=''): string protected function _compileType(string $type='', string $table=''): string
{ {
$setArrayKeys = $this->state->getSetArrayKeys();
switch($type) switch($type)
{ {
case 'insert': case 'insert':
$paramCount = count($this->setArrayKeys); $paramCount = count($setArrayKeys);
$params = array_fill(0, $paramCount, '?'); $params = array_fill(0, $paramCount, '?');
$sql = "INSERT INTO {$table} (" $sql = "INSERT INTO {$table} ("
. implode(',', $this->setArrayKeys) . implode(',', $setArrayKeys)
. ")\nVALUES (".implode(',', $params).')'; . ")\nVALUES (".implode(',', $params).')';
break; break;
case 'update': case 'update':
$sql = "UPDATE {$table}\nSET {$this->setString}"; $setString = $this->state->getSetString();
$sql = "UPDATE {$table}\nSET {$setString}";
break; break;
case 'replace': case 'replace':
@ -1416,13 +1260,16 @@ class QueryBuilder implements QueryBuilderInterface {
// Get queries // Get queries
default: default:
$sql = "SELECT * \nFROM {$this->fromString}"; $fromString = $this->state->getFromString();
$selectString = $this->state->getSelectString();
$sql = "SELECT * \nFROM {$fromString}";
// Set the select string // Set the select string
if ( ! empty($this->selectString)) if ( ! empty($selectString))
{ {
// Replace the star with the selected fields // Replace the star with the selected fields
$sql = str_replace('*', $this->selectString, $sql); $sql = str_replace('*', $selectString, $sql);
} }
break; break;
} }
@ -1452,7 +1299,8 @@ class QueryBuilder implements QueryBuilderInterface {
// Set each type of subclause // Set each type of subclause
foreach($clauses as $clause) foreach($clauses as $clause)
{ {
$param = $this->$clause; $func = 'get' . ucFirst($clause);
$param = $this->state->$func();
if (\is_array($param)) if (\is_array($param))
{ {
foreach($param as $q) foreach($param as $q)
@ -1467,9 +1315,10 @@ class QueryBuilder implements QueryBuilderInterface {
} }
// Set the limit via the class variables // Set the limit via the class variables
if (is_numeric($this->limit)) $limit = $this->state->getLimit();
if (is_numeric($limit))
{ {
$sql = $this->sql->limit($sql, $this->limit, $this->offset); $sql = $this->sql->limit($sql, $limit, $this->state->getOffset());
} }
// See if the query plan, rather than the // See if the query plan, rather than the

428
src/State.php Normal file
View File

@ -0,0 +1,428 @@
<?php declare(strict_types=1);
/**
* Query
*
* SQL Query Builder / Database Abstraction Layer
*
* PHP version 7.1
*
* @package Query
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2012 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link https://git.timshomepage.net/aviat4ion/Query
*/
namespace Query;
/**
* Query builder state
*/
class State {
// --------------------------------------------------------------------------
// ! SQL Clause Strings
// --------------------------------------------------------------------------
/**
* Compiled 'select' clause
* @var string
*/
protected $selectString = '';
/**
* Compiled 'from' clause
* @var string
*/
protected $fromString = '';
/**
* Compiled arguments for insert / update
* @var string
*/
protected $setString = '';
/**
* Order by clause
* @var string
*/
protected $orderString = '';
/**
* Group by clause
* @var string
*/
protected $groupString = '';
// --------------------------------------------------------------------------
// ! SQL Clause Arrays
// --------------------------------------------------------------------------
/**
* Keys for insert/update statement
* @var array
*/
protected $setArrayKeys = [];
/**
* Key/val pairs for order by clause
* @var array
*/
protected $orderArray = [];
/**
* Key/val pairs for group by clause
* @var array
*/
protected $groupArray = [];
// --------------------------------------------------------------------------
// ! Other Class vars
// --------------------------------------------------------------------------
/**
* Values to apply to prepared statements
* @var array
*/
protected $values = [];
/**
* Values to apply to where clauses in prepared statements
* @var array
*/
protected $whereValues = [];
/**
* Value for limit string
* @var int
*/
protected $limit;
/**
* Value for offset in limit string
* @var string|false
*/
protected $offset = FALSE;
/**
* Query component order mapping
* for complex select queries
*
* Format:
* array(
* 'type' => 'where',
* 'conjunction' => ' AND ',
* 'string' => 'k=?'
* )
*
* @var array
*/
protected $queryMap = [];
/**
* Map for having clause
* @var array
*/
protected $havingMap = [];
// --------------------------------------------------------------------------
/**
* @param string $str
* @return State
*/
public function setSelectString(string $str): self
{
$this->selectString = $str;
return $this;
}
/**
* @return string
*/
public function getSelectString(): string
{
return $this->selectString;
}
/**
* @param string $str
* @return State
*/
public function appendSelectString(string $str): self
{
$this->selectString .= $str;
return $this;
}
/**
* @return string
*/
public function getFromString(): string
{
return $this->fromString;
}
/**
* @param string $fromString
* @return State
*/
public function setFromString(string $fromString): State
{
$this->fromString = $fromString;
return $this;
}
/**
* @return string
*/
public function getSetString(): string
{
return $this->setString;
}
/**
* @param string $setString
* @return State
*/
public function setSetString(string $setString): State
{
$this->setString = $setString;
return $this;
}
/**
* @return string
*/
public function getOrderString(): string
{
return $this->orderString;
}
/**
* @param string $orderString
* @return State
*/
public function setOrderString(string $orderString): State
{
$this->orderString = $orderString;
return $this;
}
/**
* @return string
*/
public function getGroupString(): string
{
return $this->groupString;
}
/**
* @param string $groupString
* @return State
*/
public function setGroupString(string $groupString): State
{
$this->groupString = $groupString;
return $this;
}
/**
* @return array
*/
public function getSetArrayKeys(): array
{
return $this->setArrayKeys;
}
/**
* @param array $setArrayKeys
* @return State
*/
public function appendSetArrayKeys(array $setArrayKeys): State
{
$this->setArrayKeys = array_merge($this->setArrayKeys, $setArrayKeys);
return $this;
}
/**
* @param array $setArrayKeys
* @return State
*/
public function setSetArrayKeys(array $setArrayKeys): State
{
$this->setArrayKeys = $setArrayKeys;
return $this;
}
/**
* @return array
*/
public function getOrderArray(): array
{
return $this->orderArray;
}
/**
* @param string $key
* @param mixed $orderArray
* @return State
*/
public function setOrderArray(string $key, $orderArray): State
{
$this->orderArray[$key] = $orderArray;
return $this;
}
/**
* @return array
*/
public function getGroupArray(): array
{
return $this->groupArray;
}
/**
* @param array $groupArray
* @return State
*/
public function setGroupArray(array $groupArray): State
{
$this->groupArray = $groupArray;
return $this;
}
/**
* @param string $groupArray
* @return State
*/
public function appendGroupArray(string $groupArray): State
{
$this->groupArray[] = $groupArray;
return $this;
}
/**
* @return array
*/
public function getValues(): array
{
return $this->values;
}
/**
* @param array $values
* @return State
*/
public function appendValues(array $values): State
{
$this->values = array_merge($this->values, $values);
return $this;
}
/**
* @return array
*/
public function getWhereValues(): array
{
return $this->whereValues;
}
/**
* @param mixed $val
* @return State
*/
public function appendWhereValues($val): State
{
if (\is_array($val))
{
foreach($val as $v)
{
$this->whereValues[] = $v;
}
return $this;
}
$this->whereValues[] = $val;
return $this;
}
/**
* @return int
*/
public function getLimit(): ?int
{
return $this->limit;
}
/**
* @param int $limit
* @return State
*/
public function setLimit(int $limit): State
{
$this->limit = $limit;
return $this;
}
/**
* @return string|false
*/
public function getOffset()
{
return $this->offset;
}
/**
* @param string|false $offset
* @return State
*/
public function setOffset($offset): State
{
$this->offset = $offset;
return $this;
}
/**
* @return array
*/
public function getQueryMap(): array
{
return $this->queryMap;
}
/**
* Add an additional set of mapping pairs to a internal map
*
* @param string $conjunction
* @param string $string
* @param string $type
* @return State
*/
public function appendMap(string $conjunction = '', string $string = '', string $type = ''): self
{
$this->queryMap[] = [
'type' => $type,
'conjunction' => $conjunction,
'string' => $string
];
return $this;
}
/**
* @return array
*/
public function getHavingMap(): array
{
return $this->havingMap;
}
/**
* @param array $item
* @return State
*/
public function appendHavingMap(array $item): State
{
$this->havingMap[] = $item;
return $this;
}
}

View File

@ -31,11 +31,11 @@ namespace Query\Tests {
*/ */
abstract class TestCase extends \UnitTestCase abstract class TestCase extends \UnitTestCase
{ {
public function __construct() public function __construct()
{ {
$class = \get_class($this); $class = \get_class($this);
echo '<pre>';
echo 'Ran test suite: ' . $class . '<br />'; echo 'Ran test suite: ' . $class . '<br />';
if (method_exists($class, 'setupBeforeClass')) { if (method_exists($class, 'setupBeforeClass')) {
@ -49,6 +49,8 @@ namespace Query\Tests {
{ {
$class = \get_class($this); $class = \get_class($this);
echo '</pre>';
if (method_exists($class, 'tearDownAfterClass')) { if (method_exists($class, 'tearDownAfterClass')) {
$class::tearDownAfterClass(); $class::tearDownAfterClass();
} }