SQLite improvements, remove nullable PDOStatement return values

This commit is contained in:
Timothy Warren 2018-01-26 15:45:46 -05:00
parent 6a3db6581a
commit 33bb440bd2
16 changed files with 134 additions and 77 deletions

2
.gitignore vendored
View File

@ -130,7 +130,7 @@ $RECYCLE.BIN/
test_config.json test_config.json
index.html index.html
tests/db_files/* tests/db_files/*.db
build/api/* build/api/*
build/coverage/* build/coverage/*
build/logs/* build/logs/*

View File

@ -15,7 +15,6 @@
namespace Query; namespace Query;
use DomainException; use DomainException;
use InvalidArgumentException;
/** /**
* Connection manager class to manage connections for the * Connection manager class to manage connections for the
@ -97,7 +96,7 @@ final class ConnectionManager {
* *
* @param string|array|object $name * @param string|array|object $name
* @return QueryBuilderInterface * @return QueryBuilderInterface
* @throws InvalidArgumentException * @throws Exception\NonExistentConnectionException
*/ */
public function getConnection($name = ''): QueryBuilderInterface public function getConnection($name = ''): QueryBuilderInterface
{ {
@ -112,14 +111,14 @@ final class ConnectionManager {
} }
// You should actually connect before trying to get a connection... // You should actually connect before trying to get a connection...
throw new InvalidArgumentException('The specified connection does not exist'); throw new Exception\NonExistentConnectionException('The specified connection does not exist');
} }
/** /**
* Parse the passed parameters and return a connection * Parse the passed parameters and return a connection
* *
* @param object|array $params * @param object|array $params
* @throws BadDBDriverException * @throws Exception\BadDBDriverException
* @return QueryBuilderInterface * @return QueryBuilderInterface
*/ */
public function connect($params): QueryBuilderInterface public function connect($params): QueryBuilderInterface
@ -162,7 +161,7 @@ final class ConnectionManager {
* *
* @param \stdClass $params * @param \stdClass $params
* @return object|array * @return object|array
* @throws BadDBDriverException * @throws Exception\BadDBDriverException
*/ */
public function parseParams($params): array public function parseParams($params): array
{ {
@ -174,7 +173,7 @@ final class ConnectionManager {
// Make sure the class exists // Make sure the class exists
if ( ! class_exists("\\Query\\Drivers\\{$dbtype}\\Driver")) if ( ! class_exists("\\Query\\Drivers\\{$dbtype}\\Driver"))
{ {
throw new BadDBDriverException('Database driver does not exist, or is not supported'); throw new Exception\BadDBDriverException('Database driver does not exist, or is not supported');
} }
// Set additional PDO options // Set additional PDO options

View File

@ -199,7 +199,7 @@ abstract class AbstractDriver
* @return PDOStatement | FALSE * @return PDOStatement | FALSE
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function prepareQuery(string $sql, array $data): ?PDOStatement public function prepareQuery(string $sql, array $data): PDOStatement
{ {
// Prepare the sql, save the statement for easy access later // Prepare the sql, save the statement for easy access later
$this->statement = $this->prepare($sql); $this->statement = $this->prepare($sql);
@ -227,7 +227,7 @@ abstract class AbstractDriver
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @return PDOStatement * @return PDOStatement
*/ */
public function prepareExecute(string $sql, array $params): ?PDOStatement public function prepareExecute(string $sql, array $params): PDOStatement
{ {
$this->statement = $this->prepareQuery($sql, $params); $this->statement = $this->prepareQuery($sql, $params);
$this->statement->execute(); $this->statement->execute();
@ -636,7 +636,7 @@ abstract class AbstractDriver
* @param string $table * @param string $table
* @return PDOStatement * @return PDOStatement
*/ */
public function truncate(string $table): ?PDOStatement public function truncate(string $table): PDOStatement
{ {
$sql = $this->hasTruncate $sql = $this->hasTruncate
? 'TRUNCATE TABLE ' ? 'TRUNCATE TABLE '

View File

@ -14,7 +14,6 @@
*/ */
namespace Query\Drivers; namespace Query\Drivers;
use PDO;
use PDOStatement; use PDOStatement;
/** /**
@ -40,7 +39,7 @@ interface DriverInterface {
* @return \PDOStatement|null * @return \PDOStatement|null
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public function prepareQuery(string $sql, array $data): ?PDOStatement; public function prepareQuery(string $sql, array $data): PDOStatement;
/** /**
* Retrieve column information for the current database table * Retrieve column information for the current database table
@ -162,7 +161,7 @@ interface DriverInterface {
* @param array $params * @param array $params
* @return PDOStatement * @return PDOStatement
*/ */
public function prepareExecute(string $sql, array $params): ?PDOStatement; public function prepareExecute(string $sql, array $params): PDOStatement;
/** /**
* Method to simplify retrieving db results for meta-data queries * Method to simplify retrieving db results for meta-data queries

View File

@ -67,7 +67,10 @@ class SQL extends AbstractSQL {
*/ */
public function dbList(): string public function dbList(): string
{ {
return "SHOW DATABASES WHERE `Database` NOT IN ('information_schema','mysql')"; return <<<SQL
SHOW DATABASES WHERE `Database` NOT IN ('information_schema','mysql')
SQL;
} }
/** /**
@ -95,8 +98,10 @@ class SQL extends AbstractSQL {
*/ */
public function systemTableList(): string public function systemTableList(): string
{ {
return 'SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` return <<<SQL
WHERE `TABLE_SCHEMA`=\'information_schema\''; SELECT `TABLE_NAME` FROM `information_schema`.`TABLES`
WHERE `TABLE_SCHEMA`='information_schema'
SQL;
} }
/** /**
@ -156,7 +161,7 @@ class SQL extends AbstractSQL {
*/ */
public function typeList(): string public function typeList(): string
{ {
return "SELECT DISTINCT `DATA_TYPE` FROM `information_schema`.`COLUMNS`"; return 'SELECT DISTINCT `DATA_TYPE` FROM `information_schema`.`COLUMNS`';
} }
/** /**
@ -180,11 +185,12 @@ class SQL extends AbstractSQL {
public function fkList(string $table): string public function fkList(string $table): string
{ {
return <<<SQL return <<<SQL
SELECT DISTINCT `kcu`.`COLUMN_NAME` as `child_column`, SELECT DISTINCT
`kcu`.`REFERENCED_TABLE_NAME` as `parent_table`, `kcu`.`COLUMN_NAME` as `child_column`,
`kcu`.`REFERENCED_COLUMN_NAME` as `parent_column`, `kcu`.`REFERENCED_TABLE_NAME` as `parent_table`,
`rc`.`UPDATE_RULE` AS `update`, `kcu`.`REFERENCED_COLUMN_NAME` as `parent_column`,
`rc`.`DELETE_RULE` AS `delete` `rc`.`UPDATE_RULE` AS `update`,
`rc`.`DELETE_RULE` AS `delete`
FROM `INFORMATION_SCHEMA`.`TABLE_CONSTRAINTS` `tc` FROM `INFORMATION_SCHEMA`.`TABLE_CONSTRAINTS` `tc`
INNER JOIN `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` `kcu` INNER JOIN `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` `kcu`
ON `kcu`.`CONSTRAINT_NAME`=`tc`.`CONSTRAINT_NAME` ON `kcu`.`CONSTRAINT_NAME`=`tc`.`CONSTRAINT_NAME`

View File

@ -15,6 +15,7 @@
namespace Query\Drivers\Sqlite; namespace Query\Drivers\Sqlite;
use Query\Drivers\AbstractSQL; use Query\Drivers\AbstractSQL;
use Query\Exception\NotImplementedException;
/** /**
* SQLite Specific SQL * SQLite Specific SQL
@ -60,11 +61,13 @@ class SQL extends AbstractSQL {
public function tableList(): string public function tableList(): string
{ {
return <<<SQL return <<<SQL
SELECT DISTINCT "name" SELECT "name" FROM (
FROM "sqlite_master" SELECT * FROM "sqlite_master" UNION ALL
WHERE "type"='table' SELECT * FROM "sqlite_temp_master"
AND "name" NOT LIKE 'sqlite_%' )
ORDER BY "name" DESC WHERE "type"='table'
AND "name" NOT LIKE "sqlite_%"
ORDER BY "name"
SQL; SQL;
} }
@ -75,7 +78,11 @@ SQL;
*/ */
public function systemTableList(): array public function systemTableList(): array
{ {
return ['sqlite_master', 'sqlite_temp_master', 'sqlite_sequence']; return [
'sqlite_master',
'sqlite_temp_master',
'sqlite_sequence'
];
} }
/** /**
@ -97,27 +104,31 @@ SQL;
*/ */
public function triggerList(): string public function triggerList(): string
{ {
return 'SELECT "name" FROM "sqlite_master" WHERE "type"=\'trigger\''; return <<<SQL
SELECT "name" FROM "sqlite_master" WHERE "type"='trigger'
SQL;
} }
/** /**
* Return sql to list functions * Return sql to list functions
* *
* @throws NotImplementedException
* @return string * @return string
*/ */
public function functionList(): ?string public function functionList(): string
{ {
return NULL; throw new NotImplementedException('Functionality does not exist in SQLite');
} }
/** /**
* Return sql to list stored procedures * Return sql to list stored procedures
* *
* @throws NotImplementedException
* @return string * @return string
*/ */
public function procedureList(): ?string public function procedureList(): string
{ {
return NULL; throw new NotImplementedException('Functionality does not exist in SQLite');
} }
/** /**
@ -125,9 +136,9 @@ SQL;
* *
* @return string * @return string
*/ */
public function sequenceList(): ?string public function sequenceList(): string
{ {
return NULL; return 'SELECT "name" FROM "sqlite_sequence"';
} }
/** /**
@ -137,7 +148,7 @@ SQL;
*/ */
public function typeList(): array public function typeList(): array
{ {
return ['INTEGER', 'REAL', 'TEXT', 'BLOB']; return ['INTEGER', 'REAL', 'TEXT', 'BLOB', 'NULL'];
} }
/** /**
@ -148,7 +159,9 @@ SQL;
*/ */
public function columnList(string $table): string public function columnList(string $table): string
{ {
return 'PRAGMA table_info("' . $table . '")'; return <<<SQL
PRAGMA table_info("$table")
SQL;
} }
/** /**
@ -160,7 +173,9 @@ SQL;
*/ */
public function fkList(string $table): string public function fkList(string $table): string
{ {
return 'PRAGMA foreign_key_list("' . $table . '")'; return <<<SQL
PRAGMA foreign_key_list("$table")
SQL;
} }
@ -172,6 +187,8 @@ SQL;
*/ */
public function indexList(string $table): string public function indexList(string $table): string
{ {
return 'PRAGMA index_list("' . $table . '")'; return <<<SQL
PRAGMA index_list("$table")
SQL;
} }
} }

View File

@ -19,9 +19,6 @@ use Query\Drivers\AbstractUtil;
/** /**
* SQLite-specific backup, import and creation methods * SQLite-specific backup, import and creation methods
*
* @method mixed query(string $sql)
* @method string quote(string $str)
*/ */
class Util extends AbstractUtil { class Util extends AbstractUtil {
@ -78,7 +75,7 @@ class Util extends AbstractUtil {
// Quote values as needed by type // Quote values as needed by type
for($i=0, $icount=count($row); $i<$icount; $i++) for($i=0, $icount=count($row); $i<$icount; $i++)
{ {
$row[$i] = (is_numeric($row[$i])) ? $row[$i] : $this->getDriver()->quote($row[$i]); $row[$i] = is_numeric($row[$i]) ? $row[$i] : $this->getDriver()->quote($row[$i]);
} }
$rowString = 'INSERT INTO "'.$r['name'].'" ("'.implode('","', $columns).'") VALUES ('.implode(',', $row).');'; $rowString = 'INSERT INTO "'.$r['name'].'" ("'.implode('","', $columns).'") VALUES ('.implode(',', $row).');';

View File

@ -12,7 +12,7 @@
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link https://git.timshomepage.net/aviat4ion/Query * @link https://git.timshomepage.net/aviat4ion/Query
*/ */
namespace Query; namespace Query\Exception;
use InvalidArgumentException; use InvalidArgumentException;

View File

@ -0,0 +1,23 @@
<?php declare(strict_types=1);
/**
* Query
*
* SQL Query Builder / Database Abstraction Layer
*
* PHP version 7.1
*
* @package Query
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2012 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link https://git.timshomepage.net/aviat4ion/Query
*/
namespace Query\Exception;
use InvalidArgumentException;
/**
* Exception for missing database connection
*/
class NonExistentConnectionException extends InvalidArgumentException {
}

View File

@ -0,0 +1,23 @@
<?php declare(strict_types=1);
/**
* Query
*
* SQL Query Builder / Database Abstraction Layer
*
* PHP version 7.1
*
* @package Query
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2012 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link https://git.timshomepage.net/aviat4ion/Query
*/
namespace Query\Exception;
use BadMethodCallException;
/**
* Exception for non-implemented method
*/
class NotImplementedException extends BadMethodCallException{
}

View File

@ -648,7 +648,7 @@ class QueryBuilder implements QueryBuilderInterface {
* @param int|bool $offset * @param int|bool $offset
* @return PDOStatement * @return PDOStatement
*/ */
public function get(string $table='', $limit=FALSE, $offset=FALSE): ?PDOStatement public function get(string $table='', $limit=FALSE, $offset=FALSE): PDOStatement
{ {
// Set the table // Set the table
if ( ! empty($table)) if ( ! empty($table))
@ -674,7 +674,7 @@ class QueryBuilder implements QueryBuilderInterface {
* @param int|bool $offset * @param int|bool $offset
* @return PDOStatement * @return PDOStatement
*/ */
public function getWhere(string $table, $where=[], $limit=FALSE, $offset=FALSE): ?PDOStatement public function getWhere(string $table, $where=[], $limit=FALSE, $offset=FALSE): PDOStatement
{ {
// Create the where clause // Create the where clause
$this->where($where); $this->where($where);
@ -725,7 +725,7 @@ class QueryBuilder implements QueryBuilderInterface {
* @param mixed $data * @param mixed $data
* @return PDOStatement * @return PDOStatement
*/ */
public function insert(string $table, $data=[]): ?PDOStatement public function insert(string $table, $data=[]): PDOStatement
{ {
if ( ! empty($data)) if ( ! empty($data))
{ {
@ -742,7 +742,7 @@ class QueryBuilder implements QueryBuilderInterface {
* @param array $data * @param array $data
* @return PDOStatement * @return PDOStatement
*/ */
public function insertBatch(string $table, $data=[]): ?PDOStatement public function insertBatch(string $table, $data=[]): PDOStatement
{ {
// Get the generated values and sql string // Get the generated values and sql string
[$sql, $data] = $this->driver->insertBatch($table, $data); [$sql, $data] = $this->driver->insertBatch($table, $data);
@ -799,7 +799,7 @@ class QueryBuilder implements QueryBuilderInterface {
* @param array $data * @param array $data
* @return \PDOStatement|null * @return \PDOStatement|null
*/ */
public function replace(string $table, $data=[]): ?PDOStatement public function replace(string $table, $data=[]): PDOStatement
{ {
if ( ! empty($data)) if ( ! empty($data))
{ {
@ -816,7 +816,7 @@ class QueryBuilder implements QueryBuilderInterface {
* @param mixed $where * @param mixed $where
* @return PDOStatement * @return PDOStatement
*/ */
public function delete(string $table, $where=''): ?PDOStatement public function delete(string $table, $where=''): PDOStatement
{ {
// Set the where clause // Set the where clause
if ( ! empty($where)) if ( ! empty($where))
@ -1167,7 +1167,7 @@ class QueryBuilder implements QueryBuilderInterface {
* @param int $totalTime * @param int $totalTime
* @return void * @return void
*/ */
protected function _appendQuery(array $values = NULL, string $sql, int $totalTime) protected function _appendQuery(array $values = NULL, string $sql, int $totalTime): void
{ {
$evals = \is_array($values) ? $values : []; $evals = \is_array($values) ? $values : [];
$esql = str_replace('?', "%s", $sql); $esql = str_replace('?', "%s", $sql);

View File

@ -322,7 +322,7 @@ interface QueryBuilderInterface {
* @param int|bool $offset * @param int|bool $offset
* @return PDOStatement * @return PDOStatement
*/ */
public function get(string $table='', $limit=FALSE, $offset=FALSE): ?PDOStatement; public function get(string $table='', $limit=FALSE, $offset=FALSE): PDOStatement;
/** /**
* Convenience method for get() with a where clause * Convenience method for get() with a where clause
@ -333,7 +333,7 @@ interface QueryBuilderInterface {
* @param int|bool $offset * @param int|bool $offset
* @return PDOStatement * @return PDOStatement
*/ */
public function getWhere(string $table, $where=[], $limit=FALSE, $offset=FALSE): ?PDOStatement; public function getWhere(string $table, $where=[], $limit=FALSE, $offset=FALSE): PDOStatement;
/** /**
* Retrieve the number of rows in the selected table * Retrieve the number of rows in the selected table
@ -360,7 +360,7 @@ interface QueryBuilderInterface {
* @param mixed $data * @param mixed $data
* @return PDOStatement * @return PDOStatement
*/ */
public function insert(string $table, $data=[]): ?PDOStatement; public function insert(string $table, $data=[]): PDOStatement;
/** /**
* Creates and executes a batch insertion query * Creates and executes a batch insertion query
@ -369,7 +369,7 @@ interface QueryBuilderInterface {
* @param array $data * @param array $data
* @return PDOStatement * @return PDOStatement
*/ */
public function insertBatch(string $table, $data=[]): ?PDOStatement; public function insertBatch(string $table, $data=[]): PDOStatement;
/** /**
* Insertion with automatic overwrite, rather than attempted duplication * Insertion with automatic overwrite, rather than attempted duplication
@ -378,7 +378,7 @@ interface QueryBuilderInterface {
* @param array $data * @param array $data
* @return PDOStatement * @return PDOStatement
*/ */
public function replace(string $table, $data=[]): ?PDOStatement; public function replace(string $table, $data=[]): PDOStatement;
/** /**
* Creates an update clause, and executes it * Creates an update clause, and executes it
@ -387,7 +387,7 @@ interface QueryBuilderInterface {
* @param mixed $data * @param mixed $data
* @return PDOStatement * @return PDOStatement
*/ */
public function update(string $table, $data=[]): ?PDOStatement; public function update(string $table, $data=[]): PDOStatement;
/** /**
* Creates a batch update, and executes it. * Creates a batch update, and executes it.
@ -407,7 +407,7 @@ interface QueryBuilderInterface {
* @param mixed $where * @param mixed $where
* @return PDOStatement * @return PDOStatement
*/ */
public function delete(string $table, $where=''): ?PDOStatement; public function delete(string $table, $where=''): PDOStatement;
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// ! SQL Returning Methods // ! SQL Returning Methods

View File

@ -16,7 +16,7 @@ namespace Query\Tests;
use BadMethodCallException; use BadMethodCallException;
use PDO; use PDO;
use Query\BadDBDriverException; use Query\Exception\BadDBDriverException;
/** /**
* Query builder parent test class * Query builder parent test class

View File

@ -16,6 +16,7 @@ namespace Query\Tests\Drivers\SQLite;
use PDO; use PDO;
use Query\Drivers\Sqlite\Driver; use Query\Drivers\Sqlite\Driver;
use Query\Exception\NotImplementedException;
use Query\Tests\BaseDriverTest; use Query\Tests\BaseDriverTest;
/** /**
@ -83,7 +84,8 @@ SQL;
{ {
$sql = mb_trim(self::$db->getUtil()->backupStructure()); $sql = mb_trim(self::$db->getUtil()->backupStructure());
$expected = <<<SQL $expected = <<<SQL
CREATE TABLE "create_test" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT); CREATE TABLE "create_test" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "key" TEXT, "val" TEXT);
CREATE TABLE sqlite_sequence(name,seq);
CREATE TABLE "create_join" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT); CREATE TABLE "create_join" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT);
CREATE TABLE "create_delete" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT); CREATE TABLE "create_delete" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT);
CREATE TABLE TEST1 ( CREATE TABLE TEST1 (
@ -250,7 +252,7 @@ SQL;
public function testGetDBs() public function testGetDBs()
{ {
$this->assertTrue(is_array(self::$db->getDbs())); $this->assertTrue(\is_array(self::$db->getDbs()));
} }
public function testGetSchemas() public function testGetSchemas()
@ -262,18 +264,6 @@ SQL;
// ! SQL tests // ! SQL tests
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
public function testNullMethods()
{
$sql = self::$db->getSQL()->functionList();
$this->assertEqual(NULL, $sql);
$sql = self::$db->getSQL()->procedureList();
$this->assertEqual(NULL, $sql);
$sql = self::$db->getSQL()->sequenceList();
$this->assertEqual(NULL, $sql);
}
public function testGetSystemTables() public function testGetSystemTables()
{ {
$sql = self::$db->getSystemTables(); $sql = self::$db->getSystemTables();
@ -282,16 +272,19 @@ SQL;
public function testGetSequences() public function testGetSequences()
{ {
$this->assertNull(self::$db->getSequences()); $sql = self::$db->getSequences();
$this->assertEquals(['create_test'], $sql);
} }
public function testGetFunctions() public function testGetFunctions()
{ {
$this->assertNull(self::$db->getFunctions()); $this->expectException(NotImplementedException::class);
self::$db->getFunctions();
} }
public function testGetProcedures() public function testGetProcedures()
{ {
$this->assertNull(self::$db->getProcedures()); $this->expectException(NotImplementedException::class);
self::$db->getProcedures();
} }
} }

0
tests/db_files/oci.sql Normal file
View File

View File

@ -1,5 +1,5 @@
-- sample data to test SQLite -- sample data to test SQLite
CREATE TABLE IF NOT EXISTS "create_test" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT); CREATE TABLE IF NOT EXISTS "create_test" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "key" TEXT, "val" TEXT);
CREATE TABLE IF NOT EXISTS "create_join" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT); CREATE TABLE IF NOT EXISTS "create_join" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT);
CREATE TABLE IF NOT EXISTS "create_delete" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT); CREATE TABLE IF NOT EXISTS "create_delete" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT);