1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-07 06:36:44 +02:00

improved reflection skills

This commit is contained in:
David Grudl
2008-10-28 01:03:50 +00:00
parent e221a13dda
commit ab892255d3
15 changed files with 242 additions and 140 deletions

View File

@@ -339,15 +339,18 @@ class DibiMsSqlDriver extends DibiObject implements IDibiDriver
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = mssql_num_fields($this->resultSet); $count = mssql_num_fields($this->resultSet);
$meta = array(); $res = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required $row = (array) mssql_fetch_field($this->resultSet, $i);
$info = (array) mssql_fetch_field($this->resultSet, $i); $res[] = array(
$info['table'] = $info['column_source']; 'name' => $row['name'],
$info['nativetype'] = $info['type']; 'fullname' => $row['column_source'] ? $row['column_source'] . '.' . $row['name'] : $row['name'],
$meta[] = $info; 'table' => $row['column_source'],
'type' => NULL,
'nativetype' => $row['type'],
) + $row;
} }
return $meta; return $res;
} }

View File

@@ -405,13 +405,18 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = mysql_num_fields($this->resultSet); $count = mysql_num_fields($this->resultSet);
$meta = array(); $res = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
$info = (array) mysql_fetch_field($this->resultSet, $i); $row = (array) mysql_fetch_field($this->resultSet, $i);
$info['nativetype'] = $info['type']; $res[] = array(
$meta[] = $info; 'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
'type' => NULL,
'nativetype' => strtoupper($row['type']),
'nullable' => !($row['not_null']),
'default' => $row['def'],
) + $row;
} }
return $meta; return $res;
} }
@@ -438,10 +443,13 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
*/ */
public function getTables() public function getTables()
{ {
$this->query("SHOW TABLES"); $this->query("SHOW FULL TABLES");
$res = array(); $res = array();
while ($row = mysql_fetch_array($this->resultSet, MYSQL_NUM)) { while ($row = $this->fetch(FALSE)) {
$res[] = array('name' => $row[0]); $res[] = array(
'name' => $row[0],
'view' => isset($row[1]) && $row[1] === 'VIEW',
);
} }
$this->free(); $this->free();
return $res; return $res;
@@ -456,7 +464,22 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
*/ */
public function getColumns($table) public function getColumns($table)
{ {
throw new NotImplementedException; $this->query("SHOW COLUMNS FROM `$table`");
$res = array();
while ($row = $this->fetch(TRUE)) {
$type = explode('(', $row['Type']);
$res[] = array(
'name' => $row['Field'],
'table' => $table,
'nativetype' => strtoupper($type[0]),
'size' => isset($type[1]) ? (int) $type[1] : NULL,
'nullable' => $row['Null'] === 'YES',
'default' => $row['Default'],
'autoincrement' => $row['Extra'] === 'auto_increment',
);
}
$this->free();
return $res;
} }
@@ -468,7 +491,16 @@ class DibiMySqlDriver extends DibiObject implements IDibiDriver
*/ */
public function getIndexes($table) public function getIndexes($table)
{ {
throw new NotImplementedException; $this->query("SHOW INDEX FROM `$table`");
$res = array();
while ($row = $this->fetch(TRUE)) {
$res[$row['Key_name']]['name'] = $row['Key_name'];
$res[$row['Key_name']]['unique'] = !$row['Non_unique'];
$res[$row['Key_name']]['primary'] = $row['Key_name'] === 'PRIMARY';
$res[$row['Key_name']]['columns'][$row['Seq_in_index'] - 1] = $row['Column_name'];
}
$this->free();
return array_values($res);
} }

View File

@@ -387,14 +387,22 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = mysqli_num_fields($this->resultSet); $count = mysqli_num_fields($this->resultSet);
$meta = array(); $res = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required $row = (array) mysqli_fetch_field_direct($this->resultSet, $i);
$info = (array) mysqli_fetch_field_direct($this->resultSet, $i); $res[] = array(
$info['nativetype'] = $info['type']; 'name' => $row['name'],
$meta[] = $info; 'column' => $row['orgname'],
'alias' => $row['table'],
'table' => $row['orgtable'],
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
'type' => NULL,
'nativetype' => $row['type'],
'nullable' => !($row['flags'] & MYSQLI_NOT_NULL_FLAG),
'default' => $row['def'],
) + $row;
} }
return $meta; return $res;
} }
@@ -421,10 +429,18 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
*/ */
public function getTables() public function getTables()
{ {
$this->query("SHOW TABLES"); /*$this->query("
SELECT TABLE_NAME as name, TABLE_TYPE = 'VIEW' as view
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
");*/
$this->query("SHOW FULL TABLES");
$res = array(); $res = array();
while ($row = mysqli_fetch_array($this->resultSet, MYSQLI_NUM)) { while ($row = $this->fetch(FALSE)) {
$res[] = array('name' => $row[0]); $res[] = array(
'name' => $row[0],
'view' => isset($row[1]) && $row[1] === 'VIEW',
);
} }
$this->free(); $this->free();
return $res; return $res;
@@ -439,7 +455,28 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
*/ */
public function getColumns($table) public function getColumns($table)
{ {
throw new NotImplementedException; /*$table = $this->escape($table, dibi::FIELD_TEXT);
$this->query("
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = $table AND TABLE_SCHEMA = DATABASE()
");*/
$this->query("SHOW COLUMNS FROM `$table`");
$res = array();
while ($row = $this->fetch(TRUE)) {
$type = explode('(', $row['Type']);
$res[] = array(
'name' => $row['Field'],
'table' => $table,
'nativetype' => strtoupper($type[0]),
'size' => isset($type[1]) ? (int) $type[1] : NULL,
'nullable' => $row['Null'] === 'YES',
'default' => $row['Default'],
'autoincrement' => $row['Extra'] === 'auto_increment',
);
}
$this->free();
return $res;
} }
@@ -451,7 +488,23 @@ class DibiMySqliDriver extends DibiObject implements IDibiDriver
*/ */
public function getIndexes($table) public function getIndexes($table)
{ {
throw new NotImplementedException; /*$table = $this->escape($table, dibi::FIELD_TEXT);
$this->query("
SELECT *
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_NAME = $table AND TABLE_SCHEMA = DATABASE()
AND REFERENCED_COLUMN_NAME IS NULL
");*/
$this->query("SHOW INDEX FROM `$table`");
$res = array();
while ($row = $this->fetch(TRUE)) {
$res[$row['Key_name']]['name'] = $row['Key_name'];
$res[$row['Key_name']]['unique'] = !$row['Non_unique'];
$res[$row['Key_name']]['primary'] = $row['Key_name'] === 'PRIMARY';
$res[$row['Key_name']]['columns'][$row['Seq_in_index'] - 1] = $row['Column_name'];
}
$this->free();
return array_values($res);
} }

View File

@@ -361,19 +361,16 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = odbc_num_fields($this->resultSet); $count = odbc_num_fields($this->resultSet);
$meta = array(); $res = array();
for ($i = 1; $i <= $count; $i++) { for ($i = 1; $i <= $count; $i++) {
// items 'name' and 'table' are required $res[] = array(
$meta[] = array(
'name' => odbc_field_name($this->resultSet, $i), 'name' => odbc_field_name($this->resultSet, $i),
'table' => NULL, 'table' => NULL,
'fullname' => odbc_field_name($this->resultSet, $i),
'nativetype'=> odbc_field_type($this->resultSet, $i), 'nativetype'=> 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; return $res;
} }
@@ -402,9 +399,15 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
{ {
$result = odbc_tables($this->connection); $result = odbc_tables($this->connection);
$res = array(); $res = array();
while (odbc_fetch_row($result)) { while ($row = odbc_fetch_array($result)) {
$res[] = array('name' => odbc_result($result, 'TABLE_NAME')); if ($row['TABLE_TYPE'] === 'TABLE' || $row['TABLE_TYPE'] === 'VIEW') {
$res[] = array(
'name' => $row['TABLE_NAME'],
'view' => $row['TABLE_TYPE'] === 'VIEW',
);
}
} }
odbc_free_result($result);
return $res; return $res;
} }
@@ -417,7 +420,22 @@ class DibiOdbcDriver extends DibiObject implements IDibiDriver
*/ */
public function getColumns($table) public function getColumns($table)
{ {
throw new NotImplementedException; $result = odbc_columns($this->connection);
$res = array();
while ($row = odbc_fetch_array($result)) {
if ($row['TABLE_NAME'] === $table) {
$res[] = array(
'name' => $row['COLUMN_NAME'],
'table' => $table,
'nativetype' => $row['TYPE_NAME'],
'size' => $row['COLUMN_SIZE'],
'nullable' => (bool) $row['NULLABLE'],
'default' => $row['COLUMN_DEF'],
);
}
}
odbc_free_result($result);
return $res;
} }

View File

@@ -347,19 +347,16 @@ class DibiOracleDriver extends DibiObject implements IDibiDriver
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = oci_num_fields($this->resultSet); $count = oci_num_fields($this->resultSet);
$meta = array(); $res = array();
for ($i = 1; $i <= $count; $i++) { for ($i = 1; $i <= $count; $i++) {
// items 'name' and 'table' are required $res[] = array(
$meta[] = array(
'name' => oci_field_name($this->resultSet, $i), 'name' => oci_field_name($this->resultSet, $i),
'table' => NULL, 'table' => NULL,
'fullname' => oci_field_name($this->resultSet, $i),
'nativetype'=> oci_field_type($this->resultSet, $i), 'nativetype'=> 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; return $res;
} }

View File

@@ -393,17 +393,19 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = $this->resultSet->columnCount(); $count = $this->resultSet->columnCount();
$meta = array(); $res = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required $row = @$this->resultSet->getColumnMeta($i); // intentionally @
$info = @$this->resultSet->getColumnsMeta($i); // intentionally @ if ($row === FALSE) {
if ($info === FALSE) {
throw new DibiDriverException('Driver does not support meta data.'); throw new DibiDriverException('Driver does not support meta data.');
} }
$info['nativetype'] = $info['native_type']; $res[] = array(
$meta[] = $info; 'type' => NULL,
'nativetype' => $row['native_type'],
'fullname' => $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'],
) + $row;
} }
return $meta; return $res;
} }

View File

@@ -396,18 +396,17 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
{ {
$hasTable = version_compare(PHP_VERSION , '5.2.0', '>='); $hasTable = version_compare(PHP_VERSION , '5.2.0', '>=');
$count = pg_num_fields($this->resultSet); $count = pg_num_fields($this->resultSet);
$meta = array(); $res = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
// items 'name' and 'table' are required $row = array(
$meta[] = array(
'name' => pg_field_name($this->resultSet, $i), 'name' => pg_field_name($this->resultSet, $i),
'table' => $hasTable ? pg_field_table($this->resultSet, $i) : NULL, 'table' => $hasTable ? pg_field_table($this->resultSet, $i) : NULL,
'nativetype'=> pg_field_type($this->resultSet, $i), 'nativetype'=> pg_field_type($this->resultSet, $i),
'size' => pg_field_size($this->resultSet, $i),
'prtlen' => pg_field_prtlen($this->resultSet, $i),
); );
$row['fullname'] = $row['table'] ? $row['table'] . '.' . $row['name'] : $row['name'];
$res[] = $row;
} }
return $meta; return $res;
} }
@@ -434,7 +433,14 @@ class DibiPostgreDriver extends DibiObject implements IDibiDriver
*/ */
public function getTables() public function getTables()
{ {
throw new NotImplementedException; $this->query("
SELECT table_name as name, CAST(table_type = 'VIEW' AS INTEGER) as view
FROM information_schema.tables
WHERE table_schema = current_schema()
");
$res = pg_fetch_all($this->resultSet);
$this->free();
return $res;
} }

View File

@@ -361,18 +361,17 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
public function getColumnsMeta() public function getColumnsMeta()
{ {
$count = sqlite_num_fields($this->resultSet); $count = sqlite_num_fields($this->resultSet);
$meta = array(); $res = array();
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
$pair = explode('.', str_replace(array('[', ']'), '', sqlite_field_name($this->resultSet, $i))); $name = str_replace(array('[', ']'), '', sqlite_field_name($this->resultSet, $i));
if (!isset($pair[1])) { $pair = explode('.', $name);
array_unshift($pair, NULL); $res[] = array(
} 'name' => isset($pair[1]) ? $pair[1] : $pair[0],
$meta[] = array( 'table' => isset($pair[1]) ? $pair[0] : NULL,
'name' => $pair[1], 'fullname' => $name,
'table' => $pair[0],
); );
} }
return $meta; return $res;
} }
@@ -400,10 +399,14 @@ class DibiSqliteDriver extends DibiObject implements IDibiDriver
public function getTables() public function getTables()
{ {
$this->query(" $this->query("
SELECT name FROM sqlite_master WHERE type='table' SELECT name, type = 'view' as view FROM sqlite_master WHERE type IN ('table', 'view')
UNION ALL SELECT name FROM sqlite_temp_master WHERE type='table' ORDER BY name UNION ALL
SELECT name, type = 'view' as view FROM sqlite_temp_master WHERE type IN ('table', 'view')
ORDER BY name
"); ");
return sqlite_fetch_all($this->resultSet, SQLITE_ASSOC); $res = sqlite_fetch_all($this->resultSet, SQLITE_ASSOC);
$this->free();
return $res;
} }

View File

@@ -65,7 +65,7 @@ class DibiDataSource extends DibiObject implements IDataSource
* @param array columns * @param array columns
* @return ArrayIterator * @return ArrayIterator
*/ */
public function getIterator($offset = NULL, $limit = NULL, $cols = NULL) public function getIterator($offset = NULL, $limit = NULL)
{ {
return $this->connection->query(' return $this->connection->query('
SELECT * SELECT *

View File

@@ -111,16 +111,6 @@ class DibiDatabaseInfo extends DibiObject
/**
* @return array
*/
public function getSequences()
{
throw new NotImplementedException;
}
/** /**
* @return void * @return void
*/ */
@@ -289,7 +279,7 @@ class DibiTableInfo extends DibiObject
{ {
if ($this->columns === NULL) { if ($this->columns === NULL) {
$this->columns = array(); $this->columns = array();
foreach ($this->driver->getColumns($this->name) as $info) { foreach ($this->driver->getColumns($this->info['name']) as $info) {
$this->columns[strtolower($info['name'])] = new DibiColumnInfo($this->driver, $info); $this->columns[strtolower($info['name'])] = new DibiColumnInfo($this->driver, $info);
} }
} }
@@ -305,15 +295,13 @@ 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->name) as $info) { foreach ($this->driver->getIndexes($this->info['name']) as $info) {
$cols = array(); foreach ($info['columns'] as $key => $name) {
foreach ($info['columns'] as $name) { $info['columns'][$key] = $this->columns[strtolower($name)];
$cols[] = $this->columns[strtolower($name)];
} }
$name = $info['name']; $this->indexes[strtolower($info['name'])] = new DibiIndexInfo($info);
$this->indexes[strtolower($name)] = new DibiIndexInfo($this, $name, $cols, $info['unique']);
if (!empty($info['primary'])) { if (!empty($info['primary'])) {
$this->primaryKey = $this->indexes[strtolower($name)]; $this->primaryKey = $this->indexes[strtolower($info['name'])];
} }
} }
} }
@@ -343,7 +331,7 @@ class DibiColumnInfo extends DibiObject
/** @var IDibiDriver */ /** @var IDibiDriver */
private $driver; private $driver;
/** @var array (name, table, type, nativetype, size, precision, scale, nullable, default, autoincrement) */ /** @var array (name, table, fullname, type, nativetype, size, nullable, default, autoincrement) */
private $info; private $info;
@@ -366,6 +354,16 @@ class DibiColumnInfo extends DibiObject
/**
* @return bool
*/
public function hasTable()
{
return !empty($this->info['table']);
}
/** /**
* @return DibiTableInfo * @return DibiTableInfo
*/ */
@@ -409,26 +407,6 @@ class DibiColumnInfo extends DibiObject
/**
* @return int
*/
public function getPrecision()
{
return isset($this->info['precision']) ? (int) $this->info['precision'] : NULL;
}
/**
* @return int
*/
public function getScale()
{
return isset($this->info['scale']) ? (int) $this->info['scale'] : NULL;
}
/** /**
* @return bool * @return bool
*/ */
@@ -452,11 +430,22 @@ class DibiColumnInfo extends DibiObject
/** /**
* @return mixed * @return mixed
*/ */
public function getDefaultValue() public function getDefault()
{ {
return isset($this->info['default']) ? $this->info['default'] : NULL; return isset($this->info['default']) ? $this->info['default'] : NULL;
} }
/**
* @param string
* @return mixed
*/
public function getInfo($key)
{
return isset($this->info[$key]) ? $this->info[$key] : NULL;
}
} }
@@ -513,22 +502,13 @@ class DibiForeignKeyInfo extends DibiObject
*/ */
class DibiIndexInfo extends DibiObject class DibiIndexInfo extends DibiObject
{ {
/** @var string */ /** @var array (name, columns, unique, primary) */
private $name; private $info;
/** @var array of DibiColumnInfo */
private $columns;
/** @var bool */
private $unique;
public function __construct(array $info)
public function __construct($name, array $columns, $unique)
{ {
$this->name = $name; $this->info = $info;
$this->columns = $columns;
$this->unique = (bool) $unique;
} }
@@ -538,7 +518,7 @@ class DibiIndexInfo extends DibiObject
*/ */
public function getName() public function getName()
{ {
return $this->name; return $this->info['name'];
} }
@@ -548,7 +528,7 @@ class DibiIndexInfo extends DibiObject
*/ */
public function getColumns() public function getColumns()
{ {
return $this->columns; return $this->info['columns'];
} }
@@ -558,7 +538,18 @@ class DibiIndexInfo extends DibiObject
*/ */
public function isUnique() public function isUnique()
{ {
return $this->unique; return !empty($this->info['unique']);
}
/**
* @return bool
*/
public function isPrimary()
{
return !empty($this->info['primary']);
} }
} }

View File

@@ -216,7 +216,7 @@ class DibiFluent extends DibiObject
* @param string flag name * @param string flag name
* @return bool * @return bool
*/ */
final public function getFlag($flag, $value = TRUE) final public function getFlag($flag)
{ {
return isset($this->flags[strtoupper($flag)]); return isset($this->flags[strtoupper($flag)]);
} }

View File

@@ -124,7 +124,7 @@ abstract class DibiObject
} }
} }
} }
return; return NULL;
} }
} }
@@ -173,7 +173,7 @@ abstract class DibiObject
self::$extMethods[$pair[1]][''] = NULL; self::$extMethods[$pair[1]][''] = NULL;
} }
} }
if ($name === NULL) return; if ($name === NULL) return NULL;
} }
$name = strtolower($name); $name = strtolower($name);
@@ -189,7 +189,7 @@ abstract class DibiObject
if ($callback !== NULL) { // works as setter if ($callback !== NULL) { // works as setter
$l[$class] = $callback; $l[$class] = $callback;
$l[''] = NULL; $l[''] = NULL;
return; return NULL;
} }
// works as getter // works as getter

View File

@@ -169,9 +169,8 @@ class DibiResult extends DibiObject implements IDataSource
} }
$cols = array(); $cols = array();
foreach ($this->metaCache as $col) { foreach ($this->metaCache as $info) {
// intentional == $name = $info['fullname'];
$name = $col['table'] == '' ? $col['name'] : ($col['table'] . '.' . $col['name']);
if (isset($cols[$name])) { if (isset($cols[$name])) {
$fix = 1; $fix = 1;
while (isset($cols[$name . '#' . $fix])) $fix++; while (isset($cols[$name . '#' . $fix])) $fix++;
@@ -539,7 +538,7 @@ class DibiResult extends DibiObject implements IDataSource
} }
$cols = array(); $cols = array();
foreach ($this->metaCache as $info) { foreach ($this->metaCache as $info) {
$cols[] = (!$withTables || $info['table'] === NULL) ? $info['name'] : ($info['table'] . '.' . $info['name']); $cols[] = $info[$withTables ? 'fullname' : 'name'];
} }
return $cols; return $cols;
} }

View File

@@ -147,9 +147,7 @@ abstract class DibiTable extends DibiObject
'INSERT INTO %n', $this->name, '%v', $this->prepare($data) 'INSERT INTO %n', $this->name, '%v', $this->prepare($data)
); );
if ($this->primaryAutoIncrement) { return $this->primaryAutoIncrement ? $this->connection->insertId() : NULL;
return $this->connection->insertId();
}
} }

View File

@@ -250,7 +250,7 @@ final class DibiTranslator extends DibiObject
case 'by': // key ASC, key DESC case 'by': // key ASC, key DESC
foreach ($value as $k => $v) { foreach ($value as $k => $v) {
if (is_string($k)) { if (is_string($k)) {
$v = (is_string($v) && strcasecmp($v, 'desc')) || $v > 0 ? 'ASC' : 'DESC'; $v = (is_string($v) && strncasecmp($v, 'd', 1)) || $v > 0 ? 'ASC' : 'DESC';
$vx[] = $this->delimite($k) . ' ' . $v; $vx[] = $this->delimite($k) . ' ' . $v;
} else { } else {
$vx[] = $this->delimite($v); $vx[] = $this->delimite($v);