1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-07 22:56:35 +02:00

- added dibi-field-type autodetection

- added DibiColumnInfo::getVendorInfo()
This commit is contained in:
David Grudl
2008-10-28 14:37:40 +00:00
parent 318b3093a5
commit 7565ffb1d4
9 changed files with 119 additions and 50 deletions

View File

@@ -101,6 +101,7 @@ class dibi
FIELD_FLOAT = 'f', FIELD_FLOAT = 'f',
FIELD_DATE = 'd', FIELD_DATE = 'd',
FIELD_DATETIME = 't', FIELD_DATETIME = 't',
FIELD_TIME = 't',
// special // special
IDENTIFIER = 'n'; IDENTIFIER = 'n';

View File

@@ -346,9 +346,8 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
'name' => $row['name'], 'name' => $row['name'],
'fullname' => $row['column_source'] ? $row['column_source'] . '.' . $row['name'] : $row['name'], 'fullname' => $row['column_source'] ? $row['column_source'] . '.' . $row['name'] : $row['name'],
'table' => $row['column_source'], 'table' => $row['column_source'],
'type' => NULL,
'nativetype' => $row['type'], 'nativetype' => $row['type'],
) + $row; );
} }
return $res; return $res;
} }

View File

@@ -409,12 +409,12 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
$row = (array) mysql_fetch_field($this->resultSet, $i); $row = (array) mysql_fetch_field($this->resultSet, $i);
$res[] = array( $res[] = array(
'name' => $row['name'],
'table' => $row['table'],
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'], 'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
'type' => NULL,
'nativetype' => strtoupper($row['type']), 'nativetype' => strtoupper($row['type']),
'nullable' => !($row['not_null']), 'vendor' => $row,
'default' => $row['def'], );
) + $row;
} }
return $res; return $res;
} }

View File

@@ -386,21 +386,27 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
*/ */
public function getColumnsMeta() public function getColumnsMeta()
{ {
static $types;
if (empty($types)) {
$consts = get_defined_constants(TRUE);
foreach ($consts['mysqli'] as $key => $value) {
if (strncmp($key, 'MYSQLI_TYPE_', 12) === 0) {
$types[$value] = substr($key, 12);
}
}
}
$count = mysqli_num_fields($this->resultSet); $count = mysqli_num_fields($this->resultSet);
$res = array(); $res = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
$row = (array) mysqli_fetch_field_direct($this->resultSet, $i); $row = (array) mysqli_fetch_field_direct($this->resultSet, $i);
$res[] = array( $res[] = array(
'name' => $row['name'], 'name' => $row['name'],
'column' => $row['orgname'],
'alias' => $row['table'],
'table' => $row['orgtable'], 'table' => $row['orgtable'],
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'], 'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
'type' => NULL, 'nativetype' => $types[$row['type']],
'nativetype' => $row['type'], 'vendor' => $row,
'nullable' => !($row['flags'] & MYSQLI_NOT_NULL_FLAG), );
'default' => $row['def'],
) + $row;
} }
return $res; return $res;
} }

View File

@@ -400,10 +400,12 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
throw new DibiDriverException('Driver does not support meta data.'); throw new DibiDriverException('Driver does not support meta data.');
} }
$res[] = array( $res[] = array(
'type' => NULL, 'name' => $row['name'],
'table' => $row['table'],
'nativetype' => $row['native_type'], 'nativetype' => $row['native_type'],
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'], 'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
) + $row; 'vendor' => $row,
);
} }
return $res; return $res;
} }

View File

@@ -456,14 +456,14 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
$this->query(" $this->query("
SELECT indkey SELECT indkey
FROM pg_index, pg_class FROM pg_index, pg_class
WHERE pg_class.relname = '$_table' AND pg_class.oid = pg_index.indrelid AND pg_index.indisprimary WHERE pg_class.relname = $_table AND pg_class.oid = pg_index.indrelid AND pg_index.indisprimary
"); ");
$primary = (int) pg_fetch_object($this->resultSet)->indkey; $primary = (int) pg_fetch_object($this->resultSet)->indkey;
$this->query(" $this->query("
SELECT * SELECT *
FROM information_schema.columns FROM information_schema.columns
WHERE table_name = '$_table' AND table_schema = current_schema() WHERE table_name = $_table AND table_schema = current_schema()
ORDER BY ordinal_position ORDER BY ordinal_position
"); ");
$res = array(); $res = array();
@@ -472,13 +472,13 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
$res[] = array( $res[] = array(
'name' => $row['column_name'], 'name' => $row['column_name'],
'table' => $table, 'table' => $table,
'type' => NULL,
'nativetype' => strtoupper($row['udt_name']), 'nativetype' => strtoupper($row['udt_name']),
'size' => $size ? $size : NULL, 'size' => $size ? $size : NULL,
'nullable' => $row['is_nullable'] === 'YES', 'nullable' => $row['is_nullable'] === 'YES',
'default' => $row['column_default'], 'default' => $row['column_default'],
'autoincrement' => (int) $row['ordinal_position'] === $primary && substr($row['column_default'], 0, 7) === 'nextval', 'autoincrement' => (int) $row['ordinal_position'] === $primary && substr($row['column_default'], 0, 7) === 'nextval',
) + $row; 'vendor' => $row,
);
} }
$this->free(); $this->free();
return $res; return $res;

View File

@@ -369,6 +369,7 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
'name' => isset($pair[1]) ? $pair[1] : $pair[0], 'name' => isset($pair[1]) ? $pair[1] : $pair[0],
'table' => isset($pair[1]) ? $pair[0] : NULL, 'table' => isset($pair[1]) ? $pair[0] : NULL,
'fullname' => $name, 'fullname' => $name,
'nativetype' => NULL,
); );
} }
return $res; return $res;

View File

@@ -138,8 +138,11 @@ class DibiTableInfo extends DibiObject
/** @var IDibiDriver */ /** @var IDibiDriver */
private $driver; private $driver;
/** @var array */ /** @var string */
private $info; private $name;
/** @var bool */
private $view;
/** @var array */ /** @var array */
private $columns; private $columns;
@@ -158,7 +161,8 @@ class DibiTableInfo extends DibiObject
public function __construct(IDibiDriver $driver, array $info) public function __construct(IDibiDriver $driver, array $info)
{ {
$this->driver = $driver; $this->driver = $driver;
$this->info = $info; $this->name = $info['name'];
$this->view = !empty($info['view']);
} }
@@ -168,7 +172,7 @@ class DibiTableInfo extends DibiObject
*/ */
public function getName() public function getName()
{ {
return $this->info['name']; return $this->name;
} }
@@ -178,7 +182,7 @@ class DibiTableInfo extends DibiObject
*/ */
public function isView() public function isView()
{ {
return !empty($this->info['view']); return $this->view;
} }
@@ -279,7 +283,7 @@ class DibiTableInfo extends DibiObject
{ {
if ($this->columns === NULL) { if ($this->columns === NULL) {
$this->columns = array(); $this->columns = array();
foreach ($this->driver->getColumns($this->info['name']) as $info) { foreach ($this->driver->getColumns($this->name) as $info) {
$this->columns[strtolower($info['name'])] = new DibiColumnInfo($this->driver, $info); $this->columns[strtolower($info['name'])] = new DibiColumnInfo($this->driver, $info);
} }
} }
@@ -295,7 +299,7 @@ class DibiTableInfo extends DibiObject
if ($this->indexes === NULL) { if ($this->indexes === NULL) {
$this->initColumns(); $this->initColumns();
$this->indexes = array(); $this->indexes = array();
foreach ($this->driver->getIndexes($this->info['name']) as $info) { foreach ($this->driver->getIndexes($this->name) as $info) {
foreach ($info['columns'] as $key => $name) { foreach ($info['columns'] as $key => $name) {
$info['columns'][$key] = $this->columns[strtolower($name)]; $info['columns'][$key] = $this->columns[strtolower($name)];
} }
@@ -328,18 +332,25 @@ class DibiTableInfo extends DibiObject
*/ */
class DibiColumnInfo extends DibiObject class DibiColumnInfo extends DibiObject
{ {
/** @var array */
private static $types;
/** @var IDibiDriver */ /** @var IDibiDriver */
private $driver; private $driver;
/** @var array (name, table, fullname, type, nativetype, size, nullable, default, autoincrement) */ /** @var array (name, nativetype, [table], [fullname], [size], [nullable], [default], [autoincrement], [vendor]) */
private $info; private $info;
/** @var string */
private $type;
public function __construct(IDibiDriver $driver, array $info) public function __construct(IDibiDriver $driver, array $info)
{ {
$this->driver = $driver; $this->driver = $driver;
$this->info = $info; $this->info = $info;
$this->type = self::detectType($this->info['nativetype']);
} }
@@ -382,7 +393,7 @@ class DibiColumnInfo extends DibiObject
*/ */
public function getType() public function getType()
{ {
return isset($this->info['type']) ? $this->info['type'] : NULL; return $this->type;
} }
@@ -392,7 +403,7 @@ class DibiColumnInfo extends DibiObject
*/ */
public function getNativeType() public function getNativeType()
{ {
return isset($this->info['nativetype']) ? $this->info['nativetype'] : NULL; return $this->info['nativetype'];
} }
@@ -412,7 +423,7 @@ class DibiColumnInfo extends DibiObject
*/ */
public function isNullable() public function isNullable()
{ {
return !empty($this->info['nullable']); return isset($this->info['nullable']) ? (bool) $this->info['nullable'] : NULL;
} }
@@ -422,7 +433,7 @@ class DibiColumnInfo extends DibiObject
*/ */
public function isAutoIncrement() public function isAutoIncrement()
{ {
return !empty($this->info['autoincrement']); return isset($this->info['autoincrement']) ? (bool) $this->info['autoincrement'] : NULL;
} }
@@ -441,9 +452,39 @@ class DibiColumnInfo extends DibiObject
* @param string * @param string
* @return mixed * @return mixed
*/ */
public function getInfo($key) public function getVendorInfo($key)
{ {
return isset($this->info[$key]) ? $this->info[$key] : NULL; return isset($this->info['vendor'][$key]) ? $this->info['vendor'][$key] : NULL;
}
/**
* Heuristic type detection.
* @param string
* @return string
*/
public static function detectType($type)
{
static $patterns = array(
'BYTE|COUNTER|SERIAL|INT|LONG' => dibi::FIELD_INTEGER,
'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC' => dibi::FIELD_FLOAT,
'^TIME$' => dibi::FIELD_TIME,
'TIME' => dibi::FIELD_DATETIME, // DATETIME, TIMESTAMP
'YEAR|DATE' => dibi::FIELD_DATE,
'BYTEA|BLOB|BIN' => dibi::FIELD_BINARY,
'BOOL|BIT' => dibi::FIELD_BOOL,
);
if (!isset(self::$types[$type])) {
self::$types[$type] = dibi::FIELD_TEXT;
foreach ($patterns as $s => $val) {
if (preg_match("#$s#i", $type)) {
return self::$types[$type] = $val;
}
}
}
return self::$types[$type];
} }
} }
@@ -454,6 +495,7 @@ class DibiColumnInfo extends DibiObject
/** /**
* Reflection metadata class for a foreign key. * Reflection metadata class for a foreign key.
* @package dibi * @package dibi
* @todo
*/ */
class DibiForeignKeyInfo extends DibiObject class DibiForeignKeyInfo extends DibiObject
{ {
@@ -502,7 +544,7 @@ class DibiForeignKeyInfo extends DibiObject
*/ */
class DibiIndexInfo extends DibiObject class DibiIndexInfo extends DibiObject
{ {
/** @var array (name, columns, unique, primary) */ /** @var array (name, columns, [unique], [primary]) */
private $info; private $info;

View File

@@ -58,7 +58,7 @@ class DibiResult extends DibiObject implements IDataSource
* Cache for $driver->getColumnsMeta(). * Cache for $driver->getColumnsMeta().
* @var array * @var array
*/ */
private $metaCache; private $meta;
/** /**
* Already fetched? Used for allowance for first seek(0). * Already fetched? Used for allowance for first seek(0).
@@ -164,12 +164,8 @@ class DibiResult extends DibiObject implements IDataSource
final public function setWithTables($val) final public function setWithTables($val)
{ {
if ($val) { if ($val) {
if ($this->metaCache === NULL) {
$this->metaCache = $this->getDriver()->getColumnsMeta();
}
$cols = array(); $cols = array();
foreach ($this->metaCache as $info) { foreach ($this->getMeta() as $info) {
$name = $info['fullname']; $name = $info['fullname'];
if (isset($cols[$name])) { if (isset($cols[$name])) {
$fix = 1; $fix = 1;
@@ -446,6 +442,19 @@ class DibiResult extends DibiObject implements IDataSource
/**
* Autodetect column types.
* @return void
*/
final public function detectTypes()
{
foreach ($this->getMeta() as $info) {
$this->xlat[$info['name']] = array('type' => $info['type'], 'format' => NULL);
}
}
/** /**
* Define multiple columns types (for internal usage). * Define multiple columns types (for internal usage).
* @param array * @param array
@@ -508,18 +517,14 @@ class DibiResult extends DibiObject implements IDataSource
/** /**
* Gets an array of meta informations about column. * Gets an array of meta informations about columns.
* *
* @return array of DibiColumnInfo * @return array of DibiColumnInfo
*/ */
final public function getColumns() final public function getColumns()
{ {
if ($this->metaCache === NULL) {
$this->metaCache = $this->getDriver()->getColumnsMeta();
}
$cols = array(); $cols = array();
foreach ($this->metaCache as $info) { foreach ($this->getMeta() as $info) {
$cols[] = new DibiColumnInfo($this->driver, $info); $cols[] = new DibiColumnInfo($this->driver, $info);
} }
return $cols; return $cols;
@@ -533,11 +538,8 @@ class DibiResult extends DibiObject implements IDataSource
*/ */
public function getColumnNames($withTables = FALSE) public function getColumnNames($withTables = FALSE)
{ {
if ($this->metaCache === NULL) {
$this->metaCache = $this->getDriver()->getColumnsMeta();
}
$cols = array(); $cols = array();
foreach ($this->metaCache as $info) { foreach ($this->getMeta() as $info) {
$cols[] = $info[$withTables ? 'fullname' : 'name']; $cols[] = $info[$withTables ? 'fullname' : 'name'];
} }
return $cols; return $cols;
@@ -623,6 +625,22 @@ class DibiResult extends DibiObject implements IDataSource
} }
/**
* Meta lazy initialization.
* @return array
*/
private function getMeta()
{
if ($this->meta === NULL) {
$this->meta = $this->getDriver()->getColumnsMeta();
foreach ($this->meta as & $row) {
$row['type'] = DibiColumnInfo::detectType($row['nativetype']);
}
}
return $this->meta;
}
} }