mirror of
https://github.com/dg/dibi.git
synced 2025-08-05 21:58:10 +02:00
* new: qualifiy each column name with the table name using DibiResult::setWithTables
* removed DibiResult::setType(TRUE) with autodetection * removed DibiResult::getFields() & getMetaData() in favour of new method getColumnsMeta() * MySQLi and MySQL transaction implementation are the same * better escaping in DibiPostgreDriver (new pg_escape_string and addslashes)
This commit is contained in:
2
TODO.txt
2
TODO.txt
@@ -2,6 +2,6 @@
|
||||
- sjednotit DibiVariable, modifier a type u DibiDriverInterface::format()
|
||||
- odstranit podporu pro modifik<69>tory v kli<6C><69>ch pole?
|
||||
- odstranit podporu pro conditional query?
|
||||
- odstranit podporu pro meta types?
|
||||
- odstranit podporu pro meta types - odstraneno
|
||||
- event, log, profiler
|
||||
|
||||
|
@@ -244,11 +244,12 @@ class DibiMsSqlDriver extends NObject implements DibiDriverInterface
|
||||
* Fetches the row at current position and moves the internal cursor to the next position
|
||||
* internal usage only
|
||||
*
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch()
|
||||
public function fetch($type)
|
||||
{
|
||||
return mssql_fetch_assoc($this->resultset);
|
||||
return mssql_fetch_array($this->resultset, $type ? MSSQL_ASSOC : MSSQL_NUM);
|
||||
}
|
||||
|
||||
|
||||
@@ -280,47 +281,20 @@ class DibiMsSqlDriver extends NObject implements DibiDriverInterface
|
||||
|
||||
|
||||
|
||||
/** this is experimental */
|
||||
public function buildMeta()
|
||||
/**
|
||||
* Returns metadata for all columns in a result set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
static $types = array(
|
||||
'CHAR' => dibi::FIELD_TEXT,
|
||||
'COUNTER' => dibi::FIELD_COUNTER,
|
||||
'VARCHAR' => dibi::FIELD_TEXT,
|
||||
'LONGCHAR' => dibi::FIELD_TEXT,
|
||||
'INTEGER' => dibi::FIELD_INTEGER,
|
||||
'DATETIME' => dibi::FIELD_DATETIME,
|
||||
'CURRENCY' => dibi::FIELD_FLOAT,
|
||||
'BIT' => dibi::FIELD_BOOL,
|
||||
'LONGBINARY'=> dibi::FIELD_BINARY,
|
||||
'SMALLINT' => dibi::FIELD_INTEGER,
|
||||
'BYTE' => dibi::FIELD_INTEGER,
|
||||
'BIGINT' => dibi::FIELD_INTEGER,
|
||||
'INT' => dibi::FIELD_INTEGER,
|
||||
'TINYINT' => dibi::FIELD_INTEGER,
|
||||
'REAL' => dibi::FIELD_FLOAT,
|
||||
'DOUBLE' => dibi::FIELD_FLOAT,
|
||||
'DECIMAL' => dibi::FIELD_FLOAT,
|
||||
'NUMERIC' => dibi::FIELD_FLOAT,
|
||||
'MONEY' => dibi::FIELD_FLOAT,
|
||||
'SMALLMONEY'=> dibi::FIELD_FLOAT,
|
||||
'FLOAT' => dibi::FIELD_FLOAT,
|
||||
'YESNO' => dibi::FIELD_BOOL,
|
||||
// and many others?
|
||||
);
|
||||
|
||||
$count = mssql_num_fields($this->resultset);
|
||||
$meta = array();
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
|
||||
$tmp = mssql_fetch_field($this->resultset, $index);
|
||||
$type = strtoupper($tmp->type);
|
||||
$info['native'] = $tmp->type;
|
||||
$info['type'] = isset($types[$type]) ? $types[$type] : dibi::FIELD_UNKNOWN;
|
||||
$info['length'] = $tmp->max_length;
|
||||
$info['table'] = $tmp->column_source;
|
||||
|
||||
$meta[$tmp->name] = $info;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$info = (array) mssql_fetch_field($this->resultset, $i);
|
||||
$info['table'] = $info['column_source'];
|
||||
$meta[] = $info;
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
@@ -204,7 +204,7 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('BEGIN');
|
||||
$this->query('START TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
@@ -292,11 +292,12 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
|
||||
* Fetches the row at current position and moves the internal cursor to the next position
|
||||
* internal usage only
|
||||
*
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch()
|
||||
public function fetch($type)
|
||||
{
|
||||
return mysql_fetch_assoc($this->resultset);
|
||||
return mysql_fetch_array($this->resultset, $type ? MYSQL_ASSOC : MYSQL_NUM);
|
||||
}
|
||||
|
||||
|
||||
@@ -332,64 +333,19 @@ class DibiMySqlDriver extends NObject implements DibiDriverInterface
|
||||
|
||||
|
||||
|
||||
/** this is experimental */
|
||||
public function buildMeta()
|
||||
/**
|
||||
* Returns metadata for all columns in a result set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
static $types = array(
|
||||
'ENUM' => dibi::FIELD_TEXT, // eventually dibi::FIELD_INTEGER
|
||||
'SET' => dibi::FIELD_TEXT, // eventually dibi::FIELD_INTEGER
|
||||
'CHAR' => dibi::FIELD_TEXT,
|
||||
'VARCHAR' => dibi::FIELD_TEXT,
|
||||
'STRING' => dibi::FIELD_TEXT,
|
||||
'TINYTEXT' => dibi::FIELD_TEXT,
|
||||
'TEXT' => dibi::FIELD_TEXT,
|
||||
'MEDIUMTEXT'=> dibi::FIELD_TEXT,
|
||||
'LONGTEXT' => dibi::FIELD_TEXT,
|
||||
'BINARY' => dibi::FIELD_BINARY,
|
||||
'VARBINARY' => dibi::FIELD_BINARY,
|
||||
'TINYBLOB' => dibi::FIELD_BINARY,
|
||||
'BLOB' => dibi::FIELD_BINARY,
|
||||
'MEDIUMBLOB'=> dibi::FIELD_BINARY,
|
||||
'LONGBLOB' => dibi::FIELD_BINARY,
|
||||
'DATE' => dibi::FIELD_DATE,
|
||||
'DATETIME' => dibi::FIELD_DATETIME,
|
||||
'TIMESTAMP' => dibi::FIELD_DATETIME,
|
||||
'TIME' => dibi::FIELD_DATETIME,
|
||||
'BIT' => dibi::FIELD_BOOL,
|
||||
'YEAR' => dibi::FIELD_INTEGER,
|
||||
'TINYINT' => dibi::FIELD_INTEGER,
|
||||
'SMALLINT' => dibi::FIELD_INTEGER,
|
||||
'MEDIUMINT' => dibi::FIELD_INTEGER,
|
||||
'INT' => dibi::FIELD_INTEGER,
|
||||
'INTEGER' => dibi::FIELD_INTEGER,
|
||||
'BIGINT' => dibi::FIELD_INTEGER,
|
||||
'FLOAT' => dibi::FIELD_FLOAT,
|
||||
'DOUBLE' => dibi::FIELD_FLOAT,
|
||||
'REAL' => dibi::FIELD_FLOAT,
|
||||
'DECIMAL' => dibi::FIELD_FLOAT,
|
||||
'NUMERIC' => dibi::FIELD_FLOAT,
|
||||
);
|
||||
|
||||
$count = mysql_num_fields($this->resultset);
|
||||
$meta = array();
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
|
||||
$info['native'] = $native = strtoupper(mysql_field_type($this->resultset, $index));
|
||||
$info['flags'] = explode(' ', mysql_field_flags($this->resultset, $index));
|
||||
$info['length'] = mysql_field_len($this->resultset, $index);
|
||||
$info['table'] = mysql_field_table($this->resultset, $index);
|
||||
|
||||
if (in_array('auto_increment', $info['flags'])) { // or 'primary_key' ?
|
||||
$info['type'] = dibi::FIELD_COUNTER;
|
||||
} else {
|
||||
$info['type'] = isset($types[$native]) ? $types[$native] : dibi::FIELD_UNKNOWN;
|
||||
|
||||
// if ($info['type'] === dibi::FIELD_TEXT && $info['length'] > 255)
|
||||
// $info['type'] = dibi::FIELD_LONG_TEXT;
|
||||
}
|
||||
|
||||
$name = mysql_field_name($this->resultset, $index);
|
||||
$meta[$name] = $info;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$info = (array) mysql_fetch_field($this->resultset, $i);
|
||||
$meta[] = $info;
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
@@ -180,9 +180,7 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
if (!mysqli_autocommit($this->connection, FALSE)) {
|
||||
$this->throwException();
|
||||
}
|
||||
$this->query('START TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
@@ -194,10 +192,7 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if (!mysqli_commit($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
mysqli_autocommit($this->connection, TRUE);
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
|
||||
@@ -209,10 +204,7 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
if (!mysqli_rollback($this->connection)) {
|
||||
$this->throwException();
|
||||
}
|
||||
mysqli_autocommit($this->connection, TRUE);
|
||||
$this->query('ROLLBACK');
|
||||
}
|
||||
|
||||
|
||||
@@ -277,11 +269,12 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
|
||||
* Fetches the row at current position and moves the internal cursor to the next position
|
||||
* internal usage only
|
||||
*
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch()
|
||||
public function fetch($type)
|
||||
{
|
||||
return mysqli_fetch_assoc($this->resultset);
|
||||
return mysqli_fetch_array($this->resultset, $type ? MYSQLI_ASSOC : MYSQLI_NUM);
|
||||
}
|
||||
|
||||
|
||||
@@ -316,52 +309,19 @@ class DibiMySqliDriver extends NObject implements DibiDriverInterface
|
||||
|
||||
|
||||
|
||||
/** this is experimental */
|
||||
public function buildMeta()
|
||||
/**
|
||||
* Returns metadata for all columns in a result set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
static $types = array(
|
||||
MYSQLI_TYPE_FLOAT => dibi::FIELD_FLOAT,
|
||||
MYSQLI_TYPE_DOUBLE => dibi::FIELD_FLOAT,
|
||||
MYSQLI_TYPE_DECIMAL => dibi::FIELD_FLOAT,
|
||||
// MYSQLI_TYPE_NEWDECIMAL=> dibi::FIELD_FLOAT,
|
||||
// MYSQLI_TYPE_BIT => dibi::FIELD_INTEGER,
|
||||
MYSQLI_TYPE_TINY => dibi::FIELD_INTEGER,
|
||||
MYSQLI_TYPE_SHORT => dibi::FIELD_INTEGER,
|
||||
MYSQLI_TYPE_LONG => dibi::FIELD_INTEGER,
|
||||
MYSQLI_TYPE_LONGLONG => dibi::FIELD_INTEGER,
|
||||
MYSQLI_TYPE_INT24 => dibi::FIELD_INTEGER,
|
||||
MYSQLI_TYPE_YEAR => dibi::FIELD_INTEGER,
|
||||
MYSQLI_TYPE_GEOMETRY => dibi::FIELD_INTEGER,
|
||||
MYSQLI_TYPE_DATE => dibi::FIELD_DATE,
|
||||
MYSQLI_TYPE_NEWDATE => dibi::FIELD_DATE,
|
||||
MYSQLI_TYPE_TIMESTAMP => dibi::FIELD_DATETIME,
|
||||
MYSQLI_TYPE_TIME => dibi::FIELD_DATETIME,
|
||||
MYSQLI_TYPE_DATETIME => dibi::FIELD_DATETIME,
|
||||
MYSQLI_TYPE_ENUM => dibi::FIELD_TEXT, // eventually dibi::FIELD_INTEGER
|
||||
MYSQLI_TYPE_SET => dibi::FIELD_TEXT, // eventually dibi::FIELD_INTEGER
|
||||
MYSQLI_TYPE_STRING => dibi::FIELD_TEXT,
|
||||
MYSQLI_TYPE_VAR_STRING=> dibi::FIELD_TEXT,
|
||||
MYSQLI_TYPE_TINY_BLOB => dibi::FIELD_BINARY,
|
||||
MYSQLI_TYPE_MEDIUM_BLOB=> dibi::FIELD_BINARY,
|
||||
MYSQLI_TYPE_LONG_BLOB => dibi::FIELD_BINARY,
|
||||
MYSQLI_TYPE_BLOB => dibi::FIELD_BINARY,
|
||||
);
|
||||
|
||||
$count = mysqli_num_fields($this->resultset);
|
||||
$meta = array();
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
$info = (array) mysqli_fetch_field_direct($this->resultset, $index);
|
||||
$native = $info['native'] = $info['type'];
|
||||
|
||||
if ($info['flags'] & MYSQLI_AUTO_INCREMENT_FLAG) { // or 'primary_key' ?
|
||||
$info['type'] = dibi::FIELD_COUNTER;
|
||||
} else {
|
||||
$info['type'] = isset($types[$native]) ? $types[$native] : dibi::FIELD_UNKNOWN;
|
||||
// if ($info['type'] === dibi::FIELD_TEXT && $info['length'] > 255)
|
||||
// $info['type'] = dibi::FIELD_LONG_TEXT;
|
||||
}
|
||||
|
||||
$meta[$info['name']] = $info;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$info = (array) mysqli_fetch_field_direct($this->resultset, $i);
|
||||
$meta[] = $info;
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
@@ -257,11 +257,21 @@ class DibiOdbcDriver extends NObject implements DibiDriverInterface
|
||||
* Fetches the row at current position and moves the internal cursor to the next position
|
||||
* internal usage only
|
||||
*
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch()
|
||||
public function fetch($type)
|
||||
{
|
||||
if ($type) {
|
||||
return odbc_fetch_array($this->resultset, ++$this->row);
|
||||
} else {
|
||||
$set = $this->resultset;
|
||||
if (!odbc_fetch_row($set, ++$this->row)) return FALSE;
|
||||
$count = odbc_num_fields($set);
|
||||
$cols = array();
|
||||
for ($i = 1; $i <= $count; $i++) $cols[] = odbc_result($set, $i);
|
||||
return $cols;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,46 +304,24 @@ class DibiOdbcDriver extends NObject implements DibiDriverInterface
|
||||
|
||||
|
||||
|
||||
/** this is experimental */
|
||||
public function buildMeta()
|
||||
/**
|
||||
* Returns metadata for all columns in a result set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
static $types = array(
|
||||
'CHAR' => dibi::FIELD_TEXT,
|
||||
'COUNTER' => dibi::FIELD_COUNTER,
|
||||
'VARCHAR' => dibi::FIELD_TEXT,
|
||||
'LONGCHAR' => dibi::FIELD_TEXT,
|
||||
'INTEGER' => dibi::FIELD_INTEGER,
|
||||
'DATETIME' => dibi::FIELD_DATETIME,
|
||||
'CURRENCY' => dibi::FIELD_FLOAT,
|
||||
'BIT' => dibi::FIELD_BOOL,
|
||||
'LONGBINARY'=> dibi::FIELD_BINARY,
|
||||
'SMALLINT' => dibi::FIELD_INTEGER,
|
||||
'BYTE' => dibi::FIELD_INTEGER,
|
||||
'BIGINT' => dibi::FIELD_INTEGER,
|
||||
'INT' => dibi::FIELD_INTEGER,
|
||||
'TINYINT' => dibi::FIELD_INTEGER,
|
||||
'REAL' => dibi::FIELD_FLOAT,
|
||||
'DOUBLE' => dibi::FIELD_FLOAT,
|
||||
'DECIMAL' => dibi::FIELD_FLOAT,
|
||||
'NUMERIC' => dibi::FIELD_FLOAT,
|
||||
'MONEY' => dibi::FIELD_FLOAT,
|
||||
'SMALLMONEY'=> dibi::FIELD_FLOAT,
|
||||
'FLOAT' => dibi::FIELD_FLOAT,
|
||||
'YESNO' => dibi::FIELD_BOOL,
|
||||
// and many others?
|
||||
);
|
||||
|
||||
$count = odbc_num_fields($this->resultset);
|
||||
$meta = array();
|
||||
for ($index = 1; $index <= $count; $index++) {
|
||||
$native = strtoupper(odbc_field_type($this->resultset, $index));
|
||||
$name = odbc_field_name($this->resultset, $index);
|
||||
$meta[$name] = array(
|
||||
'type' => isset($types[$native]) ? $types[$native] : dibi::FIELD_UNKNOWN,
|
||||
'native' => $native,
|
||||
'length' => odbc_field_len($this->resultset, $index),
|
||||
'scale' => odbc_field_scale($this->resultset, $index),
|
||||
'precision' => odbc_field_precision($this->resultset, $index),
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => odbc_field_name($this->resultset, $i),
|
||||
'table' => NULL,
|
||||
'type' => odbc_field_type($this->resultset, $i),
|
||||
'length' => odbc_field_len($this->resultset, $i),
|
||||
'scale' => odbc_field_scale($this->resultset, $i),
|
||||
'precision' => odbc_field_precision($this->resultset, $i),
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
|
@@ -249,11 +249,12 @@ class DibiOracleDriver extends NObject implements DibiDriverInterface
|
||||
* Fetches the row at current position and moves the internal cursor to the next position
|
||||
* internal usage only
|
||||
*
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch()
|
||||
public function fetch($type)
|
||||
{
|
||||
return oci_fetch_assoc($this->resultset);
|
||||
return oci_fetch_array($this->resultset, ($type ? OCI_ASSOC : OCI_NUM) | OCI_RETURN_NULLS);
|
||||
}
|
||||
|
||||
|
||||
@@ -285,14 +286,25 @@ class DibiOracleDriver extends NObject implements DibiDriverInterface
|
||||
|
||||
|
||||
|
||||
/** this is experimental */
|
||||
public function buildMeta()
|
||||
/**
|
||||
* Returns metadata for all columns in a result set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = oci_num_fields($this->resultset);
|
||||
$meta = array();
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
$name = oci_field_name($this->resultset, $index + 1);
|
||||
$meta[$name] = array('type' => dibi::FIELD_UNKNOWN);
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => oci_field_name($this->resultset, $i),
|
||||
'table' => NULL,
|
||||
'type' => oci_field_type($this->resultset, $i),
|
||||
'size' => oci_field_size($this->resultset, $i),
|
||||
'scale' => oci_field_scale($this->resultset, $i),
|
||||
'precision' => oci_field_precision($this->resultset, $i),
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
@@ -261,11 +261,12 @@ class DibiPdoDriver extends NObject implements DibiDriverInterface
|
||||
* Fetches the row at current position and moves the internal cursor to the next position
|
||||
* internal usage only
|
||||
*
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch()
|
||||
public function fetch($type)
|
||||
{
|
||||
return $this->resultset->fetch(PDO::FETCH_ASSOC);
|
||||
return $this->resultset->fetch($type ? PDO::FETCH_ASSOC : PDO::FETCH_NUM);
|
||||
}
|
||||
|
||||
|
||||
@@ -296,17 +297,23 @@ class DibiPdoDriver extends NObject implements DibiDriverInterface
|
||||
|
||||
|
||||
|
||||
/** this is experimental */
|
||||
public function buildMeta()
|
||||
/**
|
||||
* Returns metadata for all columns in a result set
|
||||
*
|
||||
* @return array
|
||||
* @throws DibiException
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = $this->resultset->columnCount();
|
||||
$meta = array();
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
$meta = $this->resultset->getColumnMeta($index);
|
||||
// TODO:
|
||||
$meta['type'] = dibi::FIELD_UNKNOWN;
|
||||
$name = $meta['name'];
|
||||
$meta[$name] = $meta;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$info = @$this->resultset->getColumnsMeta($i);
|
||||
if ($info === FALSE) {
|
||||
throw new DibiDriverException('Driver does not support meta data');
|
||||
}
|
||||
$meta[] = $info;
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
@@ -50,6 +50,13 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
|
||||
private $resultset;
|
||||
|
||||
|
||||
/**
|
||||
* Escape method
|
||||
* @var int
|
||||
*/
|
||||
private $escMethod;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @throws DibiException
|
||||
@@ -59,6 +66,8 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
|
||||
if (!extension_loaded('pgsql')) {
|
||||
throw new DibiDriverException("PHP extension 'pgsql' is not loaded");
|
||||
}
|
||||
|
||||
$this->escMethod = version_compare(PHP_VERSION , '5.2.0', '>=') ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,9 +101,12 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
|
||||
}
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
DibiDriverException::catchError();
|
||||
@pg_set_client_encoding($this->connection, $config['charset']);
|
||||
// don't handle this error...
|
||||
DibiDriverException::restore();
|
||||
}
|
||||
|
||||
if (!empty($config['escapefix'])) $this->escMethod = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +186,7 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
|
||||
*/
|
||||
public function begin()
|
||||
{
|
||||
$this->query('BEGIN');
|
||||
$this->query('START TRANSACTION');
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +225,11 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
|
||||
*/
|
||||
public function format($value, $type)
|
||||
{
|
||||
if ($type === dibi::FIELD_TEXT) return "'" . pg_escape_string($value) . "'";
|
||||
if ($type === dibi::FIELD_TEXT) {
|
||||
if ($this->escMethod === -1) return "'" . addSlashes($value) . "'";
|
||||
if ($this->escMethod === 1 && $this->connection) return "'" . pg_escape_string($this->connection, $value) . "'";
|
||||
return "'" . pg_escape_string($value) . "'";
|
||||
}
|
||||
if ($type === dibi::IDENTIFIER) return '"' . str_replace('.', '"."', str_replace('"', '""', $value)) . '"';
|
||||
if ($type === dibi::FIELD_BOOL) return $value ? 'TRUE' : 'FALSE';
|
||||
if ($type === dibi::FIELD_DATE) return date("'Y-m-d'", $value);
|
||||
@@ -260,11 +276,12 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
|
||||
* Fetches the row at current position and moves the internal cursor to the next position
|
||||
* internal usage only
|
||||
*
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch()
|
||||
public function fetch($type)
|
||||
{
|
||||
return pg_fetch_array($this->resultset, NULL, PGSQL_ASSOC);
|
||||
return pg_fetch_array($this->resultset, NULL, $type ? PGSQL_ASSOC : PGSQL_NUM);
|
||||
}
|
||||
|
||||
|
||||
@@ -296,37 +313,25 @@ class DibiPostgreDriver extends NObject implements DibiDriverInterface
|
||||
|
||||
|
||||
|
||||
/** this is experimental */
|
||||
public function buildMeta()
|
||||
/**
|
||||
* Returns metadata for all columns in a result set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
static $types = array(
|
||||
'bool' => dibi::FIELD_BOOL,
|
||||
'int2' => dibi::FIELD_INTEGER,
|
||||
'int4' => dibi::FIELD_INTEGER,
|
||||
'int8' => dibi::FIELD_INTEGER,
|
||||
'numeric' => dibi::FIELD_FLOAT,
|
||||
'float4' => dibi::FIELD_FLOAT,
|
||||
'float8' => dibi::FIELD_FLOAT,
|
||||
'timestamp' => dibi::FIELD_DATETIME,
|
||||
'date' => dibi::FIELD_DATE,
|
||||
'time' => dibi::FIELD_DATETIME,
|
||||
'varchar' => dibi::FIELD_TEXT,
|
||||
'bpchar' => dibi::FIELD_TEXT,
|
||||
'inet' => dibi::FIELD_TEXT,
|
||||
'money' => dibi::FIELD_FLOAT,
|
||||
);
|
||||
|
||||
$hasTable = version_compare(PHP_VERSION , '5.2.0', '>=');
|
||||
$count = pg_num_fields($this->resultset);
|
||||
$meta = array();
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
|
||||
$info['native'] = $native = pg_field_type($this->resultset, $index);
|
||||
$info['length'] = pg_field_size($this->resultset, $index);
|
||||
$info['table'] = pg_field_table($this->resultset, $index);
|
||||
$info['type'] = isset($types[$native]) ? $types[$native] : dibi::FIELD_UNKNOWN;
|
||||
|
||||
$name = pg_field_name($this->resultset, $index);
|
||||
$meta[$name] = $info;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => pg_field_name($this->resultset, $i),
|
||||
'table' => $hasTable ? pg_field_table($this->resultset, $i) : NULL,
|
||||
'type' => pg_field_type($this->resultset, $i),
|
||||
'size' => pg_field_size($this->resultset, $i),
|
||||
'prtlen' => pg_field_prtlen($this->resultset, $i),
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
@@ -255,11 +255,12 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
|
||||
* Fetches the row at current position and moves the internal cursor to the next position
|
||||
* internal usage only
|
||||
*
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
public function fetch()
|
||||
public function fetch($type)
|
||||
{
|
||||
return sqlite_fetch_array($this->resultset, SQLITE_ASSOC);
|
||||
return sqlite_fetch_array($this->resultset, $type ? SQLITE_ASSOC : SQLITE_NUM);
|
||||
}
|
||||
|
||||
|
||||
@@ -293,14 +294,21 @@ class DibiSqliteDriver extends NObject implements DibiDriverInterface
|
||||
|
||||
|
||||
|
||||
/** this is experimental */
|
||||
public function buildMeta()
|
||||
/**
|
||||
* Returns metadata for all columns in a result set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsMeta()
|
||||
{
|
||||
$count = sqlite_num_fields($this->resultset);
|
||||
$meta = array();
|
||||
for ($index = 0; $index < $count; $index++) {
|
||||
$name = sqlite_field_name($this->resultset, $index);
|
||||
$meta[$name] = array('type' => dibi::FIELD_UNKNOWN);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
// items 'name' and 'table' are required
|
||||
$meta[] = array(
|
||||
'name' => sqlite_field_name($this->resultset, $i),
|
||||
'table' => NULL,
|
||||
);
|
||||
}
|
||||
return $meta;
|
||||
}
|
||||
|
@@ -99,6 +99,7 @@ class DibiConnection extends NObject
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// disconnects and rolls back transaction - do not rely on auto-disconnect and rollback!
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
|
@@ -153,9 +153,10 @@ interface DibiDriverInterface
|
||||
* Fetches the row at current position and moves the internal cursor to the next position
|
||||
* internal usage only
|
||||
*
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
* @param bool TRUE for associative array, FALSE for numeric
|
||||
* @return array array on success, nonarray if no next record
|
||||
*/
|
||||
function fetch();
|
||||
function fetch($type);
|
||||
|
||||
|
||||
|
||||
@@ -169,6 +170,16 @@ interface DibiDriverInterface
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns metadata for all columns in a result set
|
||||
*
|
||||
* @return array
|
||||
* @throws DibiException
|
||||
*/
|
||||
function getColumnsMeta();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the connection resource
|
||||
*
|
||||
|
@@ -55,10 +55,11 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
private $xlat;
|
||||
|
||||
/**
|
||||
* Describes columns types
|
||||
* Cache for $driver->getColumnsMeta()
|
||||
* @var array
|
||||
*/
|
||||
private $meta;
|
||||
private $metaCache;
|
||||
|
||||
|
||||
/**
|
||||
* Already fetched? Used for allowance for first seek(0)
|
||||
@@ -66,6 +67,12 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
*/
|
||||
private $fetched = FALSE;
|
||||
|
||||
/**
|
||||
* Qualifiy each column name with the table name?
|
||||
* @var array|FALSE
|
||||
*/
|
||||
private $withTables = FALSE;
|
||||
|
||||
|
||||
|
||||
private static $types = array(
|
||||
@@ -151,6 +158,52 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Qualifiy each column name with the table name?
|
||||
*
|
||||
* @param bool
|
||||
* @return void
|
||||
* @throws DibiException
|
||||
*/
|
||||
final public function setWithTables($val)
|
||||
{
|
||||
if ($val) {
|
||||
if ($this->metaCache === NULL) {
|
||||
$this->metaCache = $this->getDriver()->getColumnsMeta();
|
||||
}
|
||||
|
||||
$cols = array();
|
||||
foreach ($this->metaCache as $col) {
|
||||
// intentional ==
|
||||
$name = $col['table'] == '' ? $col['name'] : ($col['table'] . '.' . $col['name']);
|
||||
if (isset($cols[$name])) {
|
||||
$fix = 1;
|
||||
while (isset($cols[$name . '#' . $fix])) $fix++;
|
||||
$name .= '#' . $fix;
|
||||
}
|
||||
$cols[$name] = TRUE;
|
||||
}
|
||||
$this->withTables = array_keys($cols);
|
||||
|
||||
} else {
|
||||
$this->withTables = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Qualifiy each key with the table name?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
final public function getWithTables()
|
||||
{
|
||||
return (bool) $this->withTables;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the row at current position, process optional type conversion
|
||||
* and moves the internal cursor to the next position
|
||||
@@ -159,16 +212,23 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
*/
|
||||
final public function fetch()
|
||||
{
|
||||
$row = $this->getDriver()->fetch();
|
||||
if ($this->withTables === FALSE) {
|
||||
$row = $this->getDriver()->fetch(TRUE);
|
||||
if (!is_array($row)) return FALSE;
|
||||
|
||||
} else {
|
||||
$row = $this->getDriver()->fetch(FALSE);
|
||||
if (!is_array($row)) return FALSE;
|
||||
$row = array_combine($this->withTables, $row);
|
||||
}
|
||||
|
||||
$this->fetched = TRUE;
|
||||
|
||||
// types-converting?
|
||||
if ($this->xlat) {
|
||||
$xlat = $this->xlat; // little speed-up
|
||||
foreach ($row as $key => $value) {
|
||||
if (isset($xlat[$key])) {
|
||||
$row[$key] = $this->convert($value, $xlat[$key]);
|
||||
if ($this->xlat !== NULL) {
|
||||
foreach ($this->xlat as $col => $type) {
|
||||
if (isset($row[$col])) {
|
||||
$row[$col] = $this->convert($row[$col], $type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,21 +245,18 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
*/
|
||||
final function fetchSingle()
|
||||
{
|
||||
$row = $this->getDriver()->fetch();
|
||||
$row = $this->getDriver()->fetch(TRUE);
|
||||
if (!is_array($row)) return FALSE;
|
||||
$this->fetched = TRUE;
|
||||
$value = reset($row);
|
||||
|
||||
// types-converting?
|
||||
if ($this->xlat) {
|
||||
$xlat = $this->xlat; // little speed-up
|
||||
$value = reset($row);
|
||||
$key = key($row);
|
||||
return isset($xlat[$key])
|
||||
? $this->convert($value, $xlat[$key])
|
||||
: $value;
|
||||
if (isset($this->xlat[$key])) {
|
||||
return $this->convert($value, $this->xlat[$key]);
|
||||
}
|
||||
|
||||
return reset($row);
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
@@ -252,7 +309,7 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
$data = NULL;
|
||||
$assoc = explode(',', $assoc);
|
||||
|
||||
// check fields
|
||||
// check columns
|
||||
foreach ($assoc as $as) {
|
||||
if ($as !== '#' && $as !== '=' && !array_key_exists($as, $row)) {
|
||||
throw new InvalidArgumentException("Unknown column '$as' in associative descriptor");
|
||||
@@ -321,7 +378,7 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
|
||||
if ($value === NULL) {
|
||||
if ($key !== NULL) {
|
||||
throw new InvalidArgumentException("Either none or both fields must be specified");
|
||||
throw new InvalidArgumentException("Either none or both columns must be specified");
|
||||
}
|
||||
|
||||
if (count($row) < 2) {
|
||||
@@ -359,25 +416,21 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
|
||||
|
||||
|
||||
final public function setType($field, $type = NULL)
|
||||
final public function setType($col, $type = NULL)
|
||||
{
|
||||
if ($field === TRUE) {
|
||||
$this->buildMeta();
|
||||
|
||||
} elseif (is_array($field)) {
|
||||
$this->xlat = $field;
|
||||
if (is_array($col)) {
|
||||
$this->xlat = $col;
|
||||
|
||||
} else {
|
||||
$this->xlat[$field] = $type;
|
||||
$this->xlat[$col] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** is this needed? */
|
||||
final public function getType($field)
|
||||
final public function getType($col)
|
||||
{
|
||||
return isset($this->xlat[$field]) ? $this->xlat[$field] : NULL;
|
||||
return isset($this->xlat[$col]) ? $this->xlat[$col] : NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -402,46 +455,23 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets an array of field names
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
final public function getFields()
|
||||
{
|
||||
$this->buildMeta();
|
||||
return array_keys($this->meta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets an array of meta informations about column
|
||||
*
|
||||
* @param string column name
|
||||
* @return array
|
||||
*/
|
||||
final public function getMetaData($field)
|
||||
final public function getColumnsMeta()
|
||||
{
|
||||
$this->buildMeta();
|
||||
return isset($this->meta[$field]) ? $this->meta[$field] : FALSE;
|
||||
if ($this->metaCache === NULL) {
|
||||
$this->metaCache = $this->getDriver()->getColumnsMeta();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Acquires ....
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final protected function buildMeta()
|
||||
{
|
||||
if ($this->meta === NULL) {
|
||||
$this->meta = $this->getDriver()->buildMeta();
|
||||
foreach ($this->meta as $name => $info) {
|
||||
$this->xlat[$name] = $info['type'];
|
||||
}
|
||||
$cols = array();
|
||||
foreach ($this->metaCache as $col) {
|
||||
$name = (!$this->withTables || $col['table'] === NULL) ? $col['name'] : ($col['table'] . '.' . $col['name']);
|
||||
$cols[$name] = $col;
|
||||
}
|
||||
return $cols;
|
||||
}
|
||||
|
||||
|
||||
@@ -453,25 +483,33 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
*/
|
||||
final public function dump()
|
||||
{
|
||||
$none = TRUE;
|
||||
foreach ($this as $i => $row) {
|
||||
if ($none) {
|
||||
echo "\n<table class=\"dump\">\n<thead>\n\t<tr>\n\t\t<th>#row</th>\n";
|
||||
|
||||
foreach ($this->getFields() as $field) {
|
||||
echo "\t\t<th>" . htmlSpecialChars($field) . "</th>\n";
|
||||
foreach ($row as $col => $foo) {
|
||||
echo "\t\t<th>" . htmlSpecialChars($col) . "</th>\n";
|
||||
}
|
||||
|
||||
echo "\t</tr>\n</thead>\n<tbody>\n";
|
||||
$none = FALSE;
|
||||
}
|
||||
|
||||
foreach ($this as $row => $fields) {
|
||||
echo "\t<tr>\n\t\t<th>", $row, "</th>\n";
|
||||
foreach ($fields as $field) {
|
||||
//if (is_object($field)) $field = $field->__toString();
|
||||
echo "\t\t<td>", htmlSpecialChars($field), "</td>\n";
|
||||
echo "\t<tr>\n\t\t<th>", $i, "</th>\n";
|
||||
foreach ($row as $col) {
|
||||
//if (is_object($col)) $col = $col->__toString();
|
||||
echo "\t\t<td>", htmlSpecialChars($col), "</td>\n";
|
||||
}
|
||||
echo "\t</tr>\n";
|
||||
}
|
||||
|
||||
if ($none) {
|
||||
echo '<p><em>empty resultset</em></p>';
|
||||
} else {
|
||||
echo "</tbody>\n</table>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -55,26 +55,27 @@ echo '<hr>';
|
||||
|
||||
|
||||
// fetch row by row
|
||||
foreach ($res as $row => $fields) {
|
||||
print_r($fields);
|
||||
foreach ($res as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
echo '<hr>';
|
||||
|
||||
|
||||
// fetch row by row with defined offset
|
||||
foreach ($res->getIterator(2) as $row => $fields) {
|
||||
print_r($fields);
|
||||
foreach ($res->getIterator(2) as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
// fetch row by row with defined offset and limit
|
||||
foreach ($res->getIterator(2, 1) as $row => $fields) {
|
||||
print_r($fields);
|
||||
foreach ($res->getIterator(2, 1) as $n => $row) {
|
||||
print_r($row);
|
||||
}
|
||||
|
||||
|
||||
// more complex association array
|
||||
$res = dibi::query('
|
||||
SELECT * FROM [products]
|
||||
SELECT *
|
||||
FROM [products]
|
||||
INNER JOIN [orders] USING ([product_id])
|
||||
INNER JOIN [customers] USING ([customer_id])
|
||||
');
|
||||
|
@@ -13,14 +13,7 @@ dibi::connect(array(
|
||||
|
||||
$res = dibi::query('SELECT * FROM [customers]');
|
||||
|
||||
// auto-convert this field to integer
|
||||
// auto-convert this column to integer
|
||||
$res->setType('customer_id', Dibi::FIELD_INTEGER);
|
||||
$row = $res->fetch();
|
||||
var_dump($row);
|
||||
|
||||
|
||||
// auto-detect all types
|
||||
// WARNING: THIS WILL NOT WORK WITH SQLITE
|
||||
$res->setType(TRUE);
|
||||
$row = $res->fetch();
|
||||
var_dump($row);
|
||||
|
@@ -41,7 +41,8 @@ dibi::test("
|
||||
UPDATE [colors] SET", array(
|
||||
'color' => 'blue',
|
||||
'order' => 12,
|
||||
), "WHERE [id]=%i", 123);
|
||||
), "
|
||||
WHERE [id]=%i", 123);
|
||||
|
||||
|
||||
// SELECT
|
||||
@@ -51,10 +52,15 @@ $timestamp = mktime(0, 0, 0, 10, 13, 1997);
|
||||
dibi::test('
|
||||
SELECT COUNT(*) as [count]
|
||||
FROM [comments]
|
||||
WHERE [ip] LIKE %s', $ipMask, 'AND [date] > ', dibi::date($timestamp)
|
||||
WHERE [ip] LIKE %s', $ipMask, '
|
||||
AND [date] > ', dibi::date($timestamp)
|
||||
);
|
||||
|
||||
|
||||
// IN array
|
||||
$array = array(1, 2, 3);
|
||||
dibi::test("SELECT * FROM [people] WHERE [id] IN (", $array, ")");
|
||||
dibi::test("
|
||||
SELECT *
|
||||
FROM [people]
|
||||
WHERE [id] IN (", $array, ")
|
||||
");
|
||||
|
Reference in New Issue
Block a user