Project

General

Profile

Feature #27372 ยป prepared_statements_wip.patch

Benni Mack, 2014-01-14 17:10

View differences:

typo3/sysext/core/Classes/Database/DatabaseConnection.php
*/
public function prepare_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', array $input_parameters = array()) {
$query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
/** @var $preparedStatement \TYPO3\CMS\Core\Database\PreparedStatement */
$preparedStatement = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\PreparedStatement', $query, $from_table, array());
if (!$this->isConnected) {
$this->connectDB();
}
$preparedStatement = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\PreparedStatement', $query, $from_table, array(), $this->link->stmt_init());
// Bind values to parameters
foreach ($input_parameters as $key => $value) {
$preparedStatement->bindValue($key, $value, \TYPO3\CMS\Core\Database\PreparedStatement::PARAM_AUTOTYPE);
typo3/sysext/core/Classes/Database/PreparedStatement.php
protected $defaultFetchMode = self::FETCH_ASSOC;
/**
* MySQLi result object / DBAL object
*
* @var boolean|\mysqli_result|object
*/
protected $resource;
/**
* Random token which is wrapped around the markers
* that will be replaced by user input.
*
......
protected $parameterWrapToken;
/**
* the actual MySQL statement object, can be prepared, filled with
* @var \mysqli_stmt
*/
protected $databaseStatementObject;
/**
* Creates a new PreparedStatement. Either $query or $queryComponents
* should be used. Typically $query will be used by native MySQL TYPO3_DB
* on a ready-to-be-executed query. On the other hand, DBAL will have
......
* @param string $query SQL query to be executed
* @param string $table FROM table, used to call $GLOBALS['TYPO3_DB']->fullQuoteStr().
* @param array $precompiledQueryParts Components of the query to be executed
* @param \mysqli_stmt $statementObject the mysqli_stmt object, created by the link object
* @access private
*/
public function __construct($query, $table, array $precompiledQueryParts = array()) {
public function __construct($query, $table, array $precompiledQueryParts = array(), $statementObject = NULL) {
$this->query = $query;
$this->precompiledQueryParts = $precompiledQueryParts;
$this->table = $table;
$this->parameters = array();
$this->resource = NULL;
$this->parameterWrapToken = $this->generateParameterWrapToken();
$this->databaseStatementObject = $statementObject;
if ($this->databaseStatementObject) {
$this->databaseStatementObject->prepare($query);
}
}
/**
......
'value' => $value,
'type' => $data_type == self::PARAM_AUTOTYPE ? $this->guessValueType($value) : $data_type
);
if ($this->databaseStatementObject) {
$this->databaseStatementObject->bind_param($parameter, $value);
}
return $this;
}
......
* @api
*/
public function execute(array $input_parameters = array()) {
$query = $this->query;
$precompiledQueryParts = $this->precompiledQueryParts;
$parameterValues = $this->parameters;
if (count($input_parameters) > 0) {
$parameterValues = array();
foreach ($input_parameters as $key => $value) {
$parameterValues[$key] = array(
'value' => $value,
'type' => $this->guessValueType($value)
);
}
$this->bindValues($input_parameters);
}
$this->replaceValuesInQuery($query, $precompiledQueryParts, $parameterValues);
if (count($precompiledQueryParts) > 0) {
$query = implode('', $precompiledQueryParts['queryParts']);
}
$this->resource = $GLOBALS['TYPO3_DB']->exec_PREPAREDquery($query, $precompiledQueryParts);
// Empty binding parameters
$this->parameters = array();
$result = $this->databaseStatementObject->execute();
// Return the success flag
return $this->resource ? TRUE : FALSE;
return $result;
}
/**
......
}
switch ($fetch_style) {
case self::FETCH_ASSOC:
$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($this->resource);
$result = $this->databaseStatementObject->get_result();
$row = $result->fetch_array(MYSQLI_ASSOC);
break;
case self::FETCH_NUM:
$row = $GLOBALS['TYPO3_DB']->sql_fetch_row($this->resource);
$result = $this->databaseStatementObject->get_result();
var_dump($this);
$row = $result->fetch_array(MYSQLI_NUM);
break;
default:
throw new \InvalidArgumentException('$fetch_style must be either TYPO3\\CMS\\Core\\Database\\PreparedStatement::FETCH_ASSOC or TYPO3\\CMS\\Core\\Database\\PreparedStatement::FETCH_NUM', 1281646455);
......
* @api
*/
public function seek($rowNumber) {
return $GLOBALS['TYPO3_DB']->sql_data_seek($this->resource, intval($rowNumber));
$this->databaseStatementObject->mysqli_stmt_store_result();
$this->databaseStatementObject->data_seek(intval($rowNumber));
return TRUE;
}
/**
......
* @api
*/
public function free() {
$GLOBALS['TYPO3_DB']->sql_free_result($this->resource);
$this->databaseStatementObject->free_result();
}
/**
......
* @api
*/
public function rowCount() {
return $GLOBALS['TYPO3_DB']->sql_num_rows($this->resource);
$this->databaseStatementObject->store_result();
return $this->databaseStatementObject->num_rows;
}
/**
......
* @api
*/
public function errorCode() {
return $GLOBALS['TYPO3_DB']->sql_errno();
return $this->databaseStatementObject->errno;
}
/**
......
*/
public function errorInfo() {
return array(
$GLOBALS['TYPO3_DB']->sql_errno(),
$GLOBALS['TYPO3_DB']->sql_error()
$this->databaseStatementObject->errno,
$this->databaseStatementObject->error
);
}
......
case self::PARAM_NULL:
$value = 'NULL';
break;
case self::PARAM_INT:
$value = intval($typeValue['value']);
break;
case self::PARAM_STR:
$value = $GLOBALS['TYPO3_DB']->fullQuoteStr($typeValue['value'], $this->table);
break;
case self::PARAM_BOOL:
$value = $typeValue['value'] ? 1 : 0;
break;
case self::PARAM_INT:
case self::PARAM_STR:
$value = $typeValue['value'];
break;
default:
throw new \InvalidArgumentException(sprintf('Unknown type %s used for parameter %s.', $typeValue['type'], $key), 1281859196);
}
......
$precompiledQueryParts['queryParts'][$i] = $value;
}
}
$query = str_replace($this->parameterWrapToken . $key . $this->parameterWrapToken, $value, $query);
$query = str_replace($this->parameterWrapToken . $key . $this->parameterWrapToken, '?', $query);
}
}
}
typo3/sysext/core/Classes/Resource/FileRepository.php
if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($uid)) {
throw new \InvalidArgumentException('Uid of related record has to be an integer.', 1316789798);
}
$references = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
'*',
'sys_file_reference',
'tablenames=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($tableName, 'sys_file_reference') .
' AND deleted = 0' .
' AND hidden = 0' .
' AND uid_foreign=' . intval($uid) .
' AND fieldname=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($fieldName, 'sys_file_reference'),
'',
'sorting_foreign'
// create the prepared statement
if (!self::$findByRelationSqlStatement) {
self::$findByRelationSqlStatement = $GLOBALS['TYPO3_DB']->prepare_SELECTquery(
'*',
'sys_file_reference',
'tablenames= :relationtable ' .
' AND deleted=0' .
' AND hidden=0' .
' AND uid_foreign= :relationuid' .
' AND fieldname= :relationfield',
'',
'sorting_foreign'
);
}
$result = self::$findByRelationSqlStatement->execute(
array(
':relationtable' => $tableName,
':relationuid' => $uid,
':relationfield:' => $fieldName
)
);
$references = $result->fetchAll(\TYPO3\CMS\Core\Database\PreparedStatement::FETCH_ASSOC);
foreach ($references as $referenceRecord) {
$itemList[] = $this->createFileReferenceObject($referenceRecord);
}
$result->free();
return $itemList;
}
    (1-1/1)