Feature #27372 ยป prepared_statements_wip.patch
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;
|
||
}
|
||