Bug #23216 » 15160_poc.diff
class.ux_t3lib_db.php (working copy) | ||
---|---|---|
// Map table / field names if needed:
|
||
$ORIG_tableName = $from_table; // Saving table names in $ORIG_from_table since $from_table is transformed beneath:
|
||
if ($tableArray = $this->map_needMapping($ORIG_tableName)) {
|
||
$this->map_remapSELECTQueryParts($select_fields,$from_table,$where_clause,$groupBy,$orderBy); // Variables passed by reference!
|
||
list($select_fields, $from_table, $where_clause, $groupBy, $orderBy) = $this->map_remapSELECTQueryParts($select_fields, $from_table, $where_clause, $groupBy, $orderBy, TRUE);
|
||
}
|
||
// Get handler key and select API:
|
||
... | ... | |
}
|
||
/**
|
||
* Creates a SELECT SQL-statement to be used with an ADOdb backend.
|
||
*
|
||
* @param array parsed parameters: array($select_fields, $from_table, $where_clause, $groupBy, $orderBy)
|
||
* @return string Full SQL query for SELECT
|
||
*/
|
||
protected function SELECTqueryFromArray(array $params) {
|
||
$params[0] = $this->_quoteFieldNames($params[0]);
|
||
$select_fields = $this->SQLparser->compileFieldList($params[0]);
|
||
$params[1] = $this->_quoteFromTables($params[1]);
|
||
$from_table = $this->SQLparser->compileFromTables($params[1]);
|
||
$where_clause = '';
|
||
if (count($params[2]) > 0) {
|
||
$params[2] = $this->_quoteWhereClause($params[2]);
|
||
$where_clause = $this->SQLparser->compileWhereClause($params[2]);
|
||
}
|
||
$groupBy = '';
|
||
if (count($params[3]) > 0) {
|
||
$params[3] = $this->_quoteGroupBy($params[3]);
|
||
$groupBy = $this->SQLparser->compileFieldList($params[3]);
|
||
}
|
||
$orderBy = '';
|
||
if (count($params[4]) > 0) {
|
||
$params[4] = $this->_quoteOrderBy($params[4]);
|
||
$orderBy = $this->SQLparser->compileFieldList($params[4]);
|
||
}
|
||
// Call parent method to build actual query
|
||
$query = parent::SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
|
||
if ($this->debugOutput || $this->store_lastBuiltQuery) {
|
||
$this->debug_lastBuiltQuery = $query;
|
||
}
|
||
return $query;
|
||
}
|
||
/**
|
||
* Creates a TRUNCATE TABLE SQL-statement
|
||
*
|
||
* @param string See exec_TRUNCATEquery()
|
||
... | ... | |
}
|
||
/**
|
||
* Quotes field names in a SQL GROUP BY clause acccording to DB rules
|
||
* Quotes the field (and table) names within a group by clause with the quote
|
||
* character suitable for the DB being used
|
||
*
|
||
* @param array $groupBy The parsed GROUP BY clause to quote
|
||
* @return array
|
||
* @see quoteGroupBy()
|
||
* @param string A group by clause that can by parsed by parseFieldList
|
||
* @return string Usable group by clause with quoted field/table names
|
||
*/
|
||
protected function quoteGroupBy($groupBy) {
|
||
if ($groupBy === '') return '';
|
||
if ($this->runningNative()) return $groupBy;
|
||
$groupBy = $this->SQLparser->parseFieldList($groupBy);
|
||
$groupBy = $this->_quoteGroupBy($groupBy);
|
||
return $this->SQLparser->compileFieldList($groupBy);
|
||
}
|
||
/**
|
||
* Quotes field names in a SQL GROUP BY clause acccording to DB rules
|
||
*
|
||
* @param array $groupBy The parsed GROUP BY clause to quote
|
||
* @return array
|
||
* @see quoteGroupBy()
|
||
*/
|
||
protected function _quoteGroupBy(array $groupBy) {
|
||
foreach ($groupBy as $k => $v) {
|
||
$groupBy[$k]['field'] = $this->quoteName($groupBy[$k]['field']);
|
||
if ($groupBy[$k]['table'] != '') {
|
||
$groupBy[$k]['table'] = $this->quoteName($groupBy[$k]['table']);
|
||
}
|
||
}
|
||
return $this->SQLparser->compileFieldList($groupBy);
|
||
return $groupBy;
|
||
}
|
||
/**
|
||
... | ... | |
if ($this->runningNative()) return $orderBy;
|
||
$orderBy = $this->SQLparser->parseFieldList($orderBy);
|
||
$orderBy = $this->_quoteOrderBy($orderBy);
|
||
return $this->SQLparser->compileFieldList($orderBy);
|
||
}
|
||
/**
|
||
* Quotes field names in a SQL ORDER BY clause acccording to DB rules
|
||
*
|
||
* @param array $orderBy The parsed ORDER BY clause to quote
|
||
* @return array
|
||
* @see quoteOrderBy()
|
||
*/
|
||
protected function _quoteOrderBy(array $orderBy) {
|
||
foreach ($orderBy as $k => $v) {
|
||
$orderBy[$k]['field'] = $this->quoteName($orderBy[$k]['field']);
|
||
if ($orderBy[$k]['table'] != '') {
|
||
$orderBy[$k]['table'] = $this->quoteName($orderBy[$k]['table']);
|
||
}
|
||
}
|
||
return $this->SQLparser->compileFieldList($orderBy);
|
||
return $orderBy;
|
||
}
|
||
/**************************************
|
||
*
|
||
* Various helper functions
|
||
... | ... | |
* @return void
|
||
* @see exec_SELECTquery()
|
||
*/
|
||
protected function map_remapSELECTQueryParts(&$select_fields, &$from_table, &$where_clause, &$groupBy, &$orderBy) {
|
||
protected function map_remapSELECTQueryParts(&$select_fields, &$from_table, &$where_clause, &$groupBy, &$orderBy, $rawOutput = FALSE) {
|
||
// Backup current mapping as it may be altered if aliases on mapped tables are found
|
||
$backupMapping = $this->mapping;
|
||
... | ... | |
}
|
||
}
|
||
}
|
||
$from_table = $this->SQLparser->compileFromTables($tables);
|
||
$rawFromTable = $tables;
|
||
if (!$rawOutput) $from_table = $this->SQLparser->compileFromTables($tables);
|
||
// Where clause:
|
||
$whereParts = $this->SQLparser->parseWhereClause($where_clause);
|
||
$this->map_sqlParts($whereParts,$defaultTable);
|
||
$where_clause = $this->SQLparser->compileWhereClause($whereParts, FALSE);
|
||
$rawWhereClause = $whereParts;
|
||
if (!$rawOutput) $where_clause = $this->SQLparser->compileWhereClause($whereParts, FALSE);
|
||
// Select fields:
|
||
$expFields = $this->SQLparser->parseFieldList($select_fields);
|
||
$this->map_sqlParts($expFields,$defaultTable);
|
||
$select_fields = $this->SQLparser->compileFieldList($expFields, FALSE, FALSE);
|
||
$rawSelectFields = $expFields;
|
||
if (!$rawOutput) $select_fields = $this->SQLparser->compileFieldList($expFields, FALSE, FALSE);
|
||
// Group By fields
|
||
$expFields = $this->SQLparser->parseFieldList($groupBy);
|
||
$this->map_sqlParts($expFields,$defaultTable);
|
||
$groupBy = $this->SQLparser->compileFieldList($expFields);
|
||
$rawGroupBy = $expFields;
|
||
if (!$rawOutput) $groupBy = $this->SQLparser->compileFieldList($expFields);
|
||
// Order By fields
|
||
$expFields = $this->SQLparser->parseFieldList($orderBy);
|
||
$this->map_sqlParts($expFields,$defaultTable);
|
||
$orderBy = $this->SQLparser->compileFieldList($expFields);
|
||
$rawOrderBy = $expFields;
|
||
if (!$rawOutput) $orderBy = $this->SQLparser->compileFieldList($expFields);
|
||
// Restore the original mapping
|
||
$this->mapping = $backupMapping;
|
||
return array($rawSelectFields, $rawFromTable, $rawWhereClause, $rawGroupBy, $rawOrderBy);
|
||
}
|
||
/**
|
tests/dbOracleTest.php (working copy) | ||
---|---|---|
/**
|
||
* @test
|
||
* @see http://bugs.typo3.org/view.php?id=15160
|
||
*/
|
||
public function optimizedExecSelectIsQuicker() {
|
||
$loops = 500;
|
||
// Optimized query preparation
|
||
$time_start = t3lib_div::milliseconds();
|
||
for ($i = 0; $i < $loops; $i++) {
|
||
$selectFields = 'foo.uid';
|
||
$fromTables = 'tt_news AS foo INNER JOIN tt_news_cat_mm ON tt_news_cat_mm.uid_local = foo.uid';
|
||
$whereClause = 'tt_news_cat_mm.uid_foreign IN (SELECT foo.uid FROM tt_news_cat AS foo WHERE foo.hidden = 0)';
|
||
$groupBy = '';
|
||
$orderBy = 'foo.uid';
|
||
$rawOutput = TRUE;
|
||
$remappedParameters = $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy, $rawOutput);
|
||
$queryOptimized = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
|
||
}
|
||
$time_end = t3lib_div::milliseconds();
|
||
$timeOptimized = $time_end - $time_start;
|
||
// Normal query preparation
|
||
$time_start = t3lib_div::milliseconds();
|
||
for ($i = 0; $i < $loops; $i++) {
|
||
$selectFields = 'foo.uid';
|
||
$fromTables = 'tt_news AS foo INNER JOIN tt_news_cat_mm ON tt_news_cat_mm.uid_local = foo.uid';
|
||
$whereClause = 'tt_news_cat_mm.uid_foreign IN (SELECT foo.uid FROM tt_news_cat AS foo WHERE foo.hidden = 0)';
|
||
$groupBy = '';
|
||
$orderBy = 'foo.uid';
|
||
$GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
|
||
$queryNormal = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
|
||
}
|
||
$time_end = t3lib_div::milliseconds();
|
||
$timeNormal = $time_end - $time_start;
|
||
$this->assertEquals($queryNormal, $queryOptimized);
|
||
$this->assertTrue($timeOptimized < $timeNormal, 'Optimized way was slower than normal way');
|
||
$gain = $timeOptimized * 100 / $timeNormal;
|
||
t3lib_div::debug('Optimized run in ' . $gain . '% of time of Normal for ' . $loops . ' loops', 'Gain');
|
||
}
|
||
/**
|
||
* @test
|
||
* @see http://bugs.typo3.org/view.php?id=12758
|
||
*/
|
||
public function existsWhereClauseIsProperlyQuoted() {
|