1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-20 12:51:40 +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:
David Grudl
2007-11-30 10:12:45 +00:00
parent 1aad1c8da9
commit cbd37021f2
15 changed files with 313 additions and 353 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)
{
return odbc_fetch_array($this->resultset, ++$this->row);
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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}