Re-add missing support for index hints in XML query

This commit is contained in:
Kijin Sung 2020-12-15 22:36:55 +09:00
parent 2a5d99b2df
commit a908cd9291
3 changed files with 82 additions and 0 deletions

View file

@ -0,0 +1,14 @@
<?php
namespace Rhymix\Framework\Parsers\DBQuery;
/**
* GroupBy class.
*/
class IndexHint
{
public $target_db = array();
public $hint_type = '';
public $index_name = '';
public $table_name = '';
}

View file

@ -13,6 +13,7 @@ class Query extends VariableBase
public $name;
public $type;
public $tables = array();
public $index_hints = array();
public $columns = array();
public $conditions = array();
public $groupby = null;
@ -167,6 +168,14 @@ class Query extends VariableBase
$result .= ' FROM ' . $tables;
}
}
if (count($this->index_hints))
{
$index_hints = $this->_arrangeIndexHints($this->index_hints);
if ($index_hints !== '')
{
$result .= ' ' . $index_hints;
}
}
// Compose the WHERE clause.
if (count($this->conditions))
@ -418,6 +427,37 @@ class Query extends VariableBase
return implode('', $result);
}
/**
* Generate index hints.
*
* @param array $index_hints
* @return string
*/
protected function _arrangeIndexHints(array $index_hints): string
{
// Initialize the index list by type.
$index_list = [];
// Group each index hint by type.
foreach ($index_hints as $index_hint)
{
if (!count($index_hint->target_db) || isset($index_hint->target_db['mysql']))
{
$key = $index_hint->hint_type ?: 'USE';
$index_list[$key] = $index_list[$key] ?? [];
$index_list[$key][] = $index_hint->index_name;
}
}
// Generate a list of indexes for each group.
$result = [];
foreach ($index_list as $key => $val)
{
$result[] = sprintf('%s INDEX (%s)', $key, implode(', ', $val));
}
return implode(' ', $result);
}
/**
* Generate a WHERE clause from a list of conditions.
*

View file

@ -80,6 +80,34 @@ class DBQueryParser extends BaseParser
$query->tables[$table->alias] = $table;
}
// Load index hints.
foreach ($xml->index_hint ?: [] as $index_hint_group)
{
$index_hint_target_db = strtolower(trim($index_hint_group['for']));
if ($index_hint_target_db !== '' && $index_hint_target_db !== 'all')
{
$index_hint_target_db = explode(',', $index_hint_target_db);
$index_hint_target_db = array_combine($index_hint_target_db, array_fill(0, count($index_hint_target_db), true));
}
else
{
$index_hint_target_db = [];
}
foreach ($index_hint_group->children() ?: [] as $tag)
{
$index_hint = new DBQuery\IndexHint;
$index_hint->target_db = $index_hint_target_db;
$index_hint->hint_type = strtoupper(trim($tag['type'])) ?: 'USE';
$index_hint->index_name = trim($tag['name']) ?: '';
$index_hint->table_name = trim($tag['table']) ?: '';
if ($index_hint->index_name)
{
$query->index_hints[] = $index_hint;
}
}
}
// Load columns.
foreach ($xml->columns ? $xml->columns->children() : [] as $tag)
{