Do you wish to register an account?
Browse Source

Update types for limit clauses, misc improvements

tags/v3.0.0^2
Timothy Warren 3 months ago
parent
commit
c67fabd1f7
18 changed files with 803 additions and 813 deletions
  1. +4
    -4
      composer.json
  2. +8
    -7
      src/ConnectionManager.php
  3. +6
    -5
      src/Drivers/AbstractDriver.php
  4. +2
    -2
      src/Drivers/AbstractSQL.php
  5. +2
    -1
      src/Drivers/Mysql/Driver.php
  6. +3
    -3
      src/Drivers/Mysql/SQL.php
  7. +9
    -7
      src/Drivers/Mysql/Util.php
  8. +2
    -1
      src/Drivers/Pgsql/Util.php
  9. +2
    -2
      src/Drivers/SQLInterface.php
  10. +1
    -1
      src/Drivers/Sqlite/Driver.php
  11. +1
    -1
      src/Drivers/Sqlite/Util.php
  12. +28
    -0
      src/MapType.php
  13. +86
    -687
      src/QueryBuilder.php
  14. +618
    -0
      src/QueryBuilderBase.php
  15. +10
    -18
      src/QueryBuilderInterface.php
  16. +2
    -0
      src/QueryType.php
  17. +17
    -69
      src/State.php
  18. +2
    -5
      src/common.php

+ 4
- 4
composer.json View File

@@ -34,14 +34,14 @@
"require-dev": {
"consolidation/robo": "^2.0.0",
"monolog/monolog": "^2.0.1",
"phploc/phploc": "^6.0",
"phploc/phploc": "^5.0",
"phpmd/phpmd": "^2.8",
"phpstan/phpstan": "^0.12.2",
"phpunit/phpunit": "^9.1",
"sebastian/phpcpd": "^5",
"phpunit/phpunit": "^8.5",
"sebastian/phpcpd": "^4.1",
"simpletest/simpletest": "^1.1",
"squizlabs/php_codesniffer": "^3.0.0",
"theseer/phpdox": "*"
"theseer/phpdox": "^0.12.0"
},
"autoload": {
"psr-4": {


+ 8
- 7
src/ConnectionManager.php View File

@@ -16,6 +16,7 @@
namespace Query;

use DomainException;
use stdClass;

/**
* Connection manager class to manage connections for the
@@ -33,7 +34,7 @@ final class ConnectionManager {
* Class instance variable
* @var ConnectionManager|null
*/
private static $instance;
private static ?ConnectionManager $instance = NULL;

/**
* Private constructor to prevent multiple instances
@@ -119,7 +120,7 @@ final class ConnectionManager {
/**
* Parse the passed parameters and return a connection
*
* @param object|array $params
* @param array|object $params
* @throws Exception\BadDBDriverException
* @return QueryBuilderInterface
*/
@@ -161,13 +162,13 @@ final class ConnectionManager {
/**
* Parses params into a dsn and option array
*
* @param object | array $params
* @param array|object $rawParams
* @return array
* @throws Exception\BadDBDriverException
*/
public function parseParams($params): array
public function parseParams($rawParams): array
{
$params = (object) $params;
$params = (object) $rawParams;
$params->type = strtolower($params->type);
$dbType = ($params->type === 'postgresql') ? 'pgsql' : $params->type;
$dbType = ucfirst($dbType);
@@ -205,10 +206,10 @@ final class ConnectionManager {
*
* @codeCoverageIgnore
* @param string $dbType
* @param array|object $params
* @param stdClass $params
* @return string
*/
private function createDsn(string $dbType, $params): string
private function createDsn(string $dbType, stdClass $params): string
{
$pairs = [];



+ 6
- 5
src/Drivers/AbstractDriver.php View File

@@ -20,6 +20,7 @@ use function dbFilter;
use InvalidArgumentException;
use PDO;
use PDOStatement;
use function is_string;

/**
* Base Database class
@@ -52,7 +53,7 @@ abstract class AbstractDriver
* Reference to sql class
* @var SQLInterface
*/
protected SQLInterface $sql;
protected SQLInterface $driverSQL;

/**
* Reference to util class
@@ -110,7 +111,7 @@ abstract class AbstractDriver
$sqlClass = __NAMESPACE__ . "\\{$driver}\\SQL";
$utilClass = __NAMESPACE__ . "\\{$driver}\\Util";

$this->sql = new $sqlClass();
$this->driverSQL = new $sqlClass();
$this->util = new $utilClass($this);
}

@@ -168,7 +169,7 @@ abstract class AbstractDriver
*/
public function getSql(): SQLInterface
{
return $this->sql;
return $this->driverSQL;
}

/**
@@ -494,7 +495,7 @@ abstract class AbstractDriver
public function driverQuery($query, $filteredIndex=TRUE): ?array
{
// Call the appropriate method, if it exists
if (is_string($query) && method_exists($this->sql, $query))
if (is_string($query) && method_exists($this->driverSQL, $query))
{
$query = $this->getSql()->$query();
}
@@ -687,7 +688,7 @@ abstract class AbstractDriver
// and is not already quoted before quoting
// that value, otherwise, return the original value
return (
\is_string($str)
is_string($str)
&& strpos($str, $this->escapeCharOpen) !== 0
&& strrpos($str, $this->escapeCharClose) !== 0
)


+ 2
- 2
src/Drivers/AbstractSQL.php View File

@@ -25,10 +25,10 @@ abstract class AbstractSQL implements SQLInterface {
*
* @param string $sql
* @param int $limit
* @param int|bool $offset
* @param int $offset
* @return string
*/
public function limit(string $sql, int $limit, $offset=FALSE): string
public function limit(string $sql, int $limit, ?int $offset=NULL): string
{
$sql .= "\nLIMIT {$limit}";



+ 2
- 1
src/Drivers/Mysql/Driver.php View File

@@ -17,6 +17,7 @@ namespace Query\Drivers\Mysql;

use PDO;
use Query\Drivers\AbstractDriver;
use function defined;

/**
* MySQL specific class
@@ -49,7 +50,7 @@ class Driver extends AbstractDriver {
public function __construct(string $dsn, string $username=NULL, string $password=NULL, array $options=[])
{
// Set the charset to UTF-8
if (\defined('\\PDO::MYSQL_ATTR_INIT_COMMAND'))
if (defined('\\PDO::MYSQL_ATTR_INIT_COMMAND'))
{
$options = array_merge($options, [
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES UTF-8 COLLATE 'UTF-8'",


+ 3
- 3
src/Drivers/Mysql/SQL.php View File

@@ -30,7 +30,7 @@ class SQL extends AbstractSQL {
* @param int|boolean $offset
* @return string
*/
public function limit(string $sql, int $limit, $offset=FALSE): string
public function limit(string $sql, int $limit, ?int $offset=NULL): string
{
if ( ! is_numeric($offset))
{
@@ -166,7 +166,7 @@ SQL;
}

/**
* SQL to show infromation about columns in a table
* SQL to show information about columns in a table
*
* @param string $table
* @return string
@@ -186,7 +186,7 @@ SQL;
public function fkList(string $table): string
{
return <<<SQL
SELECT DISTINCT
SELECT DISTINCT
`kcu`.`COLUMN_NAME` as `child_column`,
`kcu`.`REFERENCED_TABLE_NAME` as `parent_table`,
`kcu`.`REFERENCED_COLUMN_NAME` as `parent_column`,


+ 9
- 7
src/Drivers/Mysql/Util.php View File

@@ -33,7 +33,8 @@ class Util extends AbstractUtil {
$string = [];

// Get databases
$dbs = $this->getDriver()->getDbs();
$driver = $this->getDriver();
$dbs = $driver->getDbs();

foreach($dbs as &$d)
{
@@ -46,11 +47,11 @@ class Util extends AbstractUtil {
// @codeCoverageIgnoreEnd

// Get the list of tables
$tables = $this->getDriver()->driverQuery("SHOW TABLES FROM `{$d}`", TRUE);
$tables = $driver->driverQuery("SHOW TABLES FROM `{$d}`", TRUE);

foreach($tables as $table)
{
$array = $this->getDriver()->driverQuery("SHOW CREATE TABLE `{$d}`.`{$table}`", FALSE);
$array = $driver->driverQuery("SHOW CREATE TABLE `{$d}`.`{$table}`", FALSE);
$row = current($array);

if ( ! isset($row['Create Table']))
@@ -72,9 +73,10 @@ class Util extends AbstractUtil {
* @param array $exclude
* @return string
*/
public function backupData($exclude=[]): string
public function backupData(array $exclude=[]): string
{
$tables = $this->getDriver()->getTables();
$driver = $this->getDriver();
$tables = $driver->getTables();

// Filter out the tables you don't want
if( ! empty($exclude))
@@ -88,7 +90,7 @@ class Util extends AbstractUtil {
foreach($tables as $t)
{
$sql = "SELECT * FROM `{$t}`";
$res = $this->getDriver()->query($sql);
$res = $driver->query($sql);
$rows = $res->fetchAll(PDO::FETCH_ASSOC);

// Skip empty tables
@@ -110,7 +112,7 @@ class Util extends AbstractUtil {
// Workaround for Quercus
foreach($row as &$r)
{
$r = $this->getDriver()->quote($r);
$r = $driver->quote($r);
}
unset($r);
$row = array_map('trim', $row);


+ 2
- 1
src/Drivers/Pgsql/Util.php View File

@@ -15,6 +15,7 @@
*/
namespace Query\Drivers\Pgsql;

use PDO;
use Query\Drivers\AbstractUtil;

/**
@@ -56,7 +57,7 @@ class Util extends AbstractUtil {
{
$sql = 'SELECT * FROM "'.trim($t).'"';
$res = $this->getDriver()->query($sql);
$objRes = $res->fetchAll(\PDO::FETCH_ASSOC);
$objRes = $res->fetchAll(PDO::FETCH_ASSOC);

// Don't add to the file if the table is empty
if (count($objRes) < 1)


+ 2
- 2
src/Drivers/SQLInterface.php View File

@@ -25,10 +25,10 @@ interface SQLInterface {
*
* @param string $sql
* @param int $limit
* @param int|bool $offset
* @param int|null $offset
* @return string
*/
public function limit(string $sql, int $limit, $offset=FALSE): string;
public function limit(string $sql, int $limit, ?int $offset=NULL): string;

/**
* Modify the query to get the query plan


+ 1
- 1
src/Drivers/Sqlite/Driver.php View File

@@ -68,7 +68,7 @@ class Driver extends AbstractDriver {
*/
public function getTables(): array
{
$sql = $this->sql->tableList();
$sql = $this->getSql()->tableList();
$res = $this->query($sql);
return dbFilter($res->fetchAll(PDO::FETCH_ASSOC), 'name');
}


+ 1
- 1
src/Drivers/Sqlite/Util.php View File

@@ -57,7 +57,7 @@ class Util extends AbstractUtil {

unset($res);

// If the row is empty, continue;
// If the row is empty, continue
if (empty($objRes))
{
continue;


+ 28
- 0
src/MapType.php View File

@@ -0,0 +1,28 @@
<?php declare(strict_types=1);
/**
* Query
*
* SQL Query Builder / Database Abstraction Layer
*
* PHP version 7.4
*
* @package Query
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2012 - 2020 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link https://git.timshomepage.net/aviat/Query
* @version 3.0.0
*/
namespace Query;

/**
* 'Enum' of query map types
*/
class MapType {
public const GROUP_END = 'group_end';
public const GROUP_START = 'group_start';
public const JOIN = 'join';
public const LIKE = 'like';
public const WHERE = 'where';
public const WHERE_IN = 'where_in';
}

+ 86
- 687
src/QueryBuilder.php
File diff suppressed because it is too large
View File


+ 618
- 0
src/QueryBuilderBase.php View File

@@ -0,0 +1,618 @@
<?php declare(strict_types=1);
/**
* Query
*
* SQL Query Builder / Database Abstraction Layer
*
* PHP version 7.4
*
* @package Query
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2012 - 2020 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link https://git.timshomepage.net/aviat/Query
* @version 3.0.0
*/
namespace Query;

use function regexInArray;

use BadMethodCallException;
use PDO;
use PDOStatement;
use Query\Drivers\DriverInterface;

/**
* @method affectedRows(): int
* @method beginTransaction(): bool
* @method commit(): bool
* @method errorCode(): string
* @method errorInfo(): array
* @method exec(string $statement): int
* @method getAttribute(int $attribute)
* @method getColumns(string $table): array | null
* @method getDbs(): array | null
* @method getFks(string $table): array | null
* @method getFunctions(): array | null
* @method getIndexes(string $table): array | null
* @method getLastQuery(): string
* @method getProcedures(): array | null
* @method getSchemas(): array | null
* @method getSequences(): array | null
* @method getSystemTables(): array | null
* @method getTables(): array
* @method getTriggers(): array | null
* @method getTypes(): array | null
* @method getUtil(): \Query\Drivers\AbstractUtil
* @method getVersion(): string
* @method getViews(): array | null
* @method inTransaction(): bool
* @method lastInsertId(string $name = NULL): string
* @method numRows(): int | null
* @method prepare(string $statement, array $driver_options = []): PDOStatement
* @method prepareExecute(string $sql, array $params): PDOStatement
* @method prepareQuery(string $sql, array $data): PDOStatement
* @method query(string $statement): PDOStatement
* @method quote(string $string, int $parameter_type = PDO::PARAM_STR): string
* @method rollback(): bool
* @method setAttribute(int $attribute, $value): bool
* @method setTablePrefix(string $prefix): void
* @method truncate(string $table): PDOStatement
*/
class QueryBuilderBase {

/**
* Convenience property for connection management
* @var string
*/
public string $connName = '';

/**
* List of queries executed
* @var array
*/
public array $queries = [
'total_time' => 0
];

/**
* Whether to do only an explain on the query
* @var bool
*/
protected bool $explain = FALSE;

/**
* Whether to return data from a modification query
* @var bool
*/
protected bool $returning = FALSE;

/**
* The current database driver
* @var DriverInterface
*/
protected ?DriverInterface $driver;

/**
* Query parser class instance
* @var QueryParser
*/
protected QueryParser $parser;

/**
* Query Builder state
* @var State
*/
protected State $state;

// --------------------------------------------------------------------------
// ! Methods
// --------------------------------------------------------------------------

/**
* Constructor
*
* @param DriverInterface $driver
* @param QueryParser $parser
*/
public function __construct(DriverInterface $driver, QueryParser $parser)
{
// Inject driver and parser
$this->driver = $driver;
$this->parser = $parser;

// Create new State object
$this->state = new State();
}

/**
* Destructor
* @codeCoverageIgnore
*/
public function __destruct()
{
$this->driver = NULL;
}

/**
* Calls a function further down the inheritance chain.
* 'Implements' methods on the driver object
*
* @param string $name
* @param array $params
* @return mixed
* @throws BadMethodCallException
*/
public function __call(string $name, array $params)
{
if (method_exists($this->driver, $name))
{
return $this->driver->$name(...$params);
}

throw new BadMethodCallException('Method does not exist');
}

/**
* Clear out the class variables, so the next query can be run
*
* @return void
*/
public function resetQuery(): void
{
$this->state = new State();
$this->explain = FALSE;
$this->returning = FALSE;
}

/**
* Method to simplify select_ methods
*
* @param string $field
* @param string|bool $as
* @return string
*/
protected function _select(string $field, $as = FALSE): string
{
// Escape the identifiers
$field = $this->driver->quoteIdent($field);

if ( ! \is_string($as))
{
// @codeCoverageIgnoreStart
return $field;
// @codeCoverageIgnoreEnd
}

$as = $this->driver->quoteIdent($as);
return "({$field}) AS {$as} ";
}

/**
* Helper function for returning sql strings
*
* @param string $type
* @param string $table
* @param bool $reset
* @return string
*/
protected function _getCompile(string $type, string $table, bool $reset): string
{
$sql = $this->_compile($type, $table);

// Reset the query builder for the next query
if ($reset)
{
$this->resetQuery();
}

return $sql;
}

/**
* Simplify 'like' methods
*
* @param string $field
* @param mixed $val
* @param string $pos
* @param string $like
* @param string $conj
* @return self
*/
protected function _like(string $field, $val, string $pos, string $like = 'LIKE', string $conj = 'AND'): self
{
$field = $this->driver->quoteIdent($field);

// Add the like string into the order map
$like = $field . " {$like} ?";

if ($pos === 'before')
{
$val = "%{$val}";
} elseif ($pos === 'after')
{
$val = "{$val}%";
} else
{
$val = "%{$val}%";
}

$conj = empty($this->state->getQueryMap()) ? ' WHERE ' : " {$conj} ";
$this->state->appendMap($conj, $like, MapType::LIKE);

// Add to the values array
$this->state->appendWhereValues($val);

return $this;
}

/**
* Simplify building having clauses
*
* @param mixed $key
* @param mixed $values
* @param string $conj
* @return self
*/
protected function _having($key, $values = [], string $conj = 'AND'): self
{
$where = $this->_where($key, $values);

// Create key/value placeholders
foreach ($where as $f => $val)
{
// Split each key by spaces, in case there
// is an operator such as >, <, !=, etc.
$fArray = explode(' ', trim($f));

$item = $this->driver->quoteIdent($fArray[0]);

// Simple key value, or an operator
$item .= (count($fArray) === 1) ? '=?' : " {$fArray[1]} ?";

// Put in the having map
$this->state->appendHavingMap([
'conjunction' => empty($this->state->getHavingMap())
? ' HAVING '
: " {$conj} ",
'string' => $item
]);
}

return $this;
}

/**
* Do all the redundant stuff for where/having type methods
*
* @param mixed $key
* @param mixed $val
* @return array
*/
protected function _where($key, $val = []): array
{
$where = [];
$pairs = [];

if (is_scalar($key))
{
$pairs[$key] = $val;
} else
{
$pairs = $key;
}

foreach ($pairs as $k => $v)
{
$where[$k] = $v;
$this->state->appendWhereValues($v);
}

return $where;
}

/**
* Simplify generating where string
*
* @param mixed $key
* @param mixed $values
* @param string $defaultConj
* @return self
*/
protected function _whereString($key, $values = [], string $defaultConj = 'AND'): self
{
// Create key/value placeholders
foreach ($this->_where($key, $values) as $f => $val)
{
$queryMap = $this->state->getQueryMap();

// Split each key by spaces, in case there
// is an operator such as >, <, !=, etc.
$fArray = explode(' ', trim($f));

$item = $this->driver->quoteIdent($fArray[0]);

// Simple key value, or an operator
$item .= (count($fArray) === 1) ? '=?' : " {$fArray[1]} ?";
$lastItem = end($queryMap);

// Determine the correct conjunction
$conjunctionList = array_column($queryMap, 'conjunction');
if (empty($queryMap) || ( ! regexInArray($conjunctionList, "/^ ?\n?WHERE/i")))
{
$conj = "\nWHERE ";
} elseif ($lastItem['type'] === 'group_start')
{
$conj = '';
} else
{
$conj = " {$defaultConj} ";
}

$this->state->appendMap($conj, $item, MapType::WHERE);
}

return $this;
}

/**
* Simplify where_in methods
*
* @param mixed $key
* @param mixed $val
* @param string $in - The (not) in fragment
* @param string $conj - The where in conjunction
* @return self
*/
protected function _whereIn($key, $val = [], string $in = 'IN', string $conj = 'AND'): self
{
$key = $this->driver->quoteIdent($key);
$params = array_fill(0, count($val), '?');
$this->state->appendWhereValues($val);

$conjunction = empty($this->state->getQueryMap()) ? ' WHERE ' : " {$conj} ";
$str = $key . " {$in} (" . implode(',', $params) . ') ';

$this->state->appendMap($conjunction, $str, MapType::WHERE_IN);

return $this;
}

/**
* Executes the compiled query
*
* @param string $type
* @param string $table
* @param string $sql
* @param array|null $vals
* @param boolean $reset
* @return PDOStatement
*/
protected function _run(string $type, string $table, string $sql = NULL, array $vals = NULL, bool $reset = TRUE): PDOStatement
{
if ($sql === NULL)
{
$sql = $this->_compile($type, $table);
}

if ($vals === NULL)
{
$vals = array_merge($this->state->getValues(), $this->state->getWhereValues());
}

$startTime = microtime(TRUE);

$res = empty($vals)
? $this->driver->query($sql)
: $this->driver->prepareExecute($sql, $vals);

$endTime = microtime(TRUE);
$totalTime = number_format($endTime - $startTime, 5);

// Add this query to the list of executed queries
$this->_appendQuery($vals, $sql, (int)$totalTime);

// Reset class state for next query
if ($reset)
{
$this->resetQuery();
}

return $res;
}

/**
* Convert the prepared statement into readable sql
*
* @param array $values
* @param string $sql
* @param int $totalTime
* @return void
*/
protected function _appendQuery(array $values, string $sql, int $totalTime): void
{
$evals = is_array($values) ? $values : [];
$esql = str_replace('?', '%s', $sql);

// Quote string values
foreach ($evals as &$v)
{
$v = ( ! is_numeric($v))
? htmlentities($this->driver->quote($v), ENT_NOQUOTES, 'utf-8')
: $v;
}
unset($v);

// Add the query onto the array of values to pass
// as arguments to sprintf
array_unshift($evals, $esql);

// Add the interpreted query to the list of executed queries
$this->queries[] = [
'time' => $totalTime,
'sql' => sprintf(...$evals)
];

$this->queries['total_time'] += $totalTime;

// Set the last query to get rowcounts properly
$this->driver->setLastQuery($sql);
}

/**
* Sub-method for generating sql strings
*
* @codeCoverageIgnore
* @param string $type
* @param string $table
* @return string
*/
protected function _compileType(string $type = QueryType::SELECT, string $table = ''): string
{
$setArrayKeys = $this->state->getSetArrayKeys();
switch ($type)
{
case QueryType::INSERT:
$paramCount = count($setArrayKeys);
$params = array_fill(0, $paramCount, '?');
$sql = "INSERT INTO {$table} ("
. implode(',', $setArrayKeys)
. ")\nVALUES (" . implode(',', $params) . ')';
break;

case QueryType::UPDATE:
$setString = $this->state->getSetString();
$sql = "UPDATE {$table}\nSET {$setString}";
break;

case QueryType::DELETE:
$sql = "DELETE FROM {$table}";
break;

case QueryType::SELECT:
default:
$fromString = $this->state->getFromString();
$selectString = $this->state->getSelectString();

$sql = "SELECT * \nFROM {$fromString}";

// Set the select string
if ( ! empty($selectString))
{
// Replace the star with the selected fields
$sql = str_replace('*', $selectString, $sql);
}
break;
}

return $sql;
}

/**
* String together the sql statements for sending to the db
*
* @param string $type
* @param string $table
* @return string
*/
protected function _compile(string $type = '', string $table = ''): string
{
// Get the base clause for the query
$sql = $this->_compileType($type, $this->driver->quoteTable($table));

$clauses = [
'queryMap',
'groupString',
'orderString',
'havingMap',
];

// Set each type of subclause
foreach ($clauses as $clause)
{
$func = 'get' . ucFirst($clause);
$param = $this->state->$func();
if (is_array($param))
{
foreach ($param as $q)
{
$sql .= $q['conjunction'] . $q['string'];
}
} else
{
$sql .= $param;
}
}

// Set the limit via the class variables
$limit = $this->state->getLimit();
if (is_numeric($limit))
{
$sql = $this->driver->getSql()->limit($sql, $limit, $this->state->getOffset());
}

// Set the returning clause, if applicable
$sql = $this->_compileReturning($sql, $type);

// See if the query plan, rather than the
// query data should be returned
if ($this->explain === TRUE)
{
$sql = $this->driver->getSql()->explain($sql);
}

return $sql;
}

/**
* Generate returning clause of query
*
* @param string $sql
* @param string $type
* @return string
*/
protected function _compileReturning(string $sql, string $type): string
{
if ($this->returning === FALSE)
{
return $sql;
}

$rawSelect = $this->state->getSelectString();
$selectString = ($rawSelect === '') ? '*' : $rawSelect;
$returningSQL = $this->driver->returning($sql, $selectString);

if ($returningSQL === $sql)
{
// If the driver doesn't support the returning clause, it returns the original query.
// Fake the same result with a transaction and a select query
if ( ! $this->inTransaction())
{
$this->beginTransaction();
}

// Generate the appropriate select query for the returning clause fallback
switch ($type)
{
case QueryType::INSERT:
// @TODO figure out a good response for insert query
break;

case QueryType::UPDATE:
// @TODO figure out a good response for update query
break;

case QueryType::INSERT_BATCH:
case QueryType::UPDATE_BATCH:
// @TODO figure out a good response for batch queries
break;

default:
// On Delete queries, what would we return?
break;
}
}

return $returningSQL;
}
}

+ 10
- 18
src/QueryBuilderInterface.php View File

@@ -107,14 +107,6 @@ interface QueryBuilderInterface {
*/
public function selectSum(string $field, $as=FALSE): self;

/**
* Add a 'returning' clause to an insert,update, or delete query
*
* @param string $fields
* @return self
*/
public function returning(string $fields = '*'): self;

/**
* Adds the 'distinct' keyword to a query
*
@@ -308,10 +300,10 @@ interface QueryBuilderInterface {
* Set a limit on the current sql statement
*
* @param int $limit
* @param int|bool $offset
* @param int|null $offset
* @return self
*/
public function limit(int $limit, $offset=FALSE): self;
public function limit(int $limit, ?int $offset=NULL): self;

// --------------------------------------------------------------------------
// ! Query Grouping Methods
@@ -364,22 +356,22 @@ interface QueryBuilderInterface {
* execute current compiled query
*
* @param string $table
* @param int|bool $limit
* @param int|bool $offset
* @param int|null $limit
* @param int|null $offset
* @return PDOStatement
*/
public function get(string $table='', $limit=FALSE, $offset=FALSE): PDOStatement;
public function get(string $table='', ?int $limit=NULL, ?int $offset=NULL): PDOStatement;

/**
* Convenience method for get() with a where clause
*
* @param string $table
* @param array $where
* @param int|bool $limit
* @param int|bool $offset
* @param int|null $limit
* @param int|null $offset
* @return PDOStatement
*/
public function getWhere(string $table, $where=[], $limit=FALSE, $offset=FALSE): PDOStatement;
public function getWhere(string $table, $where=[], ?int $limit=NULL, ?int $offset=NULL): PDOStatement;

/**
* Retrieve the number of rows in the selected table
@@ -413,9 +405,9 @@ interface QueryBuilderInterface {
*
* @param string $table
* @param array $data
* @return PDOStatement
* @return PDOStatement | null
*/
public function insertBatch(string $table, $data=[]): PDOStatement;
public function insertBatch(string $table, $data=[]): ?PDOStatement;

/**
* Creates an update clause, and executes it


+ 2
- 0
src/QueryType.php View File

@@ -21,6 +21,8 @@ namespace Query;
class QueryType {
public const SELECT = 'select';
public const INSERT = 'insert';
public const INSERT_BATCH = 'insert_batch';
public const UPDATE = 'update';
public const UPDATE_BATCH = 'update_batch';
public const DELETE = 'delete';
}

+ 17
- 69
src/State.php View File

@@ -15,6 +15,8 @@
*/
namespace Query;

use function is_array;

/**
* Query builder state
*
@@ -28,14 +30,20 @@ namespace Query;
* @method getGroupArray(): array
* @method getValues(): array
* @method getWhereValues(): array
* @method getLimit(): int
* @method getLimit(): int|null
* @method getOffset()
* @method getQueryMap(): array
* @method getHavingMap(): array
*
* @method setSelectString(string): self
* @method setFromString(string): self
* @method setSetString(string): self
* @method setSelectString(string $selectString): self
* @method setFromString(string $fromString): self
* @method setSetString(string $setString): self
* @method setOrderString(string $orderString): self
* @method setGroupString(string $groupString): self
* @method setSetArrayKeys(array $arrayKeys): self
* @method setGroupArray(array $array): self
* @method setLimit(int $limit): self
* @method setOffset(?int $offset): self
*/
class State {
// --------------------------------------------------------------------------
@@ -112,15 +120,15 @@ class State {

/**
* Value for limit string
* @var integer
* @var int
*/
protected int $limit;
protected ?int $limit = NULL;

/**
* Value for offset in limit string
* @var string|false
* @var int
*/
protected $offset = FALSE;
protected ?int $offset = NULL;

/**
* Query component order mapping
@@ -177,26 +185,6 @@ class State {
return $this;
}

/**
* @param string $orderString
* @return State
*/
public function setOrderString(string $orderString): self
{
$this->orderString = $orderString;
return $this;
}

/**
* @param string $groupString
* @return State
*/
public function setGroupString(string $groupString): self
{
$this->groupString = $groupString;
return $this;
}

/**
* @param array $setArrayKeys
* @return State
@@ -207,16 +195,6 @@ class State {
return $this;
}

/**
* @param array $setArrayKeys
* @return State
*/
public function setSetArrayKeys(array $setArrayKeys): self
{
$this->setArrayKeys = $setArrayKeys;
return $this;
}

/**
* @param string $key
* @param mixed $orderArray
@@ -228,16 +206,6 @@ class State {
return $this;
}

/**
* @param array $groupArray
* @return State
*/
public function setGroupArray(array $groupArray): self
{
$this->groupArray = $groupArray;
return $this;
}

/**
* @param string $groupArray
* @return State
@@ -264,7 +232,7 @@ class State {
*/
public function appendWhereValues($val): self
{
if (\is_array($val))
if (is_array($val))
{
foreach($val as $v)
{
@@ -278,26 +246,6 @@ class State {
return $this;
}

/**
* @param int $limit
* @return State
*/
public function setLimit(int $limit): self
{
$this->limit = $limit;
return $this;
}

/**
* @param string|false $offset
* @return State
*/
public function setOffset($offset): self
{
$this->offset = $offset;
return $this;
}

/**
* Add an additional set of mapping pairs to a internal map
*


+ 2
- 5
src/common.php View File

@@ -15,10 +15,8 @@
*/
namespace {

use Query\{
ConnectionManager,
QueryBuilderInterface
};
use Query\ConnectionManager;
use Query\QueryBuilderInterface;

/**
* Global functions that don't really fit anywhere else
@@ -139,6 +137,5 @@ namespace {
// Otherwise, return a new connection
return $manager->connect($paramsObject);
}

}
// End of common.php

Loading…
Cancel
Save