Set consistent code style

This commit is contained in:
Timothy Warren 2023-03-17 15:18:33 -04:00
parent 94d1cbb09b
commit cf2255ce87
27 changed files with 285 additions and 290 deletions

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
use DomainException;
@ -22,8 +23,8 @@ use stdClass;
* Connection manager class to manage connections for the
* Query method
*/
final class ConnectionManager {
final class ConnectionManager
{
/**
* Map of named database connections
*/
@ -91,7 +92,6 @@ final class ConnectionManager {
/**
* Returns the connection specified by the name given
*
* @param string $name
* @throws Exception\NonExistentConnectionException
*/
public function getConnection(string $name = ''): QueryBuilderInterface
@ -113,9 +113,6 @@ final class ConnectionManager {
/**
* Parse the passed parameters and return a connection
*
* @param array|object $params
* @return QueryBuilderInterface
*/
public function connect(array|object $params): QueryBuilderInterface
{
@ -138,7 +135,6 @@ final class ConnectionManager {
// Create Query Builder object
$conn = new QueryBuilder($db, new QueryParser($db));
// Save it for later
if (isset($params->alias))
{
@ -155,9 +151,7 @@ final class ConnectionManager {
/**
* Parses params into a dsn and option array
*
* @param array|object $rawParams
* @throws Exception\BadDBDriverException
* @return array
*/
public function parseParams(array|object $rawParams): array
{
@ -183,7 +177,6 @@ final class ConnectionManager {
// Create the dsn for the database to connect to
$dsn = strtolower($dbType) === 'sqlite' ? $params->file : $this->createDsn($dbType, $params);
return [$dsn, $dbType, $params, $options];
}
@ -209,7 +202,7 @@ final class ConnectionManager {
'prefix' => 'prefix',
'options' => 'options',
'database' => 'database',
'alias' => 'alias'
'alias' => 'alias',
];
foreach ($params as $key => $val)

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers;
use InvalidArgumentException;
@ -29,10 +30,8 @@ use function is_string;
*
* Extends PDO to simplify cross-database issues
*/
abstract class AbstractDriver
extends PDO
implements DriverInterface {
abstract class AbstractDriver extends PDO implements DriverInterface
{
/**
* Reference to the last executed query
*/
@ -76,7 +75,7 @@ abstract class AbstractDriver
/**
* PDO constructor wrapper
*/
public function __construct(string $dsn, string $username=NULL, string $password=NULL, array $driverOptions=[])
public function __construct(string $dsn, ?string $username=NULL, ?string $password=NULL, array $driverOptions=[])
{
// Set PDO to display errors as exceptions, and apply driver options
$driverOptions[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
@ -85,23 +84,6 @@ abstract class AbstractDriver
$this->_loadSubClasses();
}
/**
* Loads the subclasses for the driver
*/
protected function _loadSubClasses(): void
{
// Load the sql and util class for the driver
$thisClass = $this::class;
$nsArray = explode("\\", $thisClass);
array_pop($nsArray);
$driver = array_pop($nsArray);
$sqlClass = __NAMESPACE__ . "\\{$driver}\\SQL";
$utilClass = __NAMESPACE__ . "\\{$driver}\\Util";
$this->driverSQL = new $sqlClass();
$this->util = new $utilClass($this);
}
/**
* Allow invoke to work on table object
*
@ -114,14 +96,30 @@ abstract class AbstractDriver
isset($this->$name)
&& is_object($this->$name)
&& method_exists($this->$name, '__invoke')
)
{
) {
return call_user_func_array([$this->$name, '__invoke'], $args);
}
return NULL;
}
/**
* Loads the subclasses for the driver
*/
protected function _loadSubClasses(): void
{
// Load the sql and util class for the driver
$thisClass = $this::class;
$nsArray = explode('\\', $thisClass);
array_pop($nsArray);
$driver = array_pop($nsArray);
$sqlClass = __NAMESPACE__ . "\\{$driver}\\SQL";
$utilClass = __NAMESPACE__ . "\\{$driver}\\Util";
$this->driverSQL = new $sqlClass();
$this->util = new $utilClass($this);
}
// --------------------------------------------------------------------------
// ! Accessors / Mutators
// --------------------------------------------------------------------------
@ -282,6 +280,7 @@ abstract class AbstractDriver
// Fix functions
$funcs = [];
preg_match_all("#{$this->escapeCharOpen}([a-zA-Z0-9_]+(\((.*?)\))){$this->escapeCharClose}#iu", $raw, $funcs, PREG_SET_ORDER);
foreach ($funcs as $f)
{
// Unquote the function
@ -308,6 +307,7 @@ abstract class AbstractDriver
{
$tables = $this->driverQuery('tableList');
natsort($tables);
return $tables;
}
@ -326,6 +326,7 @@ abstract class AbstractDriver
{
$views = $this->driverQuery('viewList');
sort($views);
return $views;
}
@ -456,6 +457,7 @@ abstract class AbstractDriver
if (preg_match($regex, $this->lastQuery, $output) > 0)
{
$stmt = $this->query("SELECT COUNT(*) FROM {$output[1]}");
return (int) $stmt->fetchColumn();
}
@ -472,6 +474,7 @@ abstract class AbstractDriver
// Values for insertion
$vals = [];
foreach ($data as $group)
{
$vals = [...$vals, ...array_values($group)];
@ -533,6 +536,7 @@ abstract class AbstractDriver
$line = $this->quoteIdent($field) . " = CASE\n";
$cases = [];
foreach ($data as $case)
{
if (array_key_exists($field, $case))
@ -553,6 +557,7 @@ abstract class AbstractDriver
$sql .= implode(",\n", $fieldLines) . "\n";
$whereValues = array_column($data, $where);
foreach ($whereValues as $value)
{
$insertData[] = $value;
@ -579,6 +584,7 @@ abstract class AbstractDriver
$sql .= $this->quoteTable($table);
$this->statement = $this->query($sql);
return $this->statement;
}
@ -592,9 +598,6 @@ abstract class AbstractDriver
/**
* Helper method for quote_ident
*
* @param mixed $str
* @return mixed
*/
public function _quote(mixed $str): mixed
{
@ -608,7 +611,6 @@ abstract class AbstractDriver
)
? "{$this->escapeCharOpen}{$str}{$this->escapeCharClose}"
: $str;
}
/**

View File

@ -13,13 +13,14 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers;
/**
* Parent for database-specific syntax subclasses
*/
abstract class AbstractSQL implements SQLInterface {
abstract class AbstractSQL implements SQLInterface
{
/**
* Limit clause
*/

View File

@ -13,13 +13,16 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers;
use function arrayZipper;
/**
* Abstract class defining database / table creation methods
*/
abstract class AbstractUtil {
abstract class AbstractUtil
{
/**
* Save a reference to the connection object for later use
*/
@ -48,13 +51,14 @@ abstract class AbstractUtil {
// 'constraint' => ...,
// 'index' => ...,
// ]
$columnArray = \arrayZipper([
$columnArray = arrayZipper([
'type' => $fields,
'constraint' => $constraints
'constraint' => $constraints,
]);
// Join column definitions together
$columns = [];
foreach ($columnArray as $n => $props)
{
$str = $this->getDriver()->quoteIdent($n);
@ -85,16 +89,11 @@ abstract class AbstractUtil {
// --------------------------------------------------------------------------
/**
* Return an SQL file with the database table structure
*
* @abstract
*/
abstract public function backupStructure(): string;
/**
* Return an SQL file with the database data as insert statements
*
* @abstract
*/
abstract public function backupData(): string;
}

View File

@ -13,9 +13,9 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers;
use InvalidArgumentException;
use PDO;
use PDOStatement;
@ -36,12 +36,12 @@ use PDOStatement;
* @method rollback(): bool
* @method setAttribute(int $attribute, $value): bool
*/
interface DriverInterface /* extends the interface of PDO */ {
interface DriverInterface // extends the interface of PDO
{
/**
* Constructor/Connection method
*/
public function __construct(string $dsn, string $username=NULL, string $password=NULL, array $driverOptions = []);
public function __construct(string $dsn, ?string $username=NULL, ?string $password=NULL, array $driverOptions = []);
/**
* Simplifies prepared statements for database queries

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers\Mysql;
use PDO;
@ -22,8 +23,8 @@ use function defined;
/**
* MySQL specific class
*/
class Driver extends AbstractDriver {
class Driver extends AbstractDriver
{
/**
* Set the backtick as the MySQL escape character
*/
@ -39,7 +40,7 @@ class Driver extends AbstractDriver {
*
* @codeCoverageIgnore
*/
public function __construct(string $dsn, string $username=NULL, string $password=NULL, array $options=[])
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'))

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers\Mysql;
use Query\Drivers\AbstractSQL;
@ -20,8 +21,8 @@ use Query\Drivers\AbstractSQL;
/**
* MySQL specific SQL
*/
class SQL extends AbstractSQL {
class SQL extends AbstractSQL
{
/**
* Limit clause
*/
@ -56,10 +57,9 @@ class SQL extends AbstractSQL {
*/
public function dbList(): string
{
return <<<SQL
return <<<'SQL'
SHOW DATABASES WHERE `Database` NOT IN ('information_schema','mysql')
SQL;
}
/**
@ -82,7 +82,7 @@ SQL;
*/
public function systemTableList(): string
{
return <<<SQL
return <<<'SQL'
SELECT `TABLE_NAME` FROM `information_schema`.`TABLES`
WHERE `TABLE_SCHEMA`='information_schema'
SQL;

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers\Mysql;
use PDO;
@ -21,8 +22,8 @@ use Query\Drivers\AbstractUtil;
/**
* MySQL-specific backup, import and creation methods
*/
class Util extends AbstractUtil {
class Util extends AbstractUtil
{
/**
* Create an SQL backup file for the current database's structure
*/
@ -57,7 +58,6 @@ class Util extends AbstractUtil {
continue;
}
$string[] = $row['Create Table'];
}
}
@ -105,7 +105,7 @@ class Util extends AbstractUtil {
$row = array_values($row);
// Quote strings
$row = array_map(fn ($r) => is_string($r) ? $driver->quote($r) : $r, $row);
$row = array_map(static fn ($r) => is_string($r) ? $driver->quote($r) : $r, $row);
$row = array_map('trim', $row);
$rowString = 'INSERT INTO `' . trim($t) . '` (`' . implode('`,`', $columns) . '`) VALUES (' . implode(',', $row) . ');';

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers\Pgsql;
use Query\Drivers\AbstractDriver;
@ -20,14 +21,14 @@ use Query\Drivers\AbstractDriver;
/**
* PostgreSQL specific class
*/
class Driver extends AbstractDriver {
class Driver extends AbstractDriver
{
/**
* Connect to a PosgreSQL database
*
* @codeCoverageIgnore
*/
public function __construct(string $dsn, string $username=NULL, string $password=NULL, array $options=[])
public function __construct(string $dsn, ?string $username=NULL, ?string $password=NULL, array $options=[])
{
if ( ! str_contains($dsn, 'pgsql'))
{
@ -65,7 +66,7 @@ SQL;
foreach ($keys as &$key)
{
foreach(['update', 'delete'] AS $type)
foreach (['update', 'delete'] as $type)
{
if ( ! isset($valueMap[$key[$type]]))
{

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers\Pgsql;
use Query\Drivers\AbstractSQL;
@ -20,8 +21,8 @@ use Query\Drivers\AbstractSQL;
/**
* PostgreSQL specific SQL
*/
class SQL extends AbstractSQL {
class SQL extends AbstractSQL
{
/**
* Get the query plan for the sql query
*/
@ -43,7 +44,7 @@ class SQL extends AbstractSQL {
*/
public function dbList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "datname" FROM "pg_database"
WHERE "datname" NOT IN ('template0','template1')
ORDER BY "datname" ASC
@ -55,7 +56,7 @@ SQL;
*/
public function tableList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "table_name"
FROM "information_schema"."tables"
WHERE "table_type" = 'BASE TABLE'
@ -69,7 +70,7 @@ SQL;
*/
public function systemTableList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "table_name"
FROM "information_schema"."tables"
WHERE "table_type" = 'BASE TABLE'
@ -83,7 +84,7 @@ SQL;
*/
public function viewList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "viewname" FROM "pg_views"
WHERE "schemaname" NOT IN
('pg_catalog', 'information_schema')
@ -97,7 +98,7 @@ SQL;
*/
public function triggerList(): string
{
return <<<SQL
return <<<'SQL'
SELECT *
FROM "information_schema"."triggers"
WHERE "trigger_schema" NOT IN
@ -118,7 +119,7 @@ SQL;
*/
public function procedureList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "routine_name"
FROM "information_schema"."routines"
WHERE "specific_schema" NOT IN
@ -132,7 +133,7 @@ SQL;
*/
public function sequenceList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "c"."relname"
FROM "pg_class" "c"
WHERE "c"."relkind" = 'S'
@ -164,7 +165,7 @@ SQL;
*/
public function typeList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "typname" FROM "pg_catalog"."pg_type"
WHERE "typname" !~ '^pg_|_'
AND "typtype" = 'b'

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers\Pgsql;
use PDO;
@ -21,8 +22,8 @@ use Query\Drivers\AbstractUtil;
/**
* Postgres-specific backup, import and creation methods
*/
class Util extends AbstractUtil {
class Util extends AbstractUtil
{
/**
* Create an SQL backup file for the current database's structure
*/
@ -76,7 +77,6 @@ class Util extends AbstractUtil {
$row = array_map([$this->getDriver(), 'quote'], $row);
$row = array_map('trim', $row);
$rowString = 'INSERT INTO "' . trim($t) . '" ("' . implode('","', $columns) . '") VALUES (' . implode(',', $row) . ');';
$row = NULL;

View File

@ -13,13 +13,14 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers;
/**
* Interface for database-specific syntax subclasses
*/
interface SQLInterface {
interface SQLInterface
{
/**
* Get database specific sql for limit clause
*/

View File

@ -13,18 +13,20 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers\Sqlite;
use function is_array;
use InvalidArgumentException;
use PDO;
use Query\Drivers\AbstractDriver;
use function is_array;
/**
* SQLite specific class
*/
class Driver extends AbstractDriver {
class Driver extends AbstractDriver
{
/**
* SQLite has a truncate optimization,
* but no support for the actual keyword
@ -34,7 +36,7 @@ class Driver extends AbstractDriver {
/**
* Open SQLite Database
*/
public function __construct(string $dsn, string $user=NULL, string $pass=NULL, array $driverOptions=[])
public function __construct(string $dsn, ?string $user=NULL, ?string $pass=NULL, array $driverOptions=[])
{
if ( ! str_contains($dsn, 'sqlite:'))
{
@ -59,6 +61,7 @@ class Driver extends AbstractDriver {
{
$sql = $this->getSql()->tableList();
$res = $this->query($sql);
return dbFilter($res->fetchAll(PDO::FETCH_ASSOC), 'name');
}
@ -76,7 +79,7 @@ class Driver extends AbstractDriver {
'parent_table' => $row['table'],
'parent_column' => $row['to'],
'update' => $row['on_update'],
'delete' => $row['on_delete']
'delete' => $row['on_delete'],
];
}
@ -87,7 +90,7 @@ class Driver extends AbstractDriver {
* Create sql for batch insert
*
* @codeCoverageIgnore
* @return array[]|string[]|null[]
* @return array[]|null[]|string[]
*/
public function insertBatch(string $table, array $data=[]): array
{
@ -115,6 +118,7 @@ class Driver extends AbstractDriver {
// Create a key-value mapping for each field
$first = array_shift($data);
$cols = [];
foreach ($first as $colName => $datum)
{
$cols[] = $this->_quote($datum) . ' AS ' . $this->quoteIdent($colName);

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers\Sqlite;
use Query\Drivers\AbstractSQL;
@ -21,8 +22,8 @@ use Query\Exception\NotImplementedException;
/**
* SQLite Specific SQL
*/
class SQL extends AbstractSQL {
class SQL extends AbstractSQL
{
/**
* Get the query plan for the sql query
*/
@ -53,7 +54,7 @@ class SQL extends AbstractSQL {
*/
public function tableList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "name" FROM (
SELECT * FROM "sqlite_master" UNION ALL
SELECT * FROM "sqlite_temp_master"
@ -74,7 +75,7 @@ SQL;
return [
'sqlite_master',
'sqlite_temp_master',
'sqlite_sequence'
'sqlite_sequence',
];
}
@ -83,7 +84,7 @@ SQL;
*/
public function viewList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "name" FROM "sqlite_master" WHERE "type" = 'view'
SQL;
}
@ -93,7 +94,7 @@ SQL;
*/
public function triggerList(): string
{
return <<<SQL
return <<<'SQL'
SELECT "name" FROM "sqlite_master" WHERE "type"='trigger'
SQL;
}
@ -157,7 +158,6 @@ SQL;
SQL;
}
/**
* Get the list of indexes for the current table
*/

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Drivers\Sqlite;
use PDO;
@ -21,8 +22,8 @@ use Query\Drivers\AbstractUtil;
/**
* SQLite-specific backup, import and creation methods
*/
class Util extends AbstractUtil {
class Util extends AbstractUtil
{
/**
* Create an SQL backup file for the current database's data
*/

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Exception;
use InvalidArgumentException;
@ -20,5 +21,6 @@ use InvalidArgumentException;
/**
* Generic exception for bad drivers
*/
class BadDBDriverException extends InvalidArgumentException {
class BadDBDriverException extends InvalidArgumentException
{
}

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Exception;
use InvalidArgumentException;
@ -20,5 +21,6 @@ use InvalidArgumentException;
/**
* Exception for missing database connection
*/
class NonExistentConnectionException extends InvalidArgumentException {
class NonExistentConnectionException extends InvalidArgumentException
{
}

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query\Exception;
use BadMethodCallException;
@ -20,5 +21,6 @@ use BadMethodCallException;
/**
* Exception for non-implemented method
*/
class NotImplementedException extends BadMethodCallException{
class NotImplementedException extends BadMethodCallException
{
}

View File

@ -13,12 +13,14 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
/**
* Enum of join types
*/
enum JoinType: string {
enum JoinType: string
{
case CROSS = 'cross';
case INNER = 'inner';
case OUTER = 'outer';
@ -35,4 +37,3 @@ enum JoinType: string {
return self::from($val);
}
}

View File

@ -13,12 +13,14 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
/**
* 'Enum' of join types
*/
enum LikeType: string {
enum LikeType: string
{
case BEFORE = 'before';
case AFTER = 'after';
case BOTH = 'both';

View File

@ -13,12 +13,14 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
/**
* Enum of query map types
*/
enum MapType: string {
enum MapType: string
{
case GROUP_END = 'group_end';
case GROUP_START = 'group_start';
case JOIN = 'join';

View File

@ -13,18 +13,20 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
use PDOStatement;
use function is_array;
use function is_int;
use function mb_trim;
use PDOStatement;
use function mb_trim;
/**
* Convenience class for creating sql queries
*/
class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface {
class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface
{
// --------------------------------------------------------------------------
// ! Select Queries
// --------------------------------------------------------------------------
@ -69,48 +71,52 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface {
/**
* Selects the maximum value of a field from a query
*
* @param string|bool $as
* @param bool|string $as
*/
public function selectMax(string $field, $as=FALSE): self
{
// Create the select string
$this->state->appendSelectString(' MAX' . $this->_select($field, $as));
return $this;
}
/**
* Selects the minimum value of a field from a query
*
* @param string|bool $as
* @param bool|string $as
*/
public function selectMin(string $field, $as=FALSE): self
{
// Create the select string
$this->state->appendSelectString(' MIN' . $this->_select($field, $as));
return $this;
}
/**
* Selects the average value of a field from a query
*
* @param string|bool $as
* @param bool|string $as
*/
public function selectAvg(string $field, $as=FALSE): self
{
// Create the select string
$this->state->appendSelectString(' AVG' . $this->_select($field, $as));
return $this;
}
/**
* Selects the sum of a field from a query
*
* @param string|bool $as
* @param bool|string $as
*/
public function selectSum(string $field, $as=FALSE): self
{
// Create the select string
$this->state->appendSelectString(' SUM' . $this->_select($field, $as));
return $this;
}
@ -139,6 +145,7 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface {
{
// Prepend the keyword to the select string
$this->state->setSelectString(' DISTINCT' . $this->state->getSelectString());
return $this;
}
@ -148,6 +155,7 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface {
public function explain(): self
{
$this->explain = TRUE;
return $this;
}
@ -155,8 +163,6 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface {
* Specify the database table to select from
*
* Alias of `from` method to better match CodeIgniter 4
*
* @param string $tableName
*/
public function table(string $tableName): self
{
@ -514,6 +520,7 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface {
{
$sql = 'SELECT * FROM ' . $this->driver->quoteTable($table);
$res = $this->driver->query($sql);
return (int) (is_countable($res->fetchAll()) ? count($res->fetchAll()) : 0);
}
@ -589,6 +596,7 @@ class QueryBuilder extends QueryBuilderBase implements QueryBuilderInterface {
[$sql, $data, $affectedRows] = $this->driver->updateBatch($table, $data, $where);
$this->_run(QueryType::UPDATE_BATCH, $table, $sql, $data);
return $affectedRows;
}

View File

@ -13,14 +13,16 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
use function regexInArray;
use BadMethodCallException;
use PDO;
use PDOStatement;
use Query\Drivers\DriverInterface;
use function is_string;
use function regexInArray;
/**
* @method affectedRows(): int
@ -56,8 +58,8 @@ use Query\Drivers\DriverInterface;
* @method setTablePrefix(string $prefix): void
* @method truncate(string $table): PDOStatement
*/
class QueryBuilderBase {
class QueryBuilderBase
{
/**
* Convenience property for connection management
*/
@ -67,7 +69,7 @@ class QueryBuilderBase {
* List of queries executed
*/
public array $queries = [
'total_time' => 0
'total_time' => 0,
];
/**
@ -110,8 +112,8 @@ class QueryBuilderBase {
* Calls a function further down the inheritance chain.
* 'Implements' methods on the driver object
*
* @return mixed
* @throws BadMethodCallException
* @return mixed
*/
public function __call(string $name, array $params)
{
@ -141,7 +143,7 @@ class QueryBuilderBase {
// Escape the identifiers
$field = $this->driver->quoteIdent($field);
if ( ! \is_string($as))
if ( ! is_string($as))
{
// @codeCoverageIgnoreStart
return $field;
@ -149,6 +151,7 @@ class QueryBuilderBase {
}
$as = $this->driver->quoteIdent($as);
return "({$field}) AS {$as} ";
}
@ -224,7 +227,7 @@ class QueryBuilderBase {
'conjunction' => empty($this->state->getHavingMap())
? ' HAVING '
: " {$conj} ",
'string' => $item
'string' => $item,
]);
}
@ -242,7 +245,8 @@ class QueryBuilderBase {
if (is_scalar($key))
{
$pairs[$key] = $val;
} else
}
else
{
$pairs = $key;
}
@ -300,8 +304,6 @@ class QueryBuilderBase {
/**
* Simplify where_in methods
*
* @param mixed $key
* @param mixed $val
* @param string $in - The (not) in fragment
* @param string $conj - The where in conjunction
*/
@ -321,10 +323,8 @@ class QueryBuilderBase {
/**
* Executes the compiled query
*
* @param array|null $vals
*/
protected function _run(QueryType $type, string $table, string $sql = NULL, array $vals = NULL, bool $reset = TRUE): PDOStatement
protected function _run(QueryType $type, string $table, ?string $sql = NULL, ?array $vals = NULL, bool $reset = TRUE): PDOStatement
{
if ($sql === NULL)
{
@ -381,7 +381,7 @@ class QueryBuilderBase {
// Add the interpreted query to the list of executed queries
$this->queries[] = [
'time' => $totalTime,
'sql' => sprintf(...$evals)
'sql' => sprintf(...$evals),
];
$this->queries['total_time'] += $totalTime;
@ -398,6 +398,7 @@ class QueryBuilderBase {
protected function _compileType(QueryType $type = QueryType::SELECT, string $table = ''): string
{
$setArrayKeys = $this->state->getSetArrayKeys();
switch ($type)
{
case QueryType::INSERT:
@ -454,7 +455,7 @@ class QueryBuilderBase {
// Set each type of subclause
foreach ($clauses as $clause)
{
$func = 'get' . ucFirst($clause);
$func = 'get' . ucfirst($clause);
$param = $this->state->$func();
if (is_array($param))
{
@ -462,7 +463,8 @@ class QueryBuilderBase {
{
$sql .= $q['conjunction'] . $q['string'];
}
} else
}
else
{
$sql .= $param;
}

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
use PDO;
@ -57,8 +58,8 @@ use PDOStatement;
* @method setTablePrefix(string $prefix): void
* @method truncate(string $table): PDOStatement
*/
interface QueryBuilderInterface {
interface QueryBuilderInterface
{
// --------------------------------------------------------------------------
// ! Select Queries
// --------------------------------------------------------------------------
@ -70,28 +71,28 @@ interface QueryBuilderInterface {
/**
* Selects the maximum value of a field from a query
*
* @param string|bool $as
* @param bool|string $as
*/
public function selectMax(string $field, $as=FALSE): self;
/**
* Selects the minimum value of a field from a query
*
* @param string|bool $as
* @param bool|string $as
*/
public function selectMin(string $field, $as=FALSE): self;
/**
* Selects the average value of a field from a query
*
* @param string|bool $as
* @param bool|string $as
*/
public function selectAvg(string $field, $as=FALSE): self;
/**
* Selects the sum of a field from a query
*
* @param string|bool $as
* @param bool|string $as
*/
public function selectSum(string $field, $as=FALSE): self;
@ -109,8 +110,6 @@ interface QueryBuilderInterface {
* Specify the database table to select from
*
* Alias of `from` method to better match CodeIgniter 4
*
* @param string $tableName
*/
public function table(string $tableName): self;
@ -124,29 +123,21 @@ interface QueryBuilderInterface {
// --------------------------------------------------------------------------
/**
* Creates a Like clause in the sql statement
*
* @param mixed $values
*/
public function like(string $field, mixed $values, LikeType|string $pos=LikeType::BOTH): self;
/**
* Generates an OR Like clause
*
* @param mixed $values
*/
public function orLike(string $field, mixed $values, LikeType|string $pos=LikeType::BOTH): self;
/**
* Generates a NOT LIKE clause
*
* @param mixed $values
*/
public function notLike(string $field, mixed $values, LikeType|string $pos=LikeType::BOTH): self;
/**
* Generates a OR NOT LIKE clause
*
* @param mixed $values
*/
public function orNotLike(string $field, mixed $values, LikeType|string $pos=LikeType::BOTH): self;
@ -155,17 +146,11 @@ interface QueryBuilderInterface {
// --------------------------------------------------------------------------
/**
* Generates a 'Having' clause
*
* @param mixed $key
* @param mixed $values
*/
public function having(mixed $key, mixed $values=[]): self;
/**
* Generates a 'Having' clause prefixed with 'OR'
*
* @param mixed $key
* @param mixed $values
*/
public function orHaving(mixed $key, mixed $values=[]): self;
@ -176,9 +161,6 @@ interface QueryBuilderInterface {
* Specify condition(s) in the where clause of a query
* Note: this function works with key / value, or a
* passed array with key / value pairs
*
* @param mixed $key
* @param mixed $values
*/
public function where(mixed $key, mixed $values=[]): self;
@ -186,39 +168,26 @@ interface QueryBuilderInterface {
* Where clause prefixed with "OR"
*
* @param string $key
* @param mixed $values
*/
public function orWhere(mixed $key, mixed $values=[]): self;
/**
* Where clause with 'IN' statement
*
* @param string $field
* @param mixed $values
*/
public function whereIn(string $field, mixed $values=[]): self;
/**
* Where in statement prefixed with "or"
*
* @param string $field
* @param mixed $values
*/
public function orWhereIn(string $field, mixed $values=[]): self;
/**
* WHERE NOT IN (FOO) clause
*
* @param string $field
* @param mixed $values
*/
public function whereNotIn(string $field, mixed $values=[]): self;
/**
* OR WHERE NOT IN (FOO) clause
*
* @param string $field
* @param mixed $values
*/
public function orWhereNotIn(string $field, mixed $values=[]): self;
@ -228,7 +197,6 @@ interface QueryBuilderInterface {
/**
* Sets values for inserts / updates / deletes
*
* @param mixed $key
* @param mixed $values
*/
public function set(mixed $key, mixed $values = NULL): self;
@ -240,8 +208,6 @@ interface QueryBuilderInterface {
/**
* Group the results by the selected field(s)
*
* @param mixed $field
*/
public function groupBy(mixed $field): self;
@ -297,8 +263,6 @@ interface QueryBuilderInterface {
/**
* Convenience method for get() with a where clause
*
* @param array $where
*/
public function getWhere(string $table, array $where=[], ?int $limit=NULL, ?int $offset=NULL): PDOStatement;
@ -317,8 +281,6 @@ interface QueryBuilderInterface {
/**
* Creates an insert clause, and executes it
*
* @param mixed $data
*/
public function insert(string $table, mixed $data=[]): PDOStatement;
@ -331,8 +293,6 @@ interface QueryBuilderInterface {
/**
* Creates an update clause, and executes it
*
* @param mixed $data
*/
public function update(string $table, mixed $data=[]): PDOStatement;
@ -348,8 +308,6 @@ interface QueryBuilderInterface {
/**
* Deletes data from a table
*
* @param mixed $where
*/
public function delete(string $table, mixed $where=''): PDOStatement;

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
use Query\Drivers\DriverInterface;
@ -20,17 +21,8 @@ use Query\Drivers\DriverInterface;
/**
* Utility Class to parse sql clauses for properly escaping identifiers
*/
class QueryParser {
/**
* Regex patterns for various syntax components
*/
private array $matchPatterns = [
'function' => '([a-zA-Z0-9_]+\((.*?)\))',
'identifier' => '([a-zA-Z0-9_-]+\.?)+',
'operator' => '=|AND|&&?|~|\|\|?|\^|/|>=?|<=?|-|%|OR|\+|NOT|\!=?|<>|XOR'
];
class QueryParser
{
/**
* Regex matches
*/
@ -41,6 +33,15 @@ class QueryParser {
'combined' => [],
];
/**
* Regex patterns for various syntax components
*/
private array $matchPatterns = [
'function' => '([a-zA-Z0-9_]+\((.*?)\))',
'identifier' => '([a-zA-Z0-9_-]+\.?)+',
'operator' => '=|AND|&&?|~|\|\|?|\^|/|>=?|<=?|-|%|OR|\+|NOT|\!=?|<>|XOR',
];
/**
* Constructor/entry point into parser
*/
@ -81,7 +82,7 @@ class QueryParser {
// Go through and quote the identifiers
for ($i=0; $i <= $count; $i++)
{
if (in_array($parts['combined'][$i], $parts['identifiers']) && ! is_numeric($parts['combined'][$i]))
if (in_array($parts['combined'][$i], $parts['identifiers'], TRUE) && ! is_numeric($parts['combined'][$i]))
{
$parts['combined'][$i] = $this->db->quoteIdent($parts['combined'][$i]);
}
@ -92,8 +93,6 @@ class QueryParser {
/**
* Returns a more useful match array
*
* @return array
*/
protected function filterArray(array $array): array
{

View File

@ -13,12 +13,14 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
/**
* Enum of query types
*/
enum QueryType: string {
enum QueryType: string
{
case SELECT = 'select';
case INSERT = 'insert';
case INSERT_BATCH = 'insert_batch';

View File

@ -13,6 +13,7 @@
* @link https://git.timshomepage.net/aviat/Query
* @version 4.0.0
*/
namespace Query;
use function is_array;
@ -20,32 +21,33 @@ use function is_array;
/**
* Query builder state
*
* @method getSelectString(): string
* @method getFromString(): string
* @method getSetString(): string
* @method getOrderString(): string
* @method getGroupString(): string
* @method getSetArrayKeys(): array
* @method getOrderArray(): array
* @method getGroupArray(): array
* @method getValues(): array
* @method getWhereValues(): array
* @method getGroupString(): string
* @method getHavingMap(): array
* @method getLimit(): int|null
* @method getOffset()
* @method getOrderArray(): array
* @method getOrderString(): string
* @method getQueryMap(): array
* @method getHavingMap(): array
* @method getSelectString(): string
* @method getSetArrayKeys(): array
* @method getSetString(): string
* @method getValues(): array
* @method getWhereValues(): array
*
* @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 setGroupString(string $groupString): self
* @method setLimit(int $limit): self
* @method setOffset(?int $offset): self
* @method setOrderString(string $orderString): self
* @method setSelectString(string $selectString): self
* @method setSetArrayKeys(array $arrayKeys): self
* @method setSetString(string $setString): self
*/
class State {
class State
{
// --------------------------------------------------------------------------
// ! SQL Clause Strings
// --------------------------------------------------------------------------
@ -150,6 +152,7 @@ class State {
if (isset($this->$maybeProp))
{
$this->$maybeProp = $arguments[0];
return $this;
}
}
@ -160,30 +163,35 @@ class State {
public function appendSelectString(string $str): self
{
$this->selectString .= $str;
return $this;
}
public function appendSetArrayKeys(array $setArrayKeys): self
{
$this->setArrayKeys = array_merge($this->setArrayKeys, $setArrayKeys);
return $this;
}
public function setOrderArray(string $key, mixed $orderArray): self
{
$this->orderArray[$key] = $orderArray;
return $this;
}
public function appendGroupArray(string $groupArray): self
{
$this->groupArray[] = $groupArray;
return $this;
}
public function appendValues(array $values): self
{
$this->values = array_merge($this->values, $values);
return $this;
}
@ -200,6 +208,7 @@ class State {
}
$this->whereValues[] = $val;
return $this;
}
@ -211,14 +220,16 @@ class State {
$this->queryMap[] = [
'type' => $type,
'conjunction' => $conjunction,
'string' => $string
'string' => $string,
];
return $this;
}
public function appendHavingMap(array $item): self
{
$this->havingMap[] = $item;
return $this;
}
}