Various refactoring
This commit is contained in:
parent
0df1b43af8
commit
91eb8123d1
@ -16,7 +16,6 @@ A query builder/database abstraction layer, using prepared statements for securi
|
||||
|
||||
## Databases Supported
|
||||
|
||||
* Firebird (via interbase extension)
|
||||
* MySQL
|
||||
* PostgreSQL
|
||||
* SQLite
|
||||
@ -41,7 +40,7 @@ $params = array(
|
||||
'database' => 'test_db',
|
||||
|
||||
// Only required for
|
||||
// SQLite or Firebird
|
||||
// SQLite
|
||||
'file' => '/path/to/db/file',
|
||||
|
||||
// Optional paramaters
|
||||
@ -85,7 +84,7 @@ Underscored methods are also aliased to camel case methods.
|
||||
#### You can also run queries manually.
|
||||
|
||||
To run a prepared statement, call
|
||||
`$db->prepare_execute($sql, $params)`.
|
||||
`$db->prepareExecute($sql, $params)`.
|
||||
|
||||
To run a plain query, `$db->query($sql)`
|
||||
|
||||
@ -98,8 +97,8 @@ An example of a moderately complex query:
|
||||
$query = $db->select('id, key as k, val')
|
||||
->from('table t')
|
||||
->where('k >', 3)
|
||||
->or_where('id !=' 5)
|
||||
->order_by('val', 'DESC')
|
||||
->orWhere('id !=' 5)
|
||||
->orderBy('val', 'DESC')
|
||||
->limit(3, 1)
|
||||
->get();
|
||||
```
|
||||
|
@ -24,14 +24,6 @@
|
||||
<testsuite name="SQLite Tests">
|
||||
<directory>./../tests/Drivers/SQLite/</directory>
|
||||
</testsuite>
|
||||
<!-- <testsuite name="FirebirdTests">
|
||||
<file>../tests/databases/firebird/FirebirdTest.php</file>
|
||||
<file>../tests/databases/firebird/FirebirdQBTest.php</file>
|
||||
</testsuite>
|
||||
<testsuite name="OCITests">
|
||||
<file>../tests/databases/oci/OCITest.php</file>
|
||||
<file>../tests/databases/oci/OCIQBTest.php</file>
|
||||
</testsuite> -->
|
||||
</testsuites>
|
||||
<logging>
|
||||
<log type="coverage-html" target="./../coverage"/>
|
||||
|
@ -1,12 +1,6 @@
|
||||
parameters:
|
||||
autoload_files:
|
||||
- %rootDir%/../../../tests/bootstrap.php
|
||||
- %rootDir%/../../../tests/databases/mysql/MySQLTest.php
|
||||
- %rootDir%/../../../tests/databases/mysql/MySQLQBTest.php
|
||||
- %rootDir%/../../../tests/databases/pgsql/PgSQLTest.php
|
||||
- %rootDir%/../../../tests/databases/pgsql/PgSQLQBTest.php
|
||||
- %rootDir%/../../../tests/databases/sqlite/SQLiteTest.php
|
||||
- %rootDir%/../../../tests/databases/sqlite/SQLiteQBTest.php
|
||||
ignoreErrors:
|
||||
- '#Access to an undefined property Aviat\\\Ion\\\Friend::\$[a-zA-Z0-9_]+#'
|
||||
- '#Call to an undefined method Aviat\\\Ion\\\Friend::[a-zA-Z0-9_]+\(\)#'
|
||||
|
35
phpunit.xml
35
phpunit.xml
@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
colors="true"
|
||||
stopOnFailure="false"
|
||||
bootstrap="tests/bootstrap.php">
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src/</directory>
|
||||
<file>autoload.php</file>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<testsuites>
|
||||
<testsuite name="CoreTests">
|
||||
<file>tests/core/core_test.php</file>
|
||||
<file>tests/core/query_parser_test.php</file>
|
||||
<file>tests/core/connection_manager_test.php</file>
|
||||
</testsuite>
|
||||
<testsuite name="MySQLTests">
|
||||
<file>tests/databases/mysql/MySQLTest.php</file>
|
||||
<file>tests/databases/mysql/MySQLQBTest.php</file>
|
||||
</testsuite>
|
||||
<testsuite name="PgSQLTests">
|
||||
<file>tests/databases/pgsql/PgSQLTest.php</file>
|
||||
<file>tests/databases/pgsql/PgSQLQBTest.php</file>
|
||||
</testsuite>
|
||||
<testsuite name="SQLiteTests">
|
||||
<file>tests/databases/sqlite/SQLiteTest.php</file>
|
||||
<file>tests/databases/sqlite/SQLiteQBTest.php</file>
|
||||
</testsuite>
|
||||
<testsuite name="FirebirdTests">
|
||||
<file>tests/databases/firebird/FirebirdTest.php</file>
|
||||
<file>tests/databases/firebird/FirebirdQBTest.php</file>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
@ -98,10 +98,10 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _loadSubClasses()
|
||||
protected function _loadSubClasses(): void
|
||||
{
|
||||
// Load the sql and util class for the driver
|
||||
$thisClass = get_class($this);
|
||||
$thisClass = \get_class($this);
|
||||
$nsArray = explode("\\", $thisClass);
|
||||
array_pop($nsArray);
|
||||
$driver = array_pop($nsArray);
|
||||
@ -124,11 +124,11 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
{
|
||||
if (
|
||||
isset($this->$name)
|
||||
&& is_object($this->$name)
|
||||
&& \is_object($this->$name)
|
||||
&& method_exists($this->$name, '__invoke')
|
||||
)
|
||||
{
|
||||
return call_user_func_array([$this->$name, '__invoke'], $args);
|
||||
return \call_user_func_array([$this->$name, '__invoke'], $args);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @param string $queryString
|
||||
* @return void
|
||||
*/
|
||||
public function setLastQuery(string $queryString)
|
||||
public function setLastQuery(string $queryString): void
|
||||
{
|
||||
$this->lastQuery = $queryString;
|
||||
}
|
||||
@ -205,9 +205,9 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
// Prepare the sql, save the statement for easy access later
|
||||
$this->statement = $this->prepare($sql);
|
||||
|
||||
if( ! (is_array($data) || is_object($data)))
|
||||
if( ! (\is_array($data) || \is_object($data)))
|
||||
{
|
||||
throw new InvalidArgumentException("Data argument must be an object or associative array");
|
||||
throw new InvalidArgumentException('Data argument must be an object or associative array');
|
||||
}
|
||||
|
||||
// Bind the parameters
|
||||
@ -232,7 +232,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @param array $params
|
||||
* @return PDOStatement
|
||||
*/
|
||||
public function prepareExecute($sql, $params)
|
||||
public function prepareExecute($sql, $params): PDOStatement
|
||||
{
|
||||
$this->statement = $this->prepareQuery($sql, $params);
|
||||
$this->statement->execute();
|
||||
@ -245,7 +245,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function affectedRows()
|
||||
public function affectedRows(): int
|
||||
{
|
||||
// Return number of rows affected
|
||||
return $this->statement->rowCount();
|
||||
@ -256,7 +256,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @param string $table
|
||||
* @return string
|
||||
*/
|
||||
public function prefixTable($table)
|
||||
public function prefixTable($table): string
|
||||
{
|
||||
// Add the prefix to the table name
|
||||
// before quoting it
|
||||
@ -286,7 +286,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @param string $table
|
||||
* @return string
|
||||
*/
|
||||
public function quoteTable($table)
|
||||
public function quoteTable($table): string
|
||||
{
|
||||
$table = $this->prefixTable($table);
|
||||
|
||||
@ -298,11 +298,11 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* Surrounds the string with the databases identifier escape characters
|
||||
*
|
||||
* @param mixed $identifier
|
||||
* @return string
|
||||
* @return string|array
|
||||
*/
|
||||
public function quoteIdent($identifier)
|
||||
{
|
||||
if (is_array($identifier))
|
||||
if (\is_array($identifier))
|
||||
{
|
||||
return array_map([$this, __METHOD__], $identifier);
|
||||
}
|
||||
@ -335,7 +335,6 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
}
|
||||
|
||||
return $raw;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -343,7 +342,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSchemas()
|
||||
public function getSchemas(): ?array
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@ -353,7 +352,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTables()
|
||||
public function getTables(): ?array
|
||||
{
|
||||
$tables = $this->driverQuery('tableList');
|
||||
natsort($tables);
|
||||
@ -365,7 +364,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDbs()
|
||||
public function getDbs(): array
|
||||
{
|
||||
return $this->driverQuery('dbList');
|
||||
}
|
||||
@ -375,7 +374,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getViews()
|
||||
public function getViews(): ?array
|
||||
{
|
||||
$views = $this->driverQuery('viewList');
|
||||
sort($views);
|
||||
@ -387,7 +386,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSequences()
|
||||
public function getSequences(): ?array
|
||||
{
|
||||
return $this->driverQuery('sequenceList');
|
||||
}
|
||||
@ -397,7 +396,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFunctions()
|
||||
public function getFunctions(): ?array
|
||||
{
|
||||
return $this->driverQuery('functionList', FALSE);
|
||||
}
|
||||
@ -407,7 +406,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProcedures()
|
||||
public function getProcedures(): ?array
|
||||
{
|
||||
return $this->driverQuery('procedureList', FALSE);
|
||||
}
|
||||
@ -417,7 +416,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTriggers()
|
||||
public function getTriggers(): ?array
|
||||
{
|
||||
return $this->driverQuery('triggerList', FALSE);
|
||||
}
|
||||
@ -428,7 +427,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSystemTables()
|
||||
public function getSystemTables(): ?array
|
||||
{
|
||||
return $this->driverQuery('systemTableList');
|
||||
}
|
||||
@ -439,7 +438,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($table)
|
||||
public function getColumns($table): ?array
|
||||
{
|
||||
return $this->driverQuery($this->getSql()->columnList($this->prefixTable($table)), FALSE);
|
||||
}
|
||||
@ -450,7 +449,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getFks($table)
|
||||
public function getFks($table): ?array
|
||||
{
|
||||
return $this->driverQuery($this->getSql()->fkList($table), FALSE);
|
||||
}
|
||||
@ -461,7 +460,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexes($table)
|
||||
public function getIndexes($table): ?array
|
||||
{
|
||||
return $this->driverQuery($this->getSql()->indexList($this->prefixTable($table)), FALSE);
|
||||
}
|
||||
@ -471,7 +470,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTypes()
|
||||
public function getTypes(): ?array
|
||||
{
|
||||
return $this->driverQuery('typeList', FALSE);
|
||||
}
|
||||
@ -481,19 +480,19 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
*
|
||||
* @param string|array|null $query
|
||||
* @param bool $filteredIndex
|
||||
* @return array
|
||||
* @return array|null
|
||||
*/
|
||||
public function driverQuery($query, $filteredIndex=TRUE)
|
||||
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->sql, $query))
|
||||
{
|
||||
$query = $this->getSql()->$query();
|
||||
}
|
||||
|
||||
// Return if the values are returned instead of a query,
|
||||
// or if the query doesn't apply to the driver
|
||||
if ( ! is_string($query))
|
||||
if ( ! \is_string($query))
|
||||
{
|
||||
return $query;
|
||||
}
|
||||
@ -501,10 +500,10 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
// Run the query!
|
||||
$res = $this->query($query);
|
||||
|
||||
$flag = ($filteredIndex) ? PDO::FETCH_NUM : PDO::FETCH_ASSOC;
|
||||
$flag = $filteredIndex ? PDO::FETCH_NUM : PDO::FETCH_ASSOC;
|
||||
$all = $res->fetchAll($flag);
|
||||
|
||||
return ($filteredIndex) ? \db_filter($all, 0) : $all;
|
||||
return $filteredIndex ? \db_filter($all, 0) : $all;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -513,7 +512,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @see http://us3.php.net/manual/en/pdostatement.rowcount.php#87110
|
||||
* @return int|null
|
||||
*/
|
||||
public function numRows()
|
||||
public function numRows(): ?int
|
||||
{
|
||||
$regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/i';
|
||||
$output = [];
|
||||
@ -537,7 +536,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
public function insertBatch($table, $data=[])
|
||||
{
|
||||
$data = (array) $data;
|
||||
$firstRow = (array) current($data);
|
||||
$firstRow = current($data);
|
||||
if (is_scalar($firstRow))
|
||||
{
|
||||
return NULL;
|
||||
@ -558,7 +557,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
|
||||
// Create the placeholder groups
|
||||
$params = array_fill(0, count($fields), '?');
|
||||
$paramString = "(" . implode(',', $params) . ")";
|
||||
$paramString = '(' . implode(',', $params) . ')';
|
||||
$paramList = array_fill(0, count($data), $paramString);
|
||||
|
||||
// Append the placeholder groups to the query
|
||||
@ -594,7 +593,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
// 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
|
||||
)
|
||||
@ -609,7 +608,7 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
protected function _prefix($str)
|
||||
protected function _prefix($str): string
|
||||
{
|
||||
// Don't prefix an already prefixed table
|
||||
if (strpos($str, $this->tablePrefix) !== FALSE)
|
||||
@ -626,9 +625,9 @@ abstract class AbstractDriver extends PDO implements DriverInterface {
|
||||
* @param string $table
|
||||
* @return PDOStatement
|
||||
*/
|
||||
public function truncate($table)
|
||||
public function truncate($table): PDOStatement
|
||||
{
|
||||
$sql = ($this->hasTruncate)
|
||||
$sql = $this->hasTruncate
|
||||
? 'TRUNCATE TABLE '
|
||||
: 'DELETE FROM ';
|
||||
|
||||
|
@ -26,16 +26,16 @@ abstract class AbstractUtil {
|
||||
* Reference to the current connection object
|
||||
* @var DriverInterface
|
||||
*/
|
||||
private $conn;
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* Save a reference to the connection object for later use
|
||||
*
|
||||
* @param DriverInterface $conn
|
||||
* @param DriverInterface $connection
|
||||
*/
|
||||
public function __construct(DriverInterface $conn)
|
||||
public function __construct(DriverInterface $connection)
|
||||
{
|
||||
$this->conn = $conn;
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,7 +45,7 @@ abstract class AbstractUtil {
|
||||
*/
|
||||
public function getDriver()
|
||||
{
|
||||
return $this->conn;
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,7 +59,7 @@ abstract class AbstractUtil {
|
||||
*/
|
||||
public function createTable($name, $fields, array $constraints=[], $ifNotExists=TRUE)
|
||||
{
|
||||
$existsStr = ($ifNotExists) ? ' IF NOT EXISTS ' : ' ';
|
||||
$existsStr = $ifNotExists ? ' IF NOT EXISTS ' : ' ';
|
||||
|
||||
// Reorganize into an array indexed with column information
|
||||
// Eg $columnArray[$colname] = array(
|
||||
@ -77,8 +77,8 @@ abstract class AbstractUtil {
|
||||
foreach($columnArray as $n => $props)
|
||||
{
|
||||
$str = $this->getDriver()->quoteIdent($n);
|
||||
$str .= (isset($props['type'])) ? " {$props['type']}" : "";
|
||||
$str .= (isset($props['constraint'])) ? " {$props['constraint']}" : "";
|
||||
$str .= isset($props['type']) ? " {$props['type']}" : "";
|
||||
$str .= isset($props['constraint']) ? " {$props['constraint']}" : "";
|
||||
|
||||
$columns[] = $str;
|
||||
}
|
||||
@ -97,7 +97,7 @@ abstract class AbstractUtil {
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function deleteTable($name)
|
||||
public function deleteTable($name): string
|
||||
{
|
||||
return 'DROP TABLE IF EXISTS '.$this->getDriver()->quoteTable($name);
|
||||
}
|
||||
|
@ -152,8 +152,6 @@ interface DriverInterface extends PDOInterface {
|
||||
*/
|
||||
public function prepareExecute($sql, $params);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Method to simplify retrieving db results for meta-data queries
|
||||
*
|
||||
|
@ -49,7 +49,7 @@ class Driver extends AbstractDriver implements DriverInterface {
|
||||
public function __construct($dsn, $username=NULL, $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'",
|
||||
|
@ -27,7 +27,7 @@ class Util extends AbstractUtil {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function backupStructure()
|
||||
public function backupStructure(): string
|
||||
{
|
||||
$string = [];
|
||||
|
||||
@ -37,7 +37,7 @@ class Util extends AbstractUtil {
|
||||
foreach($dbs as &$d)
|
||||
{
|
||||
// Skip built-in dbs
|
||||
if ($d == 'mysql')
|
||||
if ($d === 'mysql')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -69,7 +69,7 @@ class Util extends AbstractUtil {
|
||||
* @param array $exclude
|
||||
* @return string
|
||||
*/
|
||||
public function backupData($exclude=[])
|
||||
public function backupData($exclude=[]): string
|
||||
{
|
||||
$tables = $this->getDriver()->getTables();
|
||||
|
||||
|
@ -48,7 +48,7 @@ class Driver extends AbstractDriver implements DriverInterface {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSchemas()
|
||||
public function getSchemas(): ?array
|
||||
{
|
||||
$sql = <<<SQL
|
||||
SELECT DISTINCT "schemaname" FROM "pg_tables"
|
||||
@ -67,7 +67,7 @@ SQL;
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getFks($table)
|
||||
public function getFks($table): array
|
||||
{
|
||||
$valueMap = [
|
||||
'c' => 'CASCADE',
|
||||
@ -80,10 +80,8 @@ SQL;
|
||||
{
|
||||
foreach(['update', 'delete'] AS $type)
|
||||
{
|
||||
if ( ! isset($valueMap[$key[$type]]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ( ! isset($valueMap[$key[$type]])) continue;
|
||||
|
||||
|
||||
$key[$type] = $valueMap[$key[$type]];
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace Query\Drivers\Pgsql;
|
||||
use Query\Drivers\AbstractUtil;
|
||||
|
||||
/**
|
||||
* Posgres-specific backup, import and creation methods
|
||||
* Postgres-specific backup, import and creation methods
|
||||
*/
|
||||
class Util extends AbstractUtil {
|
||||
|
||||
@ -26,7 +26,7 @@ class Util extends AbstractUtil {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function backupStructure()
|
||||
public function backupStructure(): string
|
||||
{
|
||||
// @TODO Implement Backup function
|
||||
return '';
|
||||
@ -38,7 +38,7 @@ class Util extends AbstractUtil {
|
||||
* @param array $exclude
|
||||
* @return string
|
||||
*/
|
||||
public function backupData($exclude=[])
|
||||
public function backupData(array $exclude=[]): string
|
||||
{
|
||||
$tables = $this->getDriver()->getTables();
|
||||
|
||||
|
@ -61,7 +61,7 @@ class Driver extends AbstractDriver implements DriverInterface {
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTables()
|
||||
public function getTables(): array
|
||||
{
|
||||
$sql = $this->sql->tableList();
|
||||
$res = $this->query($sql);
|
||||
@ -74,7 +74,7 @@ class Driver extends AbstractDriver implements DriverInterface {
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
public function getFks($table)
|
||||
public function getFks($table): array
|
||||
{
|
||||
$returnRows = [];
|
||||
|
||||
|
@ -33,7 +33,7 @@ class Util extends AbstractUtil {
|
||||
* @param array $excluded
|
||||
* @return string
|
||||
*/
|
||||
public function backupData($excluded=[])
|
||||
public function backupData(array $excluded=[]): string
|
||||
{
|
||||
// Get a list of all the objects
|
||||
$sql = 'SELECT DISTINCT "name"
|
||||
@ -103,7 +103,7 @@ class Util extends AbstractUtil {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function backupStructure()
|
||||
public function backupStructure(): string
|
||||
{
|
||||
// Fairly easy for SQLite...just query the master table
|
||||
$sql = 'SELECT "sql" FROM "sqlite_master"';
|
||||
|
@ -16,12 +16,172 @@ namespace Query;
|
||||
|
||||
use BadMethodCallException;
|
||||
use PDOStatement;
|
||||
use Query\Drivers\DriverInterface;
|
||||
use Query\Drivers\{
|
||||
AbstractUtil,
|
||||
DriverInterface,
|
||||
SQLInterface
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience class for creating sql queries
|
||||
* @method query(mixed $sql): PDOStatement;
|
||||
*/
|
||||
class QueryBuilder extends AbstractQueryBuilder 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
|
||||
* @var string
|
||||
*/
|
||||
public $connName = '';
|
||||
|
||||
/**
|
||||
* List of queries executed
|
||||
* @var array
|
||||
*/
|
||||
public $queries;
|
||||
|
||||
/**
|
||||
* Whether to do only an explain on the query
|
||||
* @var boolean
|
||||
*/
|
||||
protected $explain;
|
||||
|
||||
/**
|
||||
* The current database driver
|
||||
* @var DriverInterface
|
||||
*/
|
||||
public $driver;
|
||||
|
||||
/**
|
||||
* Query parser class instance
|
||||
* @var QueryParser
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
/**
|
||||
* Alias to driver util class
|
||||
* @var AbstractUtil
|
||||
*/
|
||||
protected $util;
|
||||
|
||||
/**
|
||||
* Alias to driver sql class
|
||||
* @var SQLInterface
|
||||
*/
|
||||
protected $sql;
|
||||
|
||||
/**
|
||||
* String class values to be reset
|
||||
@ -61,20 +221,20 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DriverInterface $db
|
||||
* @param DriverInterface $driver
|
||||
* @param QueryParser $parser
|
||||
*/
|
||||
public function __construct(DriverInterface $db, QueryParser $parser)
|
||||
public function __construct(DriverInterface $driver, QueryParser $parser)
|
||||
{
|
||||
// Inject driver and parser
|
||||
$this->db = $db;
|
||||
$this->driver = $driver;
|
||||
$this->parser = $parser;
|
||||
|
||||
$this->queries['total_time'] = 0;
|
||||
|
||||
// Alias driver sql and util classes
|
||||
$this->sql = $this->db->getSql();
|
||||
$this->util = $this->db->getUtil();
|
||||
$this->sql = $this->driver->getSql();
|
||||
$this->util = $this->driver->getUtil();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,7 +243,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->db = NULL;
|
||||
$this->driver = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,7 +259,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
// Alias snake_case method calls
|
||||
$camelName = \to_camel_case($name);
|
||||
|
||||
foreach([$this, $this->db] as $object)
|
||||
foreach([$this, $this->driver] as $object)
|
||||
{
|
||||
foreach([$name, $camelName] as $methodName)
|
||||
{
|
||||
@ -114,6 +274,15 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
throw new BadMethodCallException('Method does not exist');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Driver setters
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function setDriver(DriverInterface $driver)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Select Queries
|
||||
// --------------------------------------------------------------------------
|
||||
@ -141,14 +310,14 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
}
|
||||
|
||||
// Quote the identifiers
|
||||
$safeArray = $this->db->quoteIdent($fieldsArray);
|
||||
$safeArray = $this->driver->quoteIdent($fieldsArray);
|
||||
|
||||
unset($fieldsArray);
|
||||
|
||||
// Join the strings back together
|
||||
for($i = 0, $c = count($safeArray); $i < $c; $i++)
|
||||
{
|
||||
if (is_array($safeArray[$i]))
|
||||
if (\is_array($safeArray[$i]))
|
||||
{
|
||||
$safeArray[$i] = implode(' AS ', $safeArray[$i]);
|
||||
}
|
||||
@ -253,8 +422,8 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
$identArray = array_map('\\mb_trim', $identArray);
|
||||
|
||||
// Quote the identifiers
|
||||
$identArray[0] = $this->db->quoteTable($identArray[0]);
|
||||
$identArray = $this->db->quoteIdent($identArray);
|
||||
$identArray[0] = $this->driver->quoteTable($identArray[0]);
|
||||
$identArray = $this->driver->quoteIdent($identArray);
|
||||
|
||||
// Paste it back together
|
||||
$this->fromString = implode(' ', $identArray);
|
||||
@ -443,7 +612,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
|
||||
// Use the keys of the array to make the insert/update string
|
||||
// Escape the field names
|
||||
$this->setArrayKeys = array_map([$this->db, '_quote'], $this->setArrayKeys);
|
||||
$this->setArrayKeys = array_map([$this->driver, '_quote'], $this->setArrayKeys);
|
||||
|
||||
// Generate the "set" string
|
||||
$this->setString = implode('=?,', $this->setArrayKeys);
|
||||
@ -464,8 +633,8 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
{
|
||||
// Prefix and quote table name
|
||||
$table = explode(' ', mb_trim($table));
|
||||
$table[0] = $this->db->quoteTable($table[0]);
|
||||
$table = $this->db->quoteIdent($table);
|
||||
$table[0] = $this->driver->quoteTable($table[0]);
|
||||
$table = $this->driver->quoteIdent($table);
|
||||
$table = implode(' ', $table);
|
||||
|
||||
// Parse out the join condition
|
||||
@ -487,12 +656,12 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
{
|
||||
if ( ! is_scalar($field))
|
||||
{
|
||||
$newGroupArray = array_map([$this->db, 'quoteIdent'], $field);
|
||||
$newGroupArray = array_map([$this->driver, 'quoteIdent'], $field);
|
||||
$this->groupArray = array_merge($this->groupArray, $newGroupArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->groupArray[] = $this->db->quoteIdent($field);
|
||||
$this->groupArray[] = $this->driver->quoteIdent($field);
|
||||
}
|
||||
|
||||
$this->groupString = ' GROUP BY ' . implode(',', $this->groupArray);
|
||||
@ -507,7 +676,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
* @param string $type
|
||||
* @return QueryBuilderInterface
|
||||
*/
|
||||
public function orderBy($field, $type=""): QueryBuilderInterface
|
||||
public function orderBy($field, $type=''): QueryBuilderInterface
|
||||
{
|
||||
// When ordering by random, do an ascending order if the driver
|
||||
// doesn't support random ordering
|
||||
@ -518,7 +687,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
}
|
||||
|
||||
// Set fields for later manipulation
|
||||
$field = $this->db->quoteIdent($field);
|
||||
$field = $this->driver->quoteIdent($field);
|
||||
$this->orderArray[$field] = $type;
|
||||
|
||||
$orderClauses = [];
|
||||
@ -563,7 +732,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
*/
|
||||
public function groupStart(): QueryBuilderInterface
|
||||
{
|
||||
$conj = (empty($this->queryMap)) ? ' WHERE ' : ' ';
|
||||
$conj = empty($this->queryMap) ? ' WHERE ' : ' ';
|
||||
|
||||
$this->_appendMap($conj, '(', 'group_start');
|
||||
|
||||
@ -578,7 +747,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
*/
|
||||
public function notGroupStart(): QueryBuilderInterface
|
||||
{
|
||||
$conj = (empty($this->queryMap)) ? ' WHERE ' : ' AND ';
|
||||
$conj = empty($this->queryMap) ? ' WHERE ' : ' AND ';
|
||||
|
||||
$this->_appendMap($conj, ' NOT (', 'group_start');
|
||||
|
||||
@ -679,8 +848,8 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
*/
|
||||
public function countAll($table): int
|
||||
{
|
||||
$sql = 'SELECT * FROM '.$this->db->quoteTable($table);
|
||||
$res = $this->db->query($sql);
|
||||
$sql = 'SELECT * FROM '.$this->driver->quoteTable($table);
|
||||
$res = $this->driver->query($sql);
|
||||
return (int) count($res->fetchAll());
|
||||
}
|
||||
|
||||
@ -720,7 +889,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
$this->set($data);
|
||||
}
|
||||
|
||||
return $this->_run("insert", $table);
|
||||
return $this->_run('insert', $table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -733,7 +902,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
public function insertBatch($table, $data=[]): PDOStatement
|
||||
{
|
||||
// Get the generated values and sql string
|
||||
list($sql, $data) = $this->db->insertBatch($table, $data);
|
||||
list($sql, $data) = $this->driver->insertBatch($table, $data);
|
||||
|
||||
return ( ! is_null($sql))
|
||||
? $this->_run('', $table, $sql, $data)
|
||||
@ -754,7 +923,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
$this->set($data);
|
||||
}
|
||||
|
||||
return $this->_run("update", $table);
|
||||
return $this->_run('update', $table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -769,7 +938,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
public function updateBatch($table, $data, $where)
|
||||
{
|
||||
// Get the generated values and sql string
|
||||
list($sql, $data) = $this->db->updateBatch($table, $data, $where);
|
||||
list($sql, $data) = $this->driver->updateBatch($table, $data, $where);
|
||||
|
||||
return ( ! is_null($sql))
|
||||
? $this->_run('', $table, $sql, $data)
|
||||
@ -790,7 +959,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
$this->set($data);
|
||||
}
|
||||
|
||||
return $this->_run("replace", $table);
|
||||
return $this->_run('replace', $table);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -808,7 +977,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
$this->where($where);
|
||||
}
|
||||
|
||||
return $this->_run("delete", $table);
|
||||
return $this->_run('delete', $table);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@ -878,7 +1047,7 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetQuery()
|
||||
public function resetQuery(): void
|
||||
{
|
||||
// Reset strings and booleans
|
||||
foreach($this->stringVars as $var)
|
||||
@ -892,5 +1061,434 @@ class QueryBuilder extends AbstractQueryBuilder implements QueryBuilderInterface
|
||||
$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
|
||||
*
|
||||
* @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))
|
||||
{
|
||||
return $field;
|
||||
}
|
||||
|
||||
$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->queryMap) ? ' WHERE ' : " {$conj} ";
|
||||
$this->_appendMap($conj, $like, 'like');
|
||||
|
||||
// Add to the values array
|
||||
$this->whereValues[] = $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->havingMap[] = [
|
||||
'conjunction' => ( ! empty($this->havingMap)) ? " {$conj} " : ' HAVING ',
|
||||
'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 = [];
|
||||
$this->_mixedSet($where, $key, $val);
|
||||
$this->_mixedSet($this->whereValues, $key, $val, self::VALUE);
|
||||
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)
|
||||
{
|
||||
// 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($this->queryMap);
|
||||
|
||||
// Determine the correct conjunction
|
||||
$conjunctionList = array_column($this->queryMap, 'conjunction');
|
||||
if (empty($this->queryMap) || ( ! regex_in_array($conjunctionList, "/^ ?\n?WHERE/i")))
|
||||
{
|
||||
$conj = "\nWHERE ";
|
||||
}
|
||||
elseif ($lastItem['type'] === 'group_start')
|
||||
{
|
||||
$conj = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$conj = " {$defaultConj} ";
|
||||
}
|
||||
|
||||
$this->_appendMap($conj, $item, '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), '?');
|
||||
|
||||
foreach($val as $v)
|
||||
{
|
||||
$this->whereValues[] = $v;
|
||||
}
|
||||
|
||||
$conjunction = ( ! empty($this->queryMap)) ? " {$conj} " : ' WHERE ';
|
||||
$str = $key . " {$in} (".implode(',', $params).') ';
|
||||
|
||||
$this->_appendMap($conjunction, $str, '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, $sql=NULL, $vals=NULL, bool $reset=TRUE): PDOStatement
|
||||
{
|
||||
if ($sql === NULL)
|
||||
{
|
||||
$sql = $this->_compile($type, $table);
|
||||
}
|
||||
|
||||
if ($vals === NULL)
|
||||
{
|
||||
$vals = array_merge($this->values, (array) $this->whereValues);
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param array $vals
|
||||
* @param string $sql
|
||||
* @param int $totalTime
|
||||
* @return void
|
||||
*/
|
||||
protected function _appendQuery($vals, string $sql, int $totalTime)
|
||||
{
|
||||
$evals = \is_array($vals) ? $vals : [];
|
||||
$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;
|
||||
}
|
||||
|
||||
// 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
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $table
|
||||
* @return string
|
||||
*/
|
||||
protected function _compileType(string $type='', string $table=''): string
|
||||
{
|
||||
switch($type)
|
||||
{
|
||||
case 'insert':
|
||||
$paramCount = count($this->setArrayKeys);
|
||||
$params = array_fill(0, $paramCount, '?');
|
||||
$sql = "INSERT INTO {$table} ("
|
||||
. implode(',', $this->setArrayKeys)
|
||||
. ")\nVALUES (".implode(',', $params).')';
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
$sql = "UPDATE {$table}\nSET {$this->setString}";
|
||||
break;
|
||||
|
||||
case 'replace':
|
||||
// @TODO implement
|
||||
$sql = '';
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
$sql = "DELETE FROM {$table}";
|
||||
break;
|
||||
|
||||
// Get queries
|
||||
default:
|
||||
$sql = "SELECT * \nFROM {$this->fromString}";
|
||||
|
||||
// Set the select string
|
||||
if ( ! empty($this->selectString))
|
||||
{
|
||||
// Replace the star with the selected fields
|
||||
$sql = str_replace('*', $this->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)
|
||||
{
|
||||
$param = $this->$clause;
|
||||
if (\is_array($param))
|
||||
{
|
||||
foreach($param as $q)
|
||||
{
|
||||
$sql .= $q['conjunction'] . $q['string'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql .= $param;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the limit via the class variables
|
||||
if (is_numeric($this->limit))
|
||||
{
|
||||
$sql = $this->sql->limit($sql, $this->limit, $this->offset);
|
||||
}
|
||||
|
||||
// See if the query plan, rather than the
|
||||
// query data should be returned
|
||||
if ($this->explain === TRUE)
|
||||
{
|
||||
$sql = $this->sql->explain($sql);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
||||
// End of query_builder.php
|
@ -527,7 +527,7 @@ interface QueryBuilderInterface {
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetQuery();
|
||||
public function resetQuery(): void;
|
||||
}
|
||||
|
||||
// End of QueryBuilderInterface.php
|
||||
|
@ -62,6 +62,8 @@ abstract class BaseQueryBuilderTest extends TestCase {
|
||||
$query = self::$db->get('test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
$lastQuery = self::$db->getLastQuery();
|
||||
$this->assertTrue(\is_string($lastQuery));
|
||||
}
|
||||
|
||||
public function testPrefixGet()
|
||||
@ -519,6 +521,7 @@ abstract class BaseQueryBuilderTest extends TestCase {
|
||||
->insert('test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
$this->assertTrue(self::$db->affectedRows() > 0);
|
||||
}
|
||||
|
||||
public function testInsertArray()
|
||||
@ -569,6 +572,12 @@ abstract class BaseQueryBuilderTest extends TestCase {
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
public function testUpdateBatch()
|
||||
{
|
||||
$query = self::$db->updateBatch('test', [], '');
|
||||
$this->assertNull($query);
|
||||
}
|
||||
|
||||
public function testSetArrayUpdate()
|
||||
{
|
||||
$array = array(
|
||||
|
@ -51,7 +51,7 @@ class MySQLDriverTest extends BaseDriverTest {
|
||||
|
||||
public function testExists()
|
||||
{
|
||||
$this->assertTrue(in_array('mysql', PDO::getAvailableDrivers()));
|
||||
$this->assertTrue(\in_array('mysql', PDO::getAvailableDrivers(), TRUE));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@ -97,7 +97,7 @@ class MySQLDriverTest extends BaseDriverTest {
|
||||
//Check
|
||||
$dbs = self::$db->getTables();
|
||||
|
||||
$this->assertTrue(in_array('create_test', $dbs));
|
||||
$this->assertTrue(\in_array('create_test', $dbs, TRUE));
|
||||
|
||||
}
|
||||
|
||||
|
@ -43,11 +43,11 @@ class PgSQLQueryBuilderTest extends BaseQueryBuilderTest {
|
||||
else if ($params !== FALSE)
|
||||
{
|
||||
$params = $params->pgsql;
|
||||
$params->type = "pgsql";
|
||||
$params->type = 'pgsql';
|
||||
//$params->port = 5432;
|
||||
//$params->prefix = 'create_';
|
||||
$params->options = array();
|
||||
$params->options[\PDO::ATTR_PERSISTENT] = TRUE;
|
||||
$params->options[PDO::ATTR_PERSISTENT] = TRUE;
|
||||
}
|
||||
|
||||
self::$db = Query($params);
|
||||
@ -56,7 +56,7 @@ class PgSQLQueryBuilderTest extends BaseQueryBuilderTest {
|
||||
public function setUp()
|
||||
{
|
||||
// If the database isn't installed, skip the tests
|
||||
if ( ! in_array('pgsql', PDO::getAvailableDrivers()))
|
||||
if ( ! \in_array('pgsql', PDO::getAvailableDrivers(), TRUE))
|
||||
{
|
||||
$this->markTestSkipped("Postgres extension for PDO not loaded");
|
||||
}
|
||||
@ -66,7 +66,7 @@ class PgSQLQueryBuilderTest extends BaseQueryBuilderTest {
|
||||
|
||||
public function testExists()
|
||||
{
|
||||
$this->assertTrue(in_array('pgsql', PDO::getAvailableDrivers()));
|
||||
$this->assertTrue(\in_array('pgsql', PDO::getAvailableDrivers(), TRUE));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@ -84,7 +84,7 @@ class PgSQLQueryBuilderTest extends BaseQueryBuilderTest {
|
||||
// The exact results are version dependent
|
||||
// The important thing is that there is an array
|
||||
// of results returned
|
||||
$this->assertTrue(is_array($res));
|
||||
$this->assertTrue(\is_array($res));
|
||||
$this->assertTrue(count($res) > 1);
|
||||
$this->assertTrue(array_key_exists('QUERY PLAN', $res[0]));
|
||||
|
||||
@ -117,6 +117,6 @@ class PgSQLQueryBuilderTest extends BaseQueryBuilderTest {
|
||||
|
||||
public function testBackupStructure()
|
||||
{
|
||||
$this->assertEquals('', self::$db->util->backupStructure());
|
||||
$this->assertEquals('', self::$db->getUtil()->backupStructure());
|
||||
}
|
||||
}
|
@ -183,7 +183,7 @@ SQL;
|
||||
$db = new $class(QTEST_DIR.QDS.'db_files'.QDS.'test_sqlite.db');
|
||||
|
||||
$this->assertIsA($db, $class);
|
||||
$this->assertIsA(self::$db->db, $class);
|
||||
$this->assertIsA(self::$db->driver, $class);
|
||||
|
||||
unset($db);
|
||||
}
|
||||
@ -286,13 +286,13 @@ SQL;
|
||||
|
||||
public function testNullMethods()
|
||||
{
|
||||
$sql = self::$db->sql->functionList();
|
||||
$sql = self::$db->getSQL()->functionList();
|
||||
$this->assertEqual(NULL, $sql);
|
||||
|
||||
$sql = self::$db->sql->procedureList();
|
||||
$sql = self::$db->getSQL()->procedureList();
|
||||
$this->assertEqual(NULL, $sql);
|
||||
|
||||
$sql = self::$db->sql->sequenceList();
|
||||
$sql = self::$db->getSQL()->sequenceList();
|
||||
$this->assertEqual(NULL, $sql);
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,10 @@ use Query\Drivers\Sqlite\Driver;
|
||||
* Tests for the Query Parser
|
||||
*/
|
||||
class QueryParserTest extends TestCase {
|
||||
/**
|
||||
* @var QueryParser
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user