mirror of
https://github.com/dg/dibi.git
synced 2025-08-11 16:44:30 +02:00
drivers divided into Driver and ResultDriver (BC break)
This commit is contained in:
@@ -24,7 +24,7 @@ use Dibi\Helpers;
|
||||
* - buffers (int) => buffers is the number of database buffers to allocate for the server-side cache. If 0 or omitted, server chooses its own default.
|
||||
* - resource (resource) => existing connection resource
|
||||
*/
|
||||
class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
class FirebirdDriver implements Dibi\Driver, Dibi\Reflector
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
@@ -33,12 +33,6 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var resource|null */
|
||||
private $transaction;
|
||||
|
||||
@@ -225,11 +219,9 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
* Result set driver factory.
|
||||
* @param resource $resource
|
||||
*/
|
||||
public function createResultDriver($resource): Dibi\ResultDriver
|
||||
public function createResultDriver($resource): FirebirdResult
|
||||
{
|
||||
$res = clone $this;
|
||||
$res->resultSet = $resource;
|
||||
return $res;
|
||||
return new FirebirdResult($resource);
|
||||
}
|
||||
|
||||
|
||||
@@ -296,15 +288,6 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*/
|
||||
@@ -317,103 +300,7 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
}
|
||||
|
||||
|
||||
/********************* result set ********************/
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Firebird/Interbase do not support returning number of rows in result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
$result = $assoc ? @ibase_fetch_assoc($this->resultSet, IBASE_TEXT) : @ibase_fetch_row($this->resultSet, IBASE_TEXT); // intentionally @
|
||||
|
||||
if (ibase_errcode()) {
|
||||
if (ibase_errcode() == self::ERROR_EXCEPTION_THROWN) {
|
||||
preg_match('/exception (\d+) (\w+) (.*)/is', ibase_errmsg(), $match);
|
||||
throw new Dibi\ProcedureException($match[3], $match[1], $match[2]);
|
||||
|
||||
} else {
|
||||
throw new Dibi\DriverException(ibase_errmsg(), ibase_errcode());
|
||||
}
|
||||
}
|
||||
|
||||
return Helpers::false2Null($result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
* @throws Dibi\Exception
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Firebird/Interbase do not support seek in result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
ibase_free_result($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = ibase_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$row = (array) ibase_field_info($this->resultSet, $i);
|
||||
$columns[] = [
|
||||
'name' => $row['name'],
|
||||
'fullname' => $row['name'],
|
||||
'table' => $row['relation'],
|
||||
'nativetype' => $row['type'],
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/********************* Dibi\Reflector ********************/
|
||||
/********************* Dibi\Reflector ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
|
139
src/Dibi/Drivers/FirebirdResult.php
Normal file
139
src/Dibi/Drivers/FirebirdResult.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dibi\Drivers;
|
||||
|
||||
use Dibi;
|
||||
use Dibi\Helpers;
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for Firebird/InterBase result set.
|
||||
*/
|
||||
class FirebirdResult implements Dibi\ResultDriver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $resultSet
|
||||
*/
|
||||
public function __construct($resultSet)
|
||||
{
|
||||
$this->resultSet = $resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Firebird/Interbase do not support returning number of rows in result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
$result = $assoc ? @ibase_fetch_assoc($this->resultSet, IBASE_TEXT) : @ibase_fetch_row($this->resultSet, IBASE_TEXT); // intentionally @
|
||||
|
||||
if (ibase_errcode()) {
|
||||
if (ibase_errcode() == FirebirdDriver::ERROR_EXCEPTION_THROWN) {
|
||||
preg_match('/exception (\d+) (\w+) (.*)/is', ibase_errmsg(), $match);
|
||||
throw new Dibi\ProcedureException($match[3], $match[1], $match[2]);
|
||||
|
||||
} else {
|
||||
throw new Dibi\DriverException(ibase_errmsg(), ibase_errcode());
|
||||
}
|
||||
}
|
||||
|
||||
return Helpers::false2Null($result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
* @throws Dibi\Exception
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Firebird/Interbase do not support seek in result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
ibase_free_result($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = ibase_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$row = (array) ibase_field_info($this->resultSet, $i);
|
||||
$columns[] = [
|
||||
'name' => $row['name'],
|
||||
'fullname' => $row['name'],
|
||||
'table' => $row['relation'],
|
||||
'nativetype' => $row['type'],
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
@@ -30,7 +30,7 @@ use Dibi;
|
||||
* - sqlmode => see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
|
||||
* - resource (mysqli) => existing connection resource
|
||||
*/
|
||||
class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
class MySqliDriver implements Dibi\Driver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
@@ -43,12 +43,6 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/** @var \mysqli|null */
|
||||
private $connection;
|
||||
|
||||
/** @var \mysqli_result|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var bool Is buffered (seekable and countable)? */
|
||||
private $buffered;
|
||||
|
||||
@@ -260,11 +254,9 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/**
|
||||
* Result set driver factory.
|
||||
*/
|
||||
public function createResultDriver(\mysqli_result $resource): Dibi\ResultDriver
|
||||
public function createResultDriver(\mysqli_result $resource): MySqliResult
|
||||
{
|
||||
$res = clone $this;
|
||||
$res->resultSet = $resource;
|
||||
return $res;
|
||||
return new MySqliResult($resource, $this->buffered);
|
||||
}
|
||||
|
||||
|
||||
@@ -332,15 +324,6 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*/
|
||||
@@ -355,107 +338,4 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
. ($offset ? ' OFFSET ' . $offset : '');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************* result set ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
@$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new Dibi\NotSupportedException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
return mysqli_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return mysqli_fetch_array($this->resultSet, $assoc ? MYSQLI_ASSOC : MYSQLI_NUM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
* @throws Dibi\Exception
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new Dibi\NotSupportedException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
return mysqli_data_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
mysqli_free_result($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
static $types;
|
||||
if ($types === null) {
|
||||
$consts = get_defined_constants(true);
|
||||
$types = [];
|
||||
foreach ($consts['mysqli'] ?? [] as $key => $value) {
|
||||
if (strncmp($key, 'MYSQLI_TYPE_', 12) === 0) {
|
||||
$types[$value] = substr($key, 12);
|
||||
}
|
||||
}
|
||||
$types[MYSQLI_TYPE_TINY] = $types[MYSQLI_TYPE_SHORT] = $types[MYSQLI_TYPE_LONG] = 'INT';
|
||||
}
|
||||
|
||||
$count = mysqli_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$row = (array) mysqli_fetch_field_direct($this->resultSet, $i);
|
||||
$columns[] = [
|
||||
'name' => $row['name'],
|
||||
'table' => $row['orgtable'],
|
||||
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
|
||||
'nativetype' => $types[$row['type']] ?? $row['type'],
|
||||
'type' => $row['type'] === MYSQLI_TYPE_TIME ? Dibi\Type::TIME_INTERVAL : null,
|
||||
'vendor' => $row,
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*/
|
||||
public function getResultResource(): ?\mysqli_result
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return $this->resultSet;
|
||||
}
|
||||
}
|
||||
|
146
src/Dibi/Drivers/MySqliResult.php
Normal file
146
src/Dibi/Drivers/MySqliResult.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dibi\Drivers;
|
||||
|
||||
use Dibi;
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for MySQL result set via improved extension.
|
||||
*/
|
||||
class MySqliResult implements Dibi\ResultDriver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var \mysqli_result|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var bool Is buffered (seekable and countable)? */
|
||||
private $buffered;
|
||||
|
||||
|
||||
public function __construct(\mysqli_result $resultSet, bool $buffered)
|
||||
{
|
||||
$this->resultSet = $resultSet;
|
||||
$this->buffered = $buffered;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
@$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new Dibi\NotSupportedException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
return mysqli_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return mysqli_fetch_array($this->resultSet, $assoc ? MYSQLI_ASSOC : MYSQLI_NUM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
* @throws Dibi\Exception
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
if (!$this->buffered) {
|
||||
throw new Dibi\NotSupportedException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
return mysqli_data_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
mysqli_free_result($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
static $types;
|
||||
if ($types === null) {
|
||||
$consts = get_defined_constants(true);
|
||||
$types = [];
|
||||
foreach ($consts['mysqli'] ?? [] as $key => $value) {
|
||||
if (strncmp($key, 'MYSQLI_TYPE_', 12) === 0) {
|
||||
$types[$value] = substr($key, 12);
|
||||
}
|
||||
}
|
||||
$types[MYSQLI_TYPE_TINY] = $types[MYSQLI_TYPE_SHORT] = $types[MYSQLI_TYPE_LONG] = 'INT';
|
||||
}
|
||||
|
||||
$count = mysqli_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$row = (array) mysqli_fetch_field_direct($this->resultSet, $i);
|
||||
$columns[] = [
|
||||
'name' => $row['name'],
|
||||
'table' => $row['orgtable'],
|
||||
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
|
||||
'nativetype' => $types[$row['type']] ?? $row['type'],
|
||||
'type' => $row['type'] === MYSQLI_TYPE_TIME ? Dibi\Type::TIME_INTERVAL : null,
|
||||
'vendor' => $row,
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*/
|
||||
public function getResultResource(): ?\mysqli_result
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
@@ -22,25 +22,16 @@ use Dibi;
|
||||
* - persistent (bool) => try to find a persistent link?
|
||||
* - resource (resource) => existing connection resource
|
||||
*/
|
||||
class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
class OdbcDriver implements Dibi\Driver, Dibi\Reflector
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var int|null Affected rows */
|
||||
private $affectedRows;
|
||||
|
||||
/** @var int Cursor */
|
||||
private $row = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @throws Dibi\NotSupportedException
|
||||
@@ -199,11 +190,9 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
* Result set driver factory.
|
||||
* @param resource $resource
|
||||
*/
|
||||
public function createResultDriver($resource): Dibi\ResultDriver
|
||||
public function createResultDriver($resource): OdbcResult
|
||||
{
|
||||
$res = clone $this;
|
||||
$res->resultSet = $resource;
|
||||
return $res;
|
||||
return new OdbcResult($resource);
|
||||
}
|
||||
|
||||
|
||||
@@ -271,15 +260,6 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*/
|
||||
@@ -297,103 +277,6 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
}
|
||||
|
||||
|
||||
/********************* result set ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
// will return -1 with many drivers :-(
|
||||
return odbc_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
if ($assoc) {
|
||||
return Dibi\Helpers::false2Null(odbc_fetch_array($this->resultSet, ++$this->row));
|
||||
} else {
|
||||
$set = $this->resultSet;
|
||||
if (!odbc_fetch_row($set, ++$this->row)) {
|
||||
return null;
|
||||
}
|
||||
$count = odbc_num_fields($set);
|
||||
$cols = [];
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$cols[] = odbc_result($set, $i);
|
||||
}
|
||||
return $cols;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
$this->row = $row;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
odbc_free_result($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = odbc_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$columns[] = [
|
||||
'name' => odbc_field_name($this->resultSet, $i),
|
||||
'table' => null,
|
||||
'fullname' => odbc_field_name($this->resultSet, $i),
|
||||
'nativetype' => odbc_field_type($this->resultSet, $i),
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
|
||||
|
||||
/********************* Dibi\Reflector ****************d*g**/
|
||||
|
||||
|
||||
|
142
src/Dibi/Drivers/OdbcResult.php
Normal file
142
src/Dibi/Drivers/OdbcResult.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dibi\Drivers;
|
||||
|
||||
use Dibi;
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver interacting with result set via ODBC connections.
|
||||
*/
|
||||
class OdbcResult implements Dibi\ResultDriver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var int Cursor */
|
||||
private $row = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $resultSet
|
||||
*/
|
||||
public function __construct($resultSet)
|
||||
{
|
||||
$this->resultSet = $resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
// will return -1 with many drivers :-(
|
||||
return odbc_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
if ($assoc) {
|
||||
return Dibi\Helpers::false2Null(odbc_fetch_array($this->resultSet, ++$this->row));
|
||||
} else {
|
||||
$set = $this->resultSet;
|
||||
if (!odbc_fetch_row($set, ++$this->row)) {
|
||||
return null;
|
||||
}
|
||||
$count = odbc_num_fields($set);
|
||||
$cols = [];
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$cols[] = odbc_result($set, $i);
|
||||
}
|
||||
return $cols;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
$this->row = $row;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
odbc_free_result($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = odbc_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$columns[] = [
|
||||
'name' => odbc_field_name($this->resultSet, $i),
|
||||
'table' => null,
|
||||
'fullname' => odbc_field_name($this->resultSet, $i),
|
||||
'nativetype' => odbc_field_type($this->resultSet, $i),
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
@@ -25,19 +25,13 @@ use Dibi;
|
||||
* - resource (resource) => existing connection resource
|
||||
* - persistent => Creates persistent connections with oci_pconnect instead of oci_new_connect
|
||||
*/
|
||||
class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
class OracleDriver implements Dibi\Driver, Dibi\Reflector
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var bool */
|
||||
private $autocommit = true;
|
||||
|
||||
@@ -222,11 +216,9 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
* Result set driver factory.
|
||||
* @param resource $resource
|
||||
*/
|
||||
public function createResultDriver($resource): Dibi\ResultDriver
|
||||
public function createResultDriver($resource): OracleResult
|
||||
{
|
||||
$res = clone $this;
|
||||
$res->resultSet = $resource;
|
||||
return $res;
|
||||
return new OracleResult($resource);
|
||||
}
|
||||
|
||||
|
||||
@@ -300,15 +292,6 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*/
|
||||
@@ -329,89 +312,6 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
}
|
||||
|
||||
|
||||
/********************* result set ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return Dibi\Helpers::false2Null(oci_fetch_array($this->resultSet, ($assoc ? OCI_ASSOC : OCI_NUM) | OCI_RETURN_NULLS));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotImplementedException;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
oci_free_statement($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = oci_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$type = oci_field_type($this->resultSet, $i);
|
||||
$columns[] = [
|
||||
'name' => oci_field_name($this->resultSet, $i),
|
||||
'table' => null,
|
||||
'fullname' => oci_field_name($this->resultSet, $i),
|
||||
'nativetype' => $type === 'NUMBER' && oci_field_scale($this->resultSet, $i) === 0 ? 'INTEGER' : $type,
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
|
||||
|
||||
/********************* Dibi\Reflector ****************d*g**/
|
||||
|
||||
|
||||
|
125
src/Dibi/Drivers/OracleResult.php
Normal file
125
src/Dibi/Drivers/OracleResult.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dibi\Drivers;
|
||||
|
||||
use Dibi;
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for Oracle result set.
|
||||
*/
|
||||
class OracleResult implements Dibi\ResultDriver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $resultSet
|
||||
*/
|
||||
public function __construct($resultSet)
|
||||
{
|
||||
$this->resultSet = $resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return Dibi\Helpers::false2Null(oci_fetch_array($this->resultSet, ($assoc ? OCI_ASSOC : OCI_NUM) | OCI_RETURN_NULLS));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotImplementedException;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
oci_free_statement($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = oci_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$type = oci_field_type($this->resultSet, $i);
|
||||
$columns[] = [
|
||||
'name' => oci_field_name($this->resultSet, $i),
|
||||
'table' => null,
|
||||
'fullname' => oci_field_name($this->resultSet, $i),
|
||||
'nativetype' => $type === 'NUMBER' && oci_field_scale($this->resultSet, $i) === 0 ? 'INTEGER' : $type,
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
@@ -25,16 +25,13 @@ use PDO;
|
||||
* - resource (PDO) => existing connection
|
||||
* - version
|
||||
*/
|
||||
class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
class PdoDriver implements Dibi\Driver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var PDO|null Connection resource */
|
||||
private $connection;
|
||||
|
||||
/** @var \PDOStatement|null Resultset resource */
|
||||
private $resultSet;
|
||||
|
||||
/** @var int|null Affected rows */
|
||||
private $affectedRows;
|
||||
|
||||
@@ -216,11 +213,9 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/**
|
||||
* Result set driver factory.
|
||||
*/
|
||||
public function createResultDriver(\PDOStatement $resource): Dibi\ResultDriver
|
||||
public function createResultDriver(\PDOStatement $resource): PdoResult
|
||||
{
|
||||
$res = clone $this;
|
||||
$res->resultSet = $resource;
|
||||
return $res;
|
||||
return new PdoResult($resource, $this->driverName);
|
||||
}
|
||||
|
||||
|
||||
@@ -358,15 +353,6 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*/
|
||||
@@ -441,84 +427,4 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
throw new Dibi\NotSupportedException('PDO or driver does not support applying limit or offset.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************* result set ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
return $this->resultSet->rowCount();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return Helpers::false2Null($this->resultSet->fetch($assoc ? PDO::FETCH_ASSOC : PDO::FETCH_NUM));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
* @throws Dibi\Exception
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = $this->resultSet->columnCount();
|
||||
$columns = [];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$row = @$this->resultSet->getColumnMeta($i); // intentionally @
|
||||
if ($row === false) {
|
||||
throw new Dibi\NotSupportedException('Driver does not support meta data.');
|
||||
}
|
||||
$row = $row + [
|
||||
'table' => null,
|
||||
'native_type' => 'VAR_STRING',
|
||||
];
|
||||
|
||||
$columns[] = [
|
||||
'name' => $row['name'],
|
||||
'table' => $row['table'],
|
||||
'nativetype' => $row['native_type'],
|
||||
'type' => $row['native_type'] === 'TIME' && $this->driverName === 'mysql' ? Dibi\Type::TIME_INTERVAL : null,
|
||||
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
|
||||
'vendor' => $row,
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*/
|
||||
public function getResultResource(): ?\PDOStatement
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
}
|
||||
|
122
src/Dibi/Drivers/PdoResult.php
Normal file
122
src/Dibi/Drivers/PdoResult.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dibi\Drivers;
|
||||
|
||||
use Dibi;
|
||||
use Dibi\Helpers;
|
||||
use PDO;
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for PDO result set.
|
||||
*/
|
||||
class PdoResult implements Dibi\ResultDriver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var \PDOStatement|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var string */
|
||||
private $driverName;
|
||||
|
||||
|
||||
public function __construct(\PDOStatement $resultSet, string $driverName)
|
||||
{
|
||||
$this->resultSet = $resultSet;
|
||||
$this->driverName = $driverName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
return $this->resultSet->rowCount();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return Helpers::false2Null($this->resultSet->fetch($assoc ? PDO::FETCH_ASSOC : PDO::FETCH_NUM));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
* @throws Dibi\Exception
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = $this->resultSet->columnCount();
|
||||
$columns = [];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$row = @$this->resultSet->getColumnMeta($i); // intentionally @
|
||||
if ($row === false) {
|
||||
throw new Dibi\NotSupportedException('Driver does not support meta data.');
|
||||
}
|
||||
$row = $row + [
|
||||
'table' => null,
|
||||
'native_type' => 'VAR_STRING',
|
||||
];
|
||||
|
||||
$columns[] = [
|
||||
'name' => $row['name'],
|
||||
'table' => $row['table'],
|
||||
'nativetype' => $row['native_type'],
|
||||
'type' => $row['native_type'] === 'TIME' && $this->driverName === 'mysql' ? Dibi\Type::TIME_INTERVAL : null,
|
||||
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
|
||||
'vendor' => $row,
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*/
|
||||
public function getResultResource(): ?\PDOStatement
|
||||
{
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
@@ -24,19 +24,13 @@ use Dibi\Helpers;
|
||||
* - persistent (bool) => try to find a persistent link?
|
||||
* - resource (resource) => existing connection resource
|
||||
*/
|
||||
class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
class PostgreDriver implements Dibi\Driver, Dibi\Reflector
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var int|null Affected rows */
|
||||
private $affectedRows;
|
||||
|
||||
@@ -263,11 +257,9 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
* Result set driver factory.
|
||||
* @param resource $resource
|
||||
*/
|
||||
public function createResultDriver($resource): Dibi\ResultDriver
|
||||
public function createResultDriver($resource): PostgreResult
|
||||
{
|
||||
$res = clone $this;
|
||||
$res->resultSet = $resource;
|
||||
return $res;
|
||||
return new PostgreResult($resource);
|
||||
}
|
||||
|
||||
|
||||
@@ -344,15 +336,6 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return pg_unescape_bytea($value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*/
|
||||
@@ -370,89 +353,6 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
}
|
||||
|
||||
|
||||
/********************* result set ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
return pg_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return Helpers::false2Null(pg_fetch_array($this->resultSet, null, $assoc ? PGSQL_ASSOC : PGSQL_NUM));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
return pg_result_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
pg_free_result($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = pg_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$row = [
|
||||
'name' => pg_field_name($this->resultSet, $i),
|
||||
'table' => pg_field_table($this->resultSet, $i),
|
||||
'nativetype' => pg_field_type($this->resultSet, $i),
|
||||
];
|
||||
$row['fullname'] = $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'];
|
||||
$columns[] = $row;
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
|
||||
|
||||
/********************* Dibi\Reflector ****************d*g**/
|
||||
|
||||
|
||||
@@ -490,7 +390,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
}
|
||||
|
||||
$res = $this->query($query);
|
||||
$tables = pg_fetch_all($res->resultSet);
|
||||
$tables = pg_fetch_all($res->getResultResource());
|
||||
return $tables ? $tables : [];
|
||||
}
|
||||
|
||||
@@ -507,7 +407,7 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector
|
||||
LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid AND pg_index.indisprimary
|
||||
WHERE pg_class.oid = $_table::regclass
|
||||
");
|
||||
$primary = (int) pg_fetch_object($res->resultSet)->indkey;
|
||||
$primary = (int) pg_fetch_object($res->getResultResource())->indkey;
|
||||
|
||||
$res = $this->query("
|
||||
SELECT *
|
||||
|
126
src/Dibi/Drivers/PostgreResult.php
Normal file
126
src/Dibi/Drivers/PostgreResult.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dibi\Drivers;
|
||||
|
||||
use Dibi;
|
||||
use Dibi\Helpers;
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for PostgreSQL result set.
|
||||
*/
|
||||
class PostgreResult implements Dibi\ResultDriver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $resultSet
|
||||
*/
|
||||
public function __construct($resultSet)
|
||||
{
|
||||
$this->resultSet = $resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
return pg_num_rows($this->resultSet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return Helpers::false2Null(pg_fetch_array($this->resultSet, null, $assoc ? PGSQL_ASSOC : PGSQL_NUM));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
return pg_result_seek($this->resultSet, $row);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
pg_free_result($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = pg_num_fields($this->resultSet);
|
||||
$columns = [];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$row = [
|
||||
'name' => pg_field_name($this->resultSet, $i),
|
||||
'table' => pg_field_table($this->resultSet, $i),
|
||||
'nativetype' => pg_field_type($this->resultSet, $i),
|
||||
];
|
||||
$row['fullname'] = $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'];
|
||||
$columns[] = $row;
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return pg_unescape_bytea($value);
|
||||
}
|
||||
}
|
@@ -23,19 +23,13 @@ use SQLite3;
|
||||
* - formatDateTime => how to format datetime in SQL (@see date)
|
||||
* - resource (SQLite3) => existing connection resource
|
||||
*/
|
||||
class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
class Sqlite3Driver implements Dibi\Driver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var SQLite3|null */
|
||||
private $connection;
|
||||
|
||||
/** @var \SQLite3Result|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var string Date format */
|
||||
private $fmtDate;
|
||||
|
||||
@@ -208,11 +202,9 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
/**
|
||||
* Result set driver factory.
|
||||
*/
|
||||
public function createResultDriver(\SQLite3Result $resource): Dibi\ResultDriver
|
||||
public function createResultDriver(\SQLite3Result $resource): Sqlite3Result
|
||||
{
|
||||
$res = clone $this;
|
||||
$res->resultSet = $resource;
|
||||
return $res;
|
||||
return new Sqlite3Result($resource);
|
||||
}
|
||||
|
||||
|
||||
@@ -280,15 +272,6 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*/
|
||||
@@ -304,90 +287,6 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver
|
||||
}
|
||||
|
||||
|
||||
/********************* result set ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
@$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
* @throws Dibi\NotSupportedException
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return Helpers::false2Null($this->resultSet->fetchArray($assoc ? SQLITE3_ASSOC : SQLITE3_NUM));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
* @throws Dibi\NotSupportedException
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
$this->resultSet->finalize();
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = $this->resultSet->numColumns();
|
||||
$columns = [];
|
||||
static $types = [SQLITE3_INTEGER => 'int', SQLITE3_FLOAT => 'float', SQLITE3_TEXT => 'text', SQLITE3_BLOB => 'blob', SQLITE3_NULL => 'null'];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$columns[] = [
|
||||
'name' => $this->resultSet->columnName($i),
|
||||
'table' => null,
|
||||
'fullname' => $this->resultSet->columnName($i),
|
||||
'nativetype' => $types[$this->resultSet->columnType($i)],
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*/
|
||||
public function getResultResource(): ?\SQLite3Result
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
/********************* user defined functions ****************d*g**/
|
||||
|
||||
|
||||
|
124
src/Dibi/Drivers/Sqlite3Result.php
Normal file
124
src/Dibi/Drivers/Sqlite3Result.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dibi\Drivers;
|
||||
|
||||
use Dibi;
|
||||
use Dibi\Helpers;
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for SQLite3 result set.
|
||||
*/
|
||||
class Sqlite3Result implements Dibi\ResultDriver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var \SQLite3Result|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
|
||||
public function __construct(\SQLite3Result $resultSet)
|
||||
{
|
||||
$this->resultSet = $resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
@$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
* @throws Dibi\NotSupportedException
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return Helpers::false2Null($this->resultSet->fetchArray($assoc ? SQLITE3_ASSOC : SQLITE3_NUM));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
* @throws Dibi\NotSupportedException
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
$this->resultSet->finalize();
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$count = $this->resultSet->numColumns();
|
||||
$columns = [];
|
||||
static $types = [SQLITE3_INTEGER => 'int', SQLITE3_FLOAT => 'float', SQLITE3_TEXT => 'text', SQLITE3_BLOB => 'blob', SQLITE3_NULL => 'null'];
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$columns[] = [
|
||||
'name' => $this->resultSet->columnName($i),
|
||||
'table' => null,
|
||||
'fullname' => $this->resultSet->columnName($i),
|
||||
'nativetype' => $types[$this->resultSet->columnType($i)],
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
*/
|
||||
public function getResultResource(): ?\SQLite3Result
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return $this->resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
@@ -25,19 +25,13 @@ use Dibi\Helpers;
|
||||
* - charset => character encoding to set (default is UTF-8)
|
||||
* - resource (resource) => existing connection resource
|
||||
*/
|
||||
class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
class SqlsrvDriver implements Dibi\Driver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var resource|null */
|
||||
private $connection;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
/** @var int|null Affected rows */
|
||||
private $affectedRows;
|
||||
|
||||
@@ -196,11 +190,9 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
* Result set driver factory.
|
||||
* @param resource $resource
|
||||
*/
|
||||
public function createResultDriver($resource): Dibi\ResultDriver
|
||||
public function createResultDriver($resource): SqlsrvResult
|
||||
{
|
||||
$res = clone $this;
|
||||
$res->resultSet = $resource;
|
||||
return $res;
|
||||
return new SqlsrvResult($resource);
|
||||
}
|
||||
|
||||
|
||||
@@ -269,15 +261,6 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects LIMIT/OFFSET to the SQL query.
|
||||
*/
|
||||
@@ -302,84 +285,4 @@ class SqlsrvDriver implements Dibi\Driver, Dibi\ResultDriver
|
||||
$sql = sprintf('%s OFFSET %d ROWS', rtrim($sql), $offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************* result set ****************d*g**/
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return sqlsrv_fetch_array($this->resultSet, $assoc ? SQLSRV_FETCH_ASSOC : SQLSRV_FETCH_NUMERIC);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
sqlsrv_free_stmt($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$columns = [];
|
||||
foreach ((array) sqlsrv_field_metadata($this->resultSet) as $fieldMetadata) {
|
||||
$columns[] = [
|
||||
'name' => $fieldMetadata['Name'],
|
||||
'fullname' => $fieldMetadata['Name'],
|
||||
'nativetype' => $fieldMetadata['Type'],
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
}
|
||||
|
122
src/Dibi/Drivers/SqlsrvResult.php
Normal file
122
src/Dibi/Drivers/SqlsrvResult.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the "dibi" - smart database abstraction layer.
|
||||
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dibi\Drivers;
|
||||
|
||||
use Dibi;
|
||||
|
||||
|
||||
/**
|
||||
* The dibi driver for Microsoft SQL Server and SQL Azure result set.
|
||||
*/
|
||||
class SqlsrvResult implements Dibi\ResultDriver
|
||||
{
|
||||
use Dibi\Strict;
|
||||
|
||||
/** @var resource|null */
|
||||
private $resultSet;
|
||||
|
||||
/** @var bool */
|
||||
private $autoFree = true;
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $resultSet
|
||||
*/
|
||||
public function __construct($resultSet)
|
||||
{
|
||||
$this->resultSet = $resultSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->autoFree && $this->getResultResource()) {
|
||||
$this->free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of rows in a result set.
|
||||
*/
|
||||
public function getRowCount(): int
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Row count is not available for unbuffered queries.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position and moves the internal cursor to the next position.
|
||||
* @param bool $assoc true for associative array, false for numeric
|
||||
*/
|
||||
public function fetch(bool $assoc): ?array
|
||||
{
|
||||
return sqlsrv_fetch_array($this->resultSet, $assoc ? SQLSRV_FETCH_ASSOC : SQLSRV_FETCH_NUMERIC);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves cursor position without fetching row.
|
||||
*/
|
||||
public function seek(int $row): bool
|
||||
{
|
||||
throw new Dibi\NotSupportedException('Cannot seek an unbuffered result set.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Frees the resources allocated for this result set.
|
||||
*/
|
||||
public function free(): void
|
||||
{
|
||||
sqlsrv_free_stmt($this->resultSet);
|
||||
$this->resultSet = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set.
|
||||
*/
|
||||
public function getResultColumns(): array
|
||||
{
|
||||
$columns = [];
|
||||
foreach ((array) sqlsrv_field_metadata($this->resultSet) as $fieldMetadata) {
|
||||
$columns[] = [
|
||||
'name' => $fieldMetadata['Name'],
|
||||
'fullname' => $fieldMetadata['Name'],
|
||||
'nativetype' => $fieldMetadata['Type'],
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the result set resource.
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getResultResource()
|
||||
{
|
||||
$this->autoFree = false;
|
||||
return is_resource($this->resultSet) ? $this->resultSet : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes data from result set.
|
||||
*/
|
||||
public function unescapeBinary(string $value): string
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
@@ -20,7 +20,15 @@ class MockDriver extends Dibi\Drivers\SqlsrvDriver
|
||||
|
||||
public function query(string $sql): ?Dibi\ResultDriver
|
||||
{
|
||||
return $this;
|
||||
return new MockResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MockResult extends Dibi\Drivers\SqlsrvResult
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +44,7 @@ class MockDriver extends Dibi\Drivers\SqlsrvDriver
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$config['driver'] = new MockDriver;
|
||||
$conn = new Dibi\Connection($config);
|
||||
|
||||
|
Reference in New Issue
Block a user