Prepwork for 'returning' method of Query builder

This commit is contained in:
Timothy Warren 2019-12-13 15:11:49 -05:00
parent 78705bf796
commit 2bf8897918
13 changed files with 131 additions and 21 deletions

View File

@ -2,22 +2,20 @@
A query builder/database abstraction layer, using prepared statements for security. A query builder/database abstraction layer, using prepared statements for security.
[![Build Status](https://jenkins.timshomepage.net/buildStatus/icon?job=query)](https://jenkins.timshomepage.net/job/query/)
[![Code Coverage](https://scrutinizer-ci.com/g/aviat4ion/Query/badges/coverage.png?b=develop)](https://scrutinizer-ci.com/g/aviat4ion/Query/?branch=develop) [![Code Coverage](https://scrutinizer-ci.com/g/aviat4ion/Query/badges/coverage.png?b=develop)](https://scrutinizer-ci.com/g/aviat4ion/Query/?branch=develop)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/aviat4ion/Query/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/aviat4ion/Query/?branch=develop) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/aviat4ion/Query/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/aviat4ion/Query/?branch=develop)
[![Latest Stable Version](https://poser.pugx.org/aviat/query/v/stable.png)](https://packagist.org/packages/aviat/query) [![Latest Stable Version](https://poser.pugx.org/aviat/query/v/stable.png)](https://packagist.org/packages/aviat/query)
[![Total Downloads](https://poser.pugx.org/aviat/query/downloads.png)](https://packagist.org/packages/aviat/query) [![Total Downloads](https://poser.pugx.org/aviat/query/downloads.png)](https://packagist.org/packages/aviat/query)
[![Latest Unstable Version](https://poser.pugx.org/aviat/query/v/unstable.png)](https://packagist.org/packages/aviat/query) [![Latest Unstable Version](https://poser.pugx.org/aviat/query/v/unstable.png)](https://packagist.org/packages/aviat/query)
[![License](https://poser.pugx.org/aviat/query/license.png)](http://www.dbad-license.org/)
## Requirements ## Requirements
* PDO extensions for the databases you wish to use (unless it's Firebird, in which case, the interbase extension is required) * PDO extensions for the databases you wish to use
* PHP 7.1 or later * PHP 7.2 or later
## Databases Supported ## Databases Supported
* MySQL * MySQL 5+ / MariaDB
* PostgreSQL * PostgreSQL 8.4+
* SQLite * SQLite
## Including Query in your application ## Including Query in your application
@ -40,7 +38,7 @@ $params = array(
'database' => 'test_db', 'database' => 'test_db',
// Only required for // Only required for
// SQLite // SQLite
'file' => '/path/to/db/file', 'file' => '/path/to/db/file',
// Optional parameters // Optional parameters
@ -78,12 +76,12 @@ Query('old')->query($sql);
``` ```
### Running Queries ### Running Queries
Query is based on CodeIgniter's [Query Builder](http://www.codeigniter.com/user_guide/database/query_builder.html) class. Query is based on CodeIgniter's [Query Builder](http://www.codeigniter.com/user_guide/database/query_builder.html) class.
However, it has camelCased method names, and does not implement the caching methods. However, it has camelCased method names, and does not implement the caching methods.
For specific query builder methods, see the [class documentation](https://gitdev.timshomepage.net/Query/apiDocumentation/classes/Query_QueryBuilder.html#methods). For specific query builder methods, see the [class documentation](https://gitdev.timshomepage.net/Query/apiDocumentation/classes/Query_QueryBuilder.html#methods).
Other database methods not directly involved in building queries, are also available from the query builder object. Other database methods not directly involved in building queries, are also available from the query builder object.
The methods available depend on the database, but common methods are documented The methods available depend on the database, but common methods are documented
[here](https://gitdev.timshomepage.net/Query/apiDocumentation/classes/Query_Drivers_AbstractDriver.html#methods). [here](https://gitdev.timshomepage.net/Query/apiDocumentation/classes/Query_Drivers_AbstractDriver.html#methods).
#### You can also run queries manually. #### You can also run queries manually.
@ -102,7 +100,7 @@ An example of a moderately complex query:
$query = $db->select('id, key as k, val') $query = $db->select('id, key as k, val')
->from('table t') ->from('table t')
->where('k >', 3) ->where('k >', 3)
->orWhere('id !=' 5) ->orWhere('id !=', 5)
->orderBy('val', 'DESC') ->orderBy('val', 'DESC')
->limit(3, 1) ->limit(3, 1)
->get(); ->get();
@ -120,9 +118,9 @@ LIMIT 3 OFFSET 1
``` ```
The query execution methods `get`, `getWhere`, `insert`, The query execution methods `get`, `getWhere`, `insert`,
`insertBatch`,`update`, and `delete` return a native [PDOStatemnt](http://php.net/manual/en/class.pdostatement.php) object. `insertBatch`,`update`, and `delete` return a native [PDOStatement](http://php.net/manual/en/class.pdostatement.php) object.
To retrieve the results of a query, use the PDOStatement method [fetch](http://php.net/manual/en/pdostatement.fetch.php) and/or To retrieve the results of a query, use the PDOStatement method [fetch](http://php.net/manual/en/pdostatement.fetch.php) and/or
[fetchAll](http://php.net/manual/en/pdostatement.fetchall.php). [fetchAll](http://php.net/manual/en/pdostatement.fetchall.php).
```php ```php
<?php <?php

View File

@ -474,6 +474,16 @@ abstract class AbstractDriver
return $this->driverQuery('typeList', FALSE); return $this->driverQuery('typeList', FALSE);
} }
/**
* Get the version of the database engine
*
* @return string
*/
public function getVersion(): string
{
return $this->getAttribute(PDO::ATTR_SERVER_VERSION);
}
/** /**
* Method to simplify retrieving db results for meta-data queries * Method to simplify retrieving db results for meta-data queries
* *
@ -653,6 +663,18 @@ abstract class AbstractDriver
return $this->statement; return $this->statement;
} }
/**
* Generate the returning clause for the current database
*
* @param string $query
* @param string $select
* @return string
*/
public function returning(string $query, string $select): string
{
return "{$query} RETURNING {$select}";
}
/** /**
* Helper method for quote_ident * Helper method for quote_ident
* *

View File

@ -253,6 +253,13 @@ interface DriverInterface /* extends the interface of PDO */ {
*/ */
public function getUtil(): AbstractUtil; public function getUtil(): AbstractUtil;
/**
* Get the version of the database engine
*
* @return string
*/
public function getVersion(): string;
/** /**
* Get the last sql query executed * Get the last sql query executed
* *

View File

@ -63,4 +63,34 @@ class Driver extends AbstractDriver {
parent::__construct($dsn, $username, $password, $options); parent::__construct($dsn, $username, $password, $options);
} }
/**
* Generate the returning clause for the current database
*
* @param string $query
* @param string $select
* @return string
*/
public function returning(string $query, string $select): string
{
// @TODO add checks for MariaDB for future-proofing
// MariaDB 10.5.0+ supports the returning clause for insert
if (
stripos($query, 'insert') !== FALSE
&& version_compare($this->getVersion(), '10.5.0', '>=')
){
return parent::returning($query, $select);
}
// MariaDB 10.0.5+ supports the returning clause for delete
if (
stripos($query, 'delete') !== FALSE
&& version_compare($this->getVersion(), '10.0.5', '>=')
){
return parent::returning($query, $select);
}
// Just return the same SQL if the returning clause is not supported
return $query;
}
} }

View File

@ -78,7 +78,9 @@ SQL;
{ {
if ( ! isset($valueMap[$key[$type]])) if ( ! isset($valueMap[$key[$type]]))
{ {
// @codeCoverageIgnoreStart
continue; continue;
// @codeCoverageIgnoreEnd
} }
$key[$type] = $valueMap[$key[$type]]; $key[$type] = $valueMap[$key[$type]];

View File

@ -109,7 +109,7 @@ class Driver extends AbstractDriver {
{ {
// If greater than version 3.7.11, supports the same syntax as // If greater than version 3.7.11, supports the same syntax as
// MySQL and Postgres // MySQL and Postgres
if (version_compare($this->getAttribute(PDO::ATTR_SERVER_VERSION), '3.7.11', '>=')) if (version_compare($this->getVersion(), '3.7.11', '>='))
{ {
return parent::insertBatch($table, $data); return parent::insertBatch($table, $data);
} }
@ -145,4 +145,17 @@ class Driver extends AbstractDriver {
return [$sql, NULL]; return [$sql, NULL];
} }
/**
* Generate the returning clause for the current database
*
* @param string $query
* @param string $select
* @return string
*/
public function returning(string $query, string $select): string
{
// Return the same query, as the returning clause is not supported
return $query;
}
} }

26
src/QueryType.php Normal file
View File

@ -0,0 +1,26 @@
<?php declare(strict_types=1);
/**
* Query
*
* SQL Query Builder / Database Abstraction Layer
*
* PHP version 7.2
*
* @package Query
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2012 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link https://git.timshomepage.net/aviat/Query
* @version 3.0.0
*/
namespace Query;
/**
* 'Enum' of query types
*/
class QueryType {
public const SELECT = 'select';
public const INSERT = 'insert';
public const UPDATE = 'update';
public const DELETE = 'delete';
}

View File

@ -131,5 +131,12 @@ abstract class BaseDriverTest extends TestCase {
$funcs = self::$db->getFunctions(); $funcs = self::$db->getFunctions();
$this->assertTrue(\is_array($funcs)); $this->assertTrue(\is_array($funcs));
} }
public function testGetVersion(): void
{
$version = self::$db->getVersion();
$this->assertTrue(is_string($version));
$this->assertTrue(strlen($version) > 0);
}
} }
// End of db_test.php // End of db_test.php

View File

@ -24,6 +24,7 @@ class ConnectionManagerTest extends TestCase {
public static function setUpBeforeClass(): void public static function setUpBeforeClass(): void
{ {
ConnectionManager::getInstance();
self::$instance = ConnectionManager::getInstance(); self::$instance = ConnectionManager::getInstance();
} }

View File

@ -23,7 +23,6 @@ use TypeError;
/** /**
* MySQLTest class. * MySQLTest class.
* *
* @covers \Query\Drivers\Mysql\Driver
* @requires extension pdo_mysql * @requires extension pdo_mysql
*/ */
class MySQLDriverTest extends BaseDriverTest { class MySQLDriverTest extends BaseDriverTest {

View File

@ -25,7 +25,6 @@ use TypeError;
* *
* @extends DBTest * @extends DBTest
* @requires extension pdo_pgsql * @requires extension pdo_pgsql
* @covers \Query\Drivers\Pgsql\Driver
*/ */
class PgSQLDriverTest extends BaseDriverTest { class PgSQLDriverTest extends BaseDriverTest {

View File

@ -25,7 +25,6 @@ use Query\Tests\BaseDriverTest;
* *
* @extends DBTest * @extends DBTest
* @requires extension pdo_sqlite * @requires extension pdo_sqlite
* @covers \Query\Drivers\Sqlite\Driver
*/ */
class SQLiteDriverTest extends BaseDriverTest { class SQLiteDriverTest extends BaseDriverTest {
@ -253,6 +252,9 @@ SQL;
public function testGetDBs(): void public function testGetDBs(): void
{ {
$driverSQL = self::$db->getSql()->dbList();
$this->assertEqual('', $driverSQL);
$this->assertNull(self::$db->getDbs()); $this->assertNull(self::$db->getDbs());
} }

View File

@ -35,7 +35,11 @@ namespace Query\Tests {
{ {
$class = \get_class($this); $class = \get_class($this);
echo 'Ran test suite: ' . $class . '<br />'; if (PHP_SAPI !== 'cli')
{
echo 'Running test suite: ' . $class . '<br />';
flush();
}
if (method_exists($class, 'setupBeforeClass')) { if (method_exists($class, 'setupBeforeClass')) {
$class::setupBeforeClass(); $class::setupBeforeClass();