diff --git a/typo3/sysext/core/Classes/Database/DatabaseConnection.php b/typo3/sysext/core/Classes/Database/DatabaseConnection.php index 8bcfb42b0beeb6e175853e60b66501a6c3456dcb..0ec7fe69c3db3f35d06723e4dceb0b4b2d4ed679 100644 --- a/typo3/sysext/core/Classes/Database/DatabaseConnection.php +++ b/typo3/sysext/core/Classes/Database/DatabaseConnection.php @@ -727,8 +727,12 @@ class DatabaseConnection { */ 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); diff --git a/typo3/sysext/core/Classes/Database/PreparedStatement.php b/typo3/sysext/core/Classes/Database/PreparedStatement.php index cee3e53c654bc5bd102d979120afe4f72f760913..a38e60629a247bb6a4d1208b8678bb9990d3c4f4 100644 --- a/typo3/sysext/core/Classes/Database/PreparedStatement.php +++ b/typo3/sysext/core/Classes/Database/PreparedStatement.php @@ -127,13 +127,6 @@ class PreparedStatement { 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. * @@ -142,6 +135,12 @@ class PreparedStatement { 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 @@ -153,15 +152,19 @@ class PreparedStatement { * @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); + } } /** @@ -239,6 +242,9 @@ class PreparedStatement { 'value' => $value, 'type' => $data_type == self::PARAM_AUTOTYPE ? $this->guessValueType($value) : $data_type ); + if ($this->databaseStatementObject) { + $this->databaseStatementObject->bind_param($parameter, $value); + } return $this; } @@ -271,27 +277,15 @@ class PreparedStatement { * @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; } /** @@ -307,10 +301,13 @@ class PreparedStatement { } 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); @@ -326,7 +323,9 @@ class PreparedStatement { * @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; } /** @@ -352,7 +351,7 @@ class PreparedStatement { * @api */ public function free() { - $GLOBALS['TYPO3_DB']->sql_free_result($this->resource); + $this->databaseStatementObject->free_result(); } /** @@ -362,7 +361,8 @@ class PreparedStatement { * @api */ public function rowCount() { - return $GLOBALS['TYPO3_DB']->sql_num_rows($this->resource); + $this->databaseStatementObject->store_result(); + return $this->databaseStatementObject->num_rows; } /** @@ -372,7 +372,7 @@ class PreparedStatement { * @api */ public function errorCode() { - return $GLOBALS['TYPO3_DB']->sql_errno(); + return $this->databaseStatementObject->errno; } /** @@ -387,8 +387,8 @@ class PreparedStatement { */ public function errorInfo() { return array( - $GLOBALS['TYPO3_DB']->sql_errno(), - $GLOBALS['TYPO3_DB']->sql_error() + $this->databaseStatementObject->errno, + $this->databaseStatementObject->error ); } @@ -447,15 +447,13 @@ class PreparedStatement { 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); } @@ -474,7 +472,7 @@ class PreparedStatement { $precompiledQueryParts['queryParts'][$i] = $value; } } - $query = str_replace($this->parameterWrapToken . $key . $this->parameterWrapToken, $value, $query); + $query = str_replace($this->parameterWrapToken . $key . $this->parameterWrapToken, '?', $query); } } } diff --git a/typo3/sysext/core/Classes/Resource/FileRepository.php b/typo3/sysext/core/Classes/Resource/FileRepository.php index f1965e157f6ce7078327a3a897827ea9bddee498..787f11fcb8e5fd41b3b6c3a53e2fbdbf6c22c458 100644 --- a/typo3/sysext/core/Classes/Resource/FileRepository.php +++ b/typo3/sysext/core/Classes/Resource/FileRepository.php @@ -170,20 +170,40 @@ class FileRepository extends AbstractRepository { 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; }