Project

General

Profile

Bug #23216 » 15160_poc.diff

Administrator Admin, 2010-07-17 12:53

View differences:

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() {
(1-1/2)