diff --git a/dibi/libs/DibiConnection.php b/dibi/libs/DibiConnection.php index 0dff2b15..5c10660c 100644 --- a/dibi/libs/DibiConnection.php +++ b/dibi/libs/DibiConnection.php @@ -50,7 +50,6 @@ class DibiConnection extends DibiObject * Connection options: (see driver-specific options too) * - lazy (bool) => if TRUE, connection will be established only when required * - result (array) => result set options - * - detectTypes (bool) => detect the types of result set fields? * - formatDateTime => date-time format (if empty, DateTime objects will be returned) * - profiler (array or bool) * - run (bool) => enable profiler? @@ -81,7 +80,6 @@ class DibiConnection extends DibiObject self::alias($config, 'username', 'user'); self::alias($config, 'password', 'pass'); self::alias($config, 'host', 'hostname'); - self::alias($config, 'result|detectTypes', 'resultDetectTypes'); // back compatibility self::alias($config, 'result|formatDateTime', 'resultDateTime'); if (!isset($config['driver'])) { diff --git a/dibi/libs/DibiDatabaseInfo.php b/dibi/libs/DibiDatabaseInfo.php index bca1930f..800ebdd1 100644 --- a/dibi/libs/DibiDatabaseInfo.php +++ b/dibi/libs/DibiDatabaseInfo.php @@ -534,10 +534,7 @@ class DibiColumnInfo extends DibiObject */ public function getType() { - if (self::$types === NULL) { - self::$types = new DibiHashMap(array(__CLASS__, 'detectType')); - } - return self::$types->{$this->info['nativetype']}; + return self::getTypeCache()->{$this->info['nativetype']}; } @@ -640,6 +637,19 @@ class DibiColumnInfo extends DibiObject return dibi::TEXT; } + + + /** + * @internal + */ + public static function getTypeCache() + { + if (self::$types === NULL) { + self::$types = new DibiHashMap(array(__CLASS__, 'detectType')); + } + return self::$types; + } + } diff --git a/dibi/libs/DibiResult.php b/dibi/libs/DibiResult.php index a9ad0301..14a2062c 100644 --- a/dibi/libs/DibiResult.php +++ b/dibi/libs/DibiResult.php @@ -43,7 +43,7 @@ class DibiResult extends DibiObject implements IDataSource private $driver; /** @var array Translate table */ - private $types; + private $types = array(); /** @var DibiResultInfo */ private $meta; @@ -66,10 +66,7 @@ class DibiResult extends DibiObject implements IDataSource public function __construct($driver, $config) { $this->driver = $driver; - - if (!empty($config['detectTypes'])) { - $this->detectTypes(); - } + $this->detectTypes(); if (!empty($config['formatDateTime'])) { $this->dateFormat = is_string($config['formatDateTime']) ? $config['formatDateTime'] : ''; @@ -220,19 +217,11 @@ class DibiResult extends DibiObject implements IDataSource final public function fetch() { $row = $this->getDriver()->fetch(TRUE); - if (!is_array($row)) return FALSE; - - $this->fetched = TRUE; - - // types-converting? - if ($this->types !== NULL) { - foreach ($this->types as $col => $type) { - if (isset($row[$col])) { - $row[$col] = $this->convert($row[$col], $type); - } - } + if (!is_array($row)) { + return FALSE; } - + $this->fetched = TRUE; + $this->normalize($row); return new $this->rowClass($row); } @@ -245,17 +234,12 @@ class DibiResult extends DibiObject implements IDataSource final public function fetchSingle() { $row = $this->getDriver()->fetch(TRUE); - if (!is_array($row)) return FALSE; - $this->fetched = TRUE; - $value = reset($row); - - // types-converting? - $key = key($row); - if (isset($this->types[$key])) { - return $this->convert($value, $this->types[$key]); + if (!is_array($row)) { + return FALSE; } - - return $value; + $this->fetched = TRUE; + $this->normalize($row); + return reset($row); } @@ -495,7 +479,71 @@ class DibiResult extends DibiObject implements IDataSource - /********************* meta info ****************d*g**/ + /********************* column types ****************d*g**/ + + + + /** + * Autodetect column types. + * @return void + */ + private function detectTypes() + { + $cache = DibiColumnInfo::getTypeCache(); + try { + foreach ($this->getDriver()->getResultColumns() as $col) { + $this->types[$col['name']] = $cache->{$col['nativetype']}; + } + } catch (DibiNotSupportedException $e) {} + } + + + + /** + * Converts values to specified type and format. + * @param array + * @return void + */ + private function normalize(array & $row) + { + foreach ($this->types as $key => $type) { + if (!isset($row[$key])) { // NULL + continue; + } + $value = $row[$key]; + if ($value === FALSE || $type === dibi::TEXT) { + + } elseif ($type === dibi::INTEGER) { + $row[$key] = is_float($tmp = $value * 1) ? $value : $tmp; + + } elseif ($type === dibi::FLOAT) { + $row[$key] = (string) ($tmp = (float) $value) === $value ? $tmp : $value; + + } elseif ($type === dibi::BOOL) { + $row[$key] = ((bool) $value) && $value !== 'f' && $value !== 'F'; + + } elseif ($type === dibi::DATE || $type === dibi::DATETIME) { + if ((int) $value === 0) { // '', NULL, FALSE, '0000-00-00', ... + + } elseif ($this->dateFormat === '') { // return DateTime object (default) + $row[$key] = new DibiDateTime(is_numeric($value) ? date('Y-m-d H:i:s', $value) : $value); + + } elseif ($this->dateFormat === 'U') { // return timestamp + $row[$key] = is_numeric($value) ? (int) $value : strtotime($value); + + } elseif (is_numeric($value)) { // formatted date + $row[$key] = date($this->dateFormat, $value); + + } else { + $value = new DibiDateTime($value); + $row[$key] = $value->format($this->dateFormat); + } + + } elseif ($type === dibi::BINARY) { + $row[$key] = $this->getDriver()->unescape($value, $type); + } + } + } @@ -513,33 +561,6 @@ class DibiResult extends DibiObject implements IDataSource - /** - * Autodetect column types. - * @return void - */ - final public function detectTypes() - { - foreach ($this->getInfo()->getColumns() as $col) { - $this->types[$col->getName()] = $col->getType(); - } - } - - - - /** - * Define multiple columns types. - * @param array - * @return DibiResult provides a fluent interface - * @internal - */ - final public function setTypes(array $types) - { - $this->types = $types; - return $this; - } - - - /** * Returns column type. * @return string @@ -551,57 +572,7 @@ class DibiResult extends DibiObject implements IDataSource - /** - * Converts value to specified type and format. - * @param mixed value - * @param int type - * @return mixed - */ - protected function convert($value, $type) - { - if ($value === NULL || $value === FALSE) { - return NULL; - } - - switch ($type) { - case dibi::TEXT: - return (string) $value; - - case dibi::BINARY: - return $this->getDriver()->unescape($value, $type); - - case dibi::INTEGER: - return is_float($tmp = $value * 1) ? $value : $tmp; - - case dibi::FLOAT: - return (float) $value; - - case dibi::DATE: - case dibi::DATETIME: - if ((int) $value === 0) { // '', NULL, FALSE, '0000-00-00', ... - return NULL; - - } elseif ($this->dateFormat === '') { // return DateTime object (default) - return new DibiDateTime(is_numeric($value) ? date('Y-m-d H:i:s', $value) : $value); - - } elseif ($this->dateFormat === 'U') { // return timestamp - return is_numeric($value) ? (int) $value : strtotime($value); - - } elseif (is_numeric($value)) { // formatted date - return date($this->dateFormat, $value); - - } else { - $value = new DibiDateTime($value); - return $value->format($this->dateFormat); - } - - case dibi::BOOL: - return ((bool) $value) && $value !== 'f' && $value !== 'F'; - - default: - return $value; - } - } + /********************* meta info ****************d*g**/ @@ -629,9 +600,7 @@ class DibiResult extends DibiObject implements IDataSource - /** - * @deprecated - */ + /** @deprecated */ public function getColumnNames($fullNames = FALSE) { trigger_error(__METHOD__ . '() is deprecated; use $res->getInfo()->getColumnNames() instead.', E_USER_WARNING); diff --git a/examples/result-set-data-types.php b/examples/result-set-data-types.php index 03774f56..f67d3093 100644 --- a/examples/result-set-data-types.php +++ b/examples/result-set-data-types.php @@ -20,7 +20,7 @@ dibi::connect(array( $res = dibi::query('SELECT * FROM [customers]'); $res->setType('customer_id', Dibi::INTEGER) - ->setType('added', Dibi::DATETIME, 'H:i j.n.Y'); + ->setType('added', Dibi::DATETIME); Debugger::dump( $res->fetch() ); // outputs: @@ -35,8 +35,6 @@ Debugger::dump( $res->fetch() ); // using auto-detection (works well with MySQL or other strictly typed databases) $res = dibi::query('SELECT * FROM [customers]'); -$res->detectTypes(); - Debugger::dump( $res->fetch() ); // outputs: // object(DibiRow)#3 (3) {