mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-22 21:34:28 +02:00
DbRepository: Add support for join probabilities
Finally solves the issue with those nasty column prefixes..
This commit is contained in:
parent
7482a34b45
commit
b8ae738f7f
@ -49,6 +49,25 @@ abstract class DbRepository extends Repository implements Extensible, Updatable,
|
|||||||
*/
|
*/
|
||||||
protected $tableAliases;
|
protected $tableAliases;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The join probability rules
|
||||||
|
*
|
||||||
|
* This may be initialized by repositories which make use of the table join capability. It allows to define
|
||||||
|
* probability rules to enhance control how ambiguous column aliases are associated with the correct table.
|
||||||
|
* To define a rule use the name of a base table as key and another array of table names as probable join
|
||||||
|
* targets ordered by priority. (Ascending: Lower means higher priority)
|
||||||
|
* <code>
|
||||||
|
* array(
|
||||||
|
* 'table_name' => array('target1', 'target2', 'target3')
|
||||||
|
* )
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @todo Support for tree-ish rules
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $joinProbabilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The statement columns being provided
|
* The statement columns being provided
|
||||||
*
|
*
|
||||||
@ -168,6 +187,32 @@ abstract class DbRepository extends Repository implements Extensible, Updatable,
|
|||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the join probability rules
|
||||||
|
*
|
||||||
|
* Calls $this->initializeJoinProbabilities() in case $this->joinProbabilities is null.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getJoinProbabilities()
|
||||||
|
{
|
||||||
|
if ($this->joinProbabilities === null) {
|
||||||
|
$this->joinProbabilities = $this->initializeJoinProbabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->joinProbabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrite this in your repository implementation in case you need to initialize the join probabilities lazily
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function initializeJoinProbabilities()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove each COLLATE SQL-instruction from all given query columns
|
* Remove each COLLATE SQL-instruction from all given query columns
|
||||||
*
|
*
|
||||||
@ -513,7 +558,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable,
|
|||||||
return parent::providesValueConversion($table, $column);
|
return parent::providesValueConversion($table, $column);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($tableName = $this->findTableName($column))) {
|
if (($tableName = $this->findTableName($column, $table))) {
|
||||||
return parent::providesValueConversion($tableName, $column);
|
return parent::providesValueConversion($tableName, $column);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,7 +594,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable,
|
|||||||
if (! ($query !== null && $this->validateQueryColumnAssociation($table, $name))
|
if (! ($query !== null && $this->validateQueryColumnAssociation($table, $name))
|
||||||
&& !($query === null && $this->validateStatementColumnAssociation($table, $name))
|
&& !($query === null && $this->validateStatementColumnAssociation($table, $name))
|
||||||
) {
|
) {
|
||||||
$table = $this->findTableName($name);
|
$table = $this->findTableName($name, $table);
|
||||||
if (! $table) {
|
if (! $table) {
|
||||||
if ($query !== null) {
|
if ($query !== null) {
|
||||||
// It may be an aliased Zend_Db_Expr
|
// It may be an aliased Zend_Db_Expr
|
||||||
@ -629,7 +674,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable,
|
|||||||
$alias = parent::reassembleQueryColumnAlias($table, $column);
|
$alias = parent::reassembleQueryColumnAlias($table, $column);
|
||||||
if ($alias === null
|
if ($alias === null
|
||||||
&& !$this->validateQueryColumnAssociation($table, $column)
|
&& !$this->validateQueryColumnAssociation($table, $column)
|
||||||
&& ($tableName = $this->findTableName($column))
|
&& ($tableName = $this->findTableName($column, $table))
|
||||||
) {
|
) {
|
||||||
return parent::reassembleQueryColumnAlias($tableName, $column);
|
return parent::reassembleQueryColumnAlias($tableName, $column);
|
||||||
}
|
}
|
||||||
@ -739,7 +784,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable,
|
|||||||
|
|
||||||
if (! empty($this->caseInsensitiveColumns)) {
|
if (! empty($this->caseInsensitiveColumns)) {
|
||||||
if ($joined) {
|
if ($joined) {
|
||||||
$table = $this->findTableName($name);
|
$table = $this->findTableName($name, $table);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($column === $name) {
|
if ($column === $name) {
|
||||||
@ -898,7 +943,7 @@ abstract class DbRepository extends Repository implements Extensible, Updatable,
|
|||||||
*/
|
*/
|
||||||
public function joinColumn($name, $target, RepositoryQuery $query)
|
public function joinColumn($name, $target, RepositoryQuery $query)
|
||||||
{
|
{
|
||||||
if (! ($tableName = $this->findTableName($name))) {
|
if (! ($tableName = $this->findTableName($name, $target))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,24 +975,45 @@ abstract class DbRepository extends Repository implements Extensible, Updatable,
|
|||||||
/**
|
/**
|
||||||
* Return the table name for the given alias or column name
|
* Return the table name for the given alias or column name
|
||||||
*
|
*
|
||||||
* @param string $column
|
* @param string $column The alias or column name
|
||||||
|
* @param string $origin The base table of a SELECT query
|
||||||
*
|
*
|
||||||
* @return string|null null in case no table is found
|
* @return string|null null in case no table is found
|
||||||
*/
|
*/
|
||||||
protected function findTableName($column)
|
protected function findTableName($column, $origin)
|
||||||
{
|
{
|
||||||
|
// First, try to produce an exact match since it's faster and cheaper
|
||||||
$aliasTableMap = $this->getAliasTableMap();
|
$aliasTableMap = $this->getAliasTableMap();
|
||||||
if (isset($aliasTableMap[$column])) {
|
if (isset($aliasTableMap[$column])) {
|
||||||
return $aliasTableMap[$column];
|
$table = $aliasTableMap[$column];
|
||||||
|
} else {
|
||||||
|
$columnTableMap = $this->getColumnTableMap();
|
||||||
|
if (isset($columnTableMap[$column])) {
|
||||||
|
$table = $columnTableMap[$column];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$columnTableMap = $this->getColumnTableMap();
|
// But only return it if it's a probable join...
|
||||||
if (isset($columnTableMap[$column])) {
|
$joinProbabilities = $this->getJoinProbabilities();
|
||||||
return $columnTableMap[$column];
|
if (isset($joinProbabilities[$origin])) {
|
||||||
|
$probableJoins = $joinProbabilities[$origin];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jom): Elaborate whether it makes sense to throw ProgrammingError
|
// ...if probability can be determined
|
||||||
// instead (duplicate aliases in different tables?)
|
if (isset($table) && (empty($probableJoins) || in_array($table, $probableJoins, true))) {
|
||||||
|
return $table;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Without a proper exact match, there is only one fast and cheap way to find a suitable table..
|
||||||
|
if (! empty($probableJoins)) {
|
||||||
|
foreach ($probableJoins as $table) {
|
||||||
|
if (isset($aliasTableMap[$table . '.' . $column])) {
|
||||||
|
return $table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last chance to find a table. Though, this usually ends up with a QueryException..
|
||||||
foreach ($aliasTableMap as $prefixedAlias => $table) {
|
foreach ($aliasTableMap as $prefixedAlias => $table) {
|
||||||
if (strpos($prefixedAlias, '.') !== false) {
|
if (strpos($prefixedAlias, '.') !== false) {
|
||||||
list($_, $alias) = explode('.', $prefixedAlias, 2);
|
list($_, $alias) = explode('.', $prefixedAlias, 2);
|
||||||
|
@ -644,6 +644,11 @@ abstract class Repository implements Selectable
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach ($queryColumns as $table => $columns) {
|
foreach ($queryColumns as $table => $columns) {
|
||||||
|
foreach ($columns as $alias => $column) {
|
||||||
|
$alias = is_string($alias) ? $alias : $column;
|
||||||
|
$columns[$table . '_' . $alias] = $column;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($columns as $alias => $column) {
|
foreach ($columns as $alias => $column) {
|
||||||
if (! is_string($alias)) {
|
if (! is_string($alias)) {
|
||||||
$key = $column;
|
$key = $column;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user