No subject
Fri Mar 12 13:03:17 CET 2010
- get rid of "is_numeric" and use is_int when possible.
- cast with intval() when the parameter is supposed to be an integer
- added a $stmt->seek() because I use it some times. Strange thing that
PDO doesn't support it.
- enhanced some comments and error messages.
+1 on reading, reviewing and testing.
Cheers,
Ernesto
Xavier Perseguers schrieb am 16.08.2010 22:21:
> Please find v3 attached.
>
> We had kind of a live discussion with other core devs this morning and
> here is the summary:
>
> - "Old way" of creating queries ($GLOBALS['TYPO3_DB']->exec_* methods
> will still work as before. Only if you explicitly call the
> prepare_SELECTquery method will you gain access to enhanced DB API
>
> - We want to provide a PDO-like syntax but we don't aim at having a
> PDO-compatible implementation. We can provide enhancements and we should
> not fear having some goodies. We want to learn from Extbase (this is why
> I added some chaining feature for instance)
>
> What as changed basically with this new version:
>
> - Took comments into account
> - Enhanced the documentation with some examples which render properly
> when compiling documentation with doxygen or phpdoc
> - Removed bindParam() method (borrowed from PDO) because we do not like
> this way of programming and it hardly make sense in TYPO3. In PDO it is
> used mainly for getting back parameters. We do not have that in TYPO3.
> - Added bindValues() which takes an array of parameters. A complement to
> the bindValue() method which acts as the parameter you may pass to
> execute() but with a potentially clearer separation.
> - Added chaining on both bindValue() and bindValues()
>
> Sorry. Did not have time to provide unit tests.
>
> Cheers
> Xavier
>
--------------070602040709090700030606
Content-Type: text/plain;
name="15457_core_v4.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="15457_core_v4.diff"
Index: t3lib/class.t3lib_sqlparser.php
===================================================================
--- t3lib/class.t3lib_sqlparser.php (Revision 8607)
+++ t3lib/class.t3lib_sqlparser.php (Arbeitskopie)
@@ -190,10 +190,11 @@
* Parsing SELECT query
*
* @param string SQL string with SELECT query to parse
+ * @param array Array holding references to either named (:name) or question mark (?) parameters found
* @return mixed Returns array with components of SELECT query on success, otherwise an error message string.
* @see compileSELECT()
*/
- protected function parseSELECT($parseString) {
+ protected function parseSELECT($parseString, &$parameterReferences = NULL) {
// Removing SELECT:
$parseString = $this->trimSQL($parseString);
@@ -201,6 +202,10 @@
// Init output variable:
$result = array();
+ if ($parameterReferences === NULL) {
+ $result['parameters'] = array();
+ $parameterReferences = &$result['parameters'];
+ }
$result['type'] = 'SELECT';
// Looking for STRAIGHT_JOIN keyword:
@@ -221,7 +226,7 @@
if ($parseString) {
// Get WHERE clause:
- $result['WHERE'] = $this->parseWhereClause($parseString, '^(GROUP[[:space:]]+BY|ORDER[[:space:]]+BY|LIMIT)[[:space:]]+');
+ $result['WHERE'] = $this->parseWhereClause($parseString, '^(GROUP[[:space:]]+BY|ORDER[[:space:]]+BY|LIMIT)[[:space:]]+', $parameterReferences);
if ($this->parse_error) { return $this->parse_error; }
// If the WHERE clause parsing was stopped by GROUP BY, ORDER BY or LIMIT, then proceed with parsing:
@@ -1025,9 +1030,10 @@
*
* @param string WHERE clause to parse. NOTICE: passed by reference!
* @param string Regular expressing to STOP parsing, eg. '^(GROUP BY|ORDER BY|LIMIT)([[:space:]]*)'
+ * @param array Array holding references to either named (:name) or question mark (?) parameters found
* @return mixed If successful parsing, returns an array, otherwise an error string.
*/
- public function parseWhereClause(&$parseString, $stopRegex = '') {
+ public function parseWhereClause(&$parseString, $stopRegex = '', array &$parameterReferences = array()) {
// Prepare variables:
$parseString = $this->trimSQL($parseString);
@@ -1057,7 +1063,7 @@
if (preg_match('/^EXISTS[[:space:]]*[(]/i', $parseString)) {
$stack[$level][$pnt[$level]]['func']['type'] = $this->nextPart($parseString, '^(EXISTS)[[:space:]]*');
$parseString = trim(substr($parseString, 1)); // Strip of "("
- $stack[$level][$pnt[$level]]['func']['subquery'] = $this->parseSELECT($parseString);
+ $stack[$level][$pnt[$level]]['func']['subquery'] = $this->parseSELECT($parseString, $parameterReferences);
// Seek to new position in parseString after parsing of the subquery
$parseString = $stack[$level][$pnt[$level]]['func']['subquery']['parseString'];
unset($stack[$level][$pnt[$level]]['func']['subquery']['parseString']);
@@ -1225,7 +1231,7 @@
$stack[$level][$pnt[$level]]['value'] = $values;
} else if (t3lib_div::inList('IN,NOT IN', $stack[$level][$pnt[$level]]['comparator']) && preg_match('/^[(][[:space:]]*SELECT[[:space:]]+/', $parseString)) {
$this->nextPart($parseString, '^([(])');
- $stack[$level][$pnt[$level]]['subquery'] = $this->parseSELECT($parseString);
+ $stack[$level][$pnt[$level]]['subquery'] = $this->parseSELECT($parseString, $parameterReferences);
// Seek to new position in parseString after parsing of the subquery
$parseString = $stack[$level][$pnt[$level]]['subquery']['parseString'];
unset($stack[$level][$pnt[$level]]['subquery']['parseString']);
@@ -1241,7 +1247,7 @@
$stack[$level][$pnt[$level]]['values'][1] = $this->getValue($parseString);
} else {
// Finding value for comparator:
- $stack[$level][$pnt[$level]]['value'] = $this->getValue($parseString, $stack[$level][$pnt[$level]]['comparator']);
+ $stack[$level][$pnt[$level]]['value'] = &$this->getValueOrParameter($parseString, $stack[$level][$pnt[$level]]['comparator'], '', $parameterReferences);
if ($this->parse_error) {
return $this->parse_error;
}
@@ -1390,6 +1396,39 @@
}
/**
+ * Finds value or either named (:name) or question mark (?) parameter markers at the beginning
+ * of $parseString, returns result and strips it of parseString.
+ * This method returns a pointer to the parameter or value that was found. In case of a parameter
+ * the pointer is a reference to the corresponding item in array $parameterReferences.
+ *
+ * @param string $parseString The parseString
+ * @param string $comparator The comparator used before.
+ * @param string $mode The mode, e.g., "INDEX"
+ * @param mixed The value (string/integer) or parameter (:name/?). Otherwise an array with error message in first key (0)
+ */
+ protected function &getValueOrParameter(&$parseString, $comparator = '', $mode = '', array &$parameterReferences = array()) {
+ $parameter = $this->nextPart($parseString, '^(\\:[[:alnum:]_]+|\\?)');
+ if ($parameter === '?') {
+ if (!isset($parameterReferences['?'])) {
+ $parameterReferences['?'] = array();
+ }
+ $value = array('?');
+ $parameterReferences['?'][] = &$value;
+ } elseif ($parameter !== '') { // named parameter
+ if (isset($parameterReferences[$parameter])) {
+ // Use the same reference as last time we encountered this parameter
+ $value = &$parameterReferences[$parameter];
+ } else {
+ $value = array($parameter);
+ $parameterReferences[$parameter] = &$value;
+ }
+ } else {
+ $value = $this->getValue($parseString, $comparator, $mode);
+ }
+ return $value;
+ }
+
+ /**
* Finds value in beginning of $parseString, returns result and strips it of parseString
*
* @param string The parseString, eg. "(0,1,2,3) ..." or "('asdf','qwer') ..." or "1234 ..." or "'My string value here' ..."
Index: t3lib/class.t3lib_db.php
===================================================================
--- t3lib/class.t3lib_db.php (Revision 8607)
+++ t3lib/class.t3lib_db.php (Arbeitskopie)
@@ -676,11 +676,84 @@
+ /**************************************
+ *
+ * Prepared Query Support
+ *
+ **************************************/
+ /**
+ * Creates a SELECT prepared SQL statement.
+ *
+ * @param string See exec_SELECTquery()
+ * @param string See exec_SELECTquery()
+ * @param string See exec_SELECTquery()
+ * @param string See exec_SELECTquery()
+ * @param string See exec_SELECTquery()
+ * @param string See exec_SELECTquery()
+ * @param array $input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as t3lib_db_PreparedStatement::PARAM_AUTOTYPE.
+ * @return t3lib_db_PreparedStatement Prepared statement
+ */
+ 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);
+ $preparedStatement = t3lib_div::makeInstance('t3lib_db_PreparedStatement', $query, $from_table, array());
+ /* @var $preparedStatement t3lib_db_PreparedStatement */
+ // Bind values to parameters
+ foreach ($input_parameters as $key => $value) {
+ $preparedStatement->bindValue($key, $value, t3lib_db_PreparedStatement::PARAM_AUTOTYPE);
+ }
+ // Return prepared statement
+ return $preparedStatement;
+ }
+ /**
+ * Creates a SELECT prepared SQL statement based on input query parts array
+ *
+ * @param array Query parts array
+ * @param array $input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as t3lib_db_PreparedStatement::PARAM_AUTOTYPE.
+ * @return t3lib_db_PreparedStatement Prepared statement
+ */
+ public function prepare_SELECTqueryArray(array $queryParts, array $input_parameters = array()) {
+ return $this->prepare_SELECTquery(
+ $queryParts['SELECT'],
+ $queryParts['FROM'],
+ $queryParts['WHERE'],
+ $queryParts['GROUPBY'],
+ $queryParts['ORDERBY'],
+ $queryParts['LIMIT'],
+ $input_parameters
+ );
+ }
+ /**
+ * Executes a prepared query.
+ * This method may only be called by t3lib_db_PreparedStatement.
+ *
+ * @param string $query The query to execute
+ * @param array $queryComponents The components of the query to execute
+ * @return pointer MySQL result pointer / DBAL object
+ * @access private
+ */
+ public function exec_PREPAREDquery($query, array $queryComponents) {
+ $res = mysql_query($query, $this->link);
+ if ($this->debugOutput) {
+ $this->debug('stmt_execute', $query);
+ }
+ return $res;
+ }
+
+
+
+
+
+
+
+
+
+
+
/**************************************
*
* Various helper functions
Index: t3lib/db/class.t3lib_db_PreparedStatement.php
===================================================================
--- t3lib/db/class.t3lib_db_PreparedStatement.php (Revision 0)
+++ t3lib/db/class.t3lib_db_PreparedStatement.php (Revision 0)
@@ -0,0 +1,459 @@
+<?php
+/***************************************************************
+* Copyright notice
+*
+* (c) 2010 Xavier Perseguers <typo3 at perseguers.ch>
+* All rights reserved
+*
+* This script is part of the TYPO3 project. The TYPO3 project is
+* free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* The GNU General Public License can be found at
+* http://www.gnu.org/copyleft/gpl.html.
+* A copy is found in the textfile GPL.txt and important notices to the license
+* from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+* This script is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * TYPO3 prepared statement for t3lib_db class.
+ *
+ * USE:
+ * In all TYPO3 scripts when you need to create a prepared query:
+ * <code>
+ * $statement = $GLOBALS['TYPO3_DB']->prepare_SELECTquery('*', 'pages', 'uid = :uid');
+ * $statement->execute(array(':uid' => 2));
+ * while (($row = $statement->fetch()) !== FALSE) {
+ * // ...
+ * }
+ * $statement->free();
+ * </code>
+ *
+ * @author Xavier Perseguers <typo3 at perseguers.ch>
+ * @package TYPO3
+ * @subpackage t3lib
+ */
+class t3lib_db_PreparedStatement {
+
+ /**
+ * Represents the SQL NULL data type.
+ * @var integer
+ */
+ const PARAM_NULL = 0;
+
+ /**
+ * Represents the SQL INTEGER data type.
+ * @var integer
+ */
+ const PARAM_INT = 1;
+
+ /**
+ * Represents the SQL CHAR, VARCHAR, or other string data type.
+ * @var integer
+ */
+ const PARAM_STR = 2;
+
+ /**
+ * Represents a boolean data type.
+ * @var integer
+ */
+ const PARAM_BOOL = 3;
+
+ /**
+ * Automatically detects underlying type
+ * @var integer
+ */
+ const PARAM_AUTOTYPE = 4;
+
+ /**
+ * Specifies that the fetch method shall return each row as an array indexed by
+ * column name as returned in the corresponding result set. If the result set
+ * contains multiple columns with the same name, t3lib_db_PreparedStatement::FETCH_ASSOC
+ * returns only a single value per column name.
+ * @var integer
+ */
+ const FETCH_ASSOC = 2;
+
+ /**
+ * Specifies that the fetch method shall return each row as an array indexed by
+ * column number as returned in the corresponding result set, starting at column 0.
+ * @var integer
+ */
+ const FETCH_NUM = 3;
+
+ /**
+ * Query to be executed.
+ * @var string
+ */
+ protected $query;
+
+ /**
+ * Components of the query to be executed.
+ * @var array
+ */
+ protected $precompiledQueryParts;
+
+ /**
+ * Table (used to call $GLOBALS['TYPO3_DB']->fullQuoteStr().
+ * @var string
+ */
+ protected $table;
+
+ /**
+ * Binding parameters.
+ * @var array
+ */
+ protected $parameters;
+
+ /**
+ * Default fetch mode.
+ * @var integer
+ */
+ protected $defaultFetchMode = self::FETCH_ASSOC;
+
+ /**
+ * MySQL result pointer (of SELECT query) / DBAL object.
+ * @var pointer
+ */
+ protected $resource;
+
+ /**
+ * 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
+ * parse the query and will be able to safely know where parameters are used
+ * and will use $queryComponents instead.
+ * This constructor may only be used by t3lib_DB.
+ *
+ * @param string $query SQL query to be executed
+ * @param string FROM table, used to call $GLOBALS['TYPO3_DB']->fullQuoteStr().
+ * @param array $precompiledQueryParts Components of the query to be executed
+ * @access private
+ */
+ public function __construct($query, $table, array $precompiledQueryParts = array()) {
+ $this->query = $query;
+ $this->precompiledQueryParts = $precompiledQueryParts;
+ $this->table = $table;
+ $this->parameters = array();
+ $this->resource = NULL;
+ }
+
+ /**
+ * Binds an array of values to corresponding named or question mark placeholders in the SQL
+ * statement that was use to prepare the statement.
+ *
+ * Example 1:
+ * <code>
+ * $statement = $GLOBALS['TYPO3_DB']->prepare_SELECTquery('*', 'bugs', 'reported_by = ? AND bug_status = ?');
+ * $statement->bindValues(array('goofy', 'FIXED'));
+ * </code>
+ *
+ * Example 2:
+ * <code>
+ * $statement = $GLOBALS['TYPO3_DB']->prepare_SELECTquery('*', 'bugs', 'reported_by = :nickname AND bug_status = :status');
+ * $statement->bindValues(array(':nickname' => 'goofy', ':status' => 'FIXED'));
+ * </code>
+ *
+ * @param array $values The values to bind to the parameter. Data type will be set to t3lib_db_PreparedStatement::PARAM_AUTOTYPE.
+ * @return t3lib_db_PreparedStatement The current prepared statement to allow method chaining
+ * @api
+ */
+ public function bindValues(array $values) {
+ foreach ($values as $parameter => $value) {
+ $key = is_int($parameter) ? $parameter + 1 : $parameter;
+ $this->bindValue($key, $value, self::PARAM_AUTOTYPE);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Binds a value to a corresponding named or question mark placeholder in the SQL
+ * statement that was use to prepare the statement.
+ *
+ * Example 1:
+ * <code>
+ * $statement = $GLOBALS['TYPO3_DB']->prepare_SELECTquery('*', 'bugs', 'reported_by = ? AND bug_status = ?');
+ * $statement->bindValue(1, 'goofy');
+ * $statement->bindValue(2, 'FIXED');
+ * </code>
+ *
+ * Example 2:
+ * <code>
+ * $statement = $GLOBALS['TYPO3_DB']->prepare_SELECTquery('*', 'bugs', 'reported_by = :nickname AND bug_status = :status');
+ * $statement->bindValue(':nickname', 'goofy');
+ * $statement->bindValue(':status', 'FIXED');
+ * </code>
+ *
+ * @param mixed $parameter Parameter identifier. For a prepared statement using named placeholders, this will be a parameter name of the form :name. For a prepared statement using question mark placeholders, this will be the 1-indexed position of the parameter.
+ * @param mixed $value The value to bind to the parameter.
+ * @param integer $data_type Explicit data type for the parameter using the t3lib_db_PreparedStatement::PARAM_* constants. If not given, the PHP type of the value will be used instead (int, string, boolean)
+ * @return t3lib_db_PreparedStatement The current prepared statement to allow method chaining
+ * @api
+ */
+ public function bindValue($parameter, $value, $data_type = self::PARAM_AUTOTYPE) {
+ switch ($data_type) {
+ case self::PARAM_INT:
+ if (!is_int($value)) {
+ throw new InvalidArgumentException('$value is not an integer as expected: ' . $value, 1281868686);
+ }
+ break;
+ case self::PARAM_BOOL:
+ if (!is_bool($value)) {
+ throw new InvalidArgumentException('$value is not a boolean as expected: ' . $value, 1281868687);
+ }
+ break;
+ }
+
+ $key = is_int($parameter) ? $parameter - 1 : $parameter;
+ $this->parameters[$key] = array(
+ 'value' => $value,
+ 'type' => ($data_type == self::PARAM_AUTOTYPE ? $this->guessValueType($value) : $data_type),
+ );
+
+ return $this;
+ }
+
+ /**
+ * Executes the prepared statement. If the prepared statement included parameter
+ * markers, you must either:
+ * - call {@link t3lib_db_PreparedStatement::bindParam()} to bind PHP variables
+ * to the parameter markers: bound variables pass their value as input
+ * - or pass an array of input-only parameter values
+ *
+ * @param array $input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as t3lib_db_PreparedStatement::PARAM_AUTOTYPE.
+ * @return boolean Returns TRUE on success or FALSE on failure.
+ * @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 $value) {
+ $parameterValues[] = array(
+ 'value' => $value,
+ 'type' => $this->guessValueType($value),
+ );
+ }
+ }
+
+ $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();
+
+ // Return the success flag
+ return ($this->resource ? TRUE : FALSE);
+ }
+
+ /**
+ * Fetches a row from a result set associated with a t3lib_db_PreparedStatement object.
+ *
+ * @param integer $fetch_style Controls how the next row will be returned to the caller. This value must be one of the t3lib_db_PreparedStatement::FETCH_* constants. If omitted, default fetch mode for this prepared query will be used.
+ * @return array Array of rows or FALSE if there are no more rows.
+ * @api
+ */
+ public function fetch($fetch_style = 0) {
+ if ($fetch_style == 0) {
+ $fetch_style = $this->defaultFetchMode;
+ }
+ switch ($fetch_style) {
+ case self::FETCH_ASSOC:
+ $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($this->resource);
+ break;
+ case self::FETCH_NUM:
+ $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($this->resource);
+ break;
+ default:
+ throw new InvalidArgumentException('$fetch_style must be either t3lib_db_PreparedStatement::FETCH_ASSOC or t3lib_db_PreparedStatement::FETCH_NUM', 1281646455);
+ }
+ return $row;
+ }
+
+ /**
+ * Returns an array containing all of the result set rows.
+ *
+ * @param integer $fetch_style Controls the contents of the returned array as documented in {@link t3lib_db_PreparedStatement::fetch()}.
+ * @return array Array of rows.
+ * @api
+ */
+ public function fetchAll($fetch_style = 0) {
+ $rows = array();
+ while (($row = $this->fetch($fetch_style)) !== FALSE) {
+ $rows[] = $row;
+ }
+ return $rows;
+ }
+
+ /**
+ * Releases the cursor. Should always be call after having fetched rows from
+ * a query execution.
+ *
+ * @return void
+ * @api
+ */
+ public function free() {
+ $GLOBALS['TYPO3_DB']->sql_free_result($this->resource);
+ }
+
+ /**
+ * Returns the number of rows affected by the last SQL statement.
+ *
+ * @return integer The number of rows.
+ * @api
+ */
+ public function rowCount() {
+ return $GLOBALS['TYPO3_DB']->sql_num_rows($this->resource);
+ }
+
+ /**
+ * Move internal result pointer
+ *
+ * @param integer $rowNumber Where to place the result pointer (0 = start)
+ * @return boolean Returns TRUE on success or FALSE on failure.
+ * @api
+ */
+ public function seek($rowNumber) {
+ return $GLOBALS['TYPO3_DB']->sql_data_seek($this->resource, intval($rowNumber));
+ }
+
+
+
+ /**
+ * Returns the error number on the last execute() call.
+ *
+ * @return integer Driver specific error code.
+ * @api
+ */
+ public function errorCode() {
+ return $GLOBALS['TYPO3_DB']->sql_errno();
+ }
+
+ /**
+ * Returns an array of error information about the last operation performed by this statement handle.
+ * The array consists of the following fields:
+ * <ol start="0">
+ * <li>Driver specific error code.</li>
+ * <li>Driver specific error message</li>
+ * </ol>
+ *
+ * @return array Array of error information.
+ */
+ public function errorInfo() {
+ return array(
+ $GLOBALS['TYPO3_DB']->sql_errno(),
+ $GLOBALS['TYPO3_DB']->sql_error(),
+ );
+ }
+
+ /**
+ * Sets the default fetch mode for this prepared query.
+ *
+ * @param integer $mode One of the t3lib_db_PreparedStatement::FETCH_* constants
+ * @return void
+ * @api
+ */
+ public function setFetchMode($mode) {
+ switch ($mode) {
+ case self::FETCH_ASSOC:
+ case self::FETCH_NUM:
+ $this->defaultFetchMode = $mode;
+ break;
+ default:
+ throw new InvalidArgumentException('$mode must be either t3lib_db_PreparedStatement::FETCH_ASSOC or t3lib_db_PreparedStatement::FETCH_NUM', 1281875340);
+ }
+ }
+
+ /**
+ * Guesses the type of a given value.
+ *
+ * @param mixed $value
+ * @return integer One of the t3lib_db_PreparedStatement::PARAM_* constants
+ */
+ protected function guessValueType($value) {
+ if (is_bool($value)) {
+ $type = self::PARAM_BOOL;
+ } elseif (t3lib_div::testInt($value))) {
+ $type = self::PARAM_INT;
+ } elseif (is_null($value) || strtoupper($value) === 'NULL') {
+ $type = self::PARAM_NULL;
+ } else {
+ $type = self::PARAM_STR;
+ }
+
+ return $type;
+ }
+
+ /**
+ * Replaces values for each parameter in a query.
+ *
+ * @param string $query
+ * @param array $precompiledQueryParts
+ * @param array $parameterValues
+ * @return void
+ */
+ protected function replaceValuesInQuery(&$query, array &$precompiledQueryParts, array $parameterValues) {
+ foreach ($this->parameters as $key => $typeValue) {
+ switch ($typeValue['type']) {
+ 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;
+ default:
+ throw new InvalidArgumentException(
+ sprintf('Unknown type %s used for parameter %s.', $typeValue['type'], $key),
+ 1281859196
+ );
+ }
+
+ if (is_int($key)) {
+ if (count($precompiledQueryParts['queryParts']) > 0) {
+ $precompiledQueryParts['queryParts'][2 * $key + 1] = $value;
+ } else {
+ $parts = explode('?', $query, 2);
+ $parts[0] .= $value;
+ $query = implode('', $parts);
+ }
+ } else {
+ for ($i = 1; $i < count($precompiledQueryParts['queryParts']); $i++) {
+ if ($precompiledQueryParts['queryParts'][$i] === $key) {
+ $precompiledQueryParts['queryParts'][$i] = $value;
+ }
+ $query = str_replace($key, $value, $query);
+ }
+ }
+ }
+ }
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/db/class.t3lib_db_PreparedStatement.php']) {
+ include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/db/class.t3lib_db_PreparedStatement.php']);
+}
+
+?>
\ Kein Zeilenvorschub am Ende der Datei
Index: t3lib/core_autoload.php
===================================================================
--- t3lib/core_autoload.php (Revision 8607)
+++ t3lib/core_autoload.php (Arbeitskopie)
@@ -20,6 +20,7 @@
't3lib_compressor' => PATH_t3lib . 'class.t3lib_compressor.php',
't3lib_cs' => PATH_t3lib . 'class.t3lib_cs.php',
't3lib_db' => PATH_t3lib . 'class.t3lib_db.php',
+ 't3lib_db_preparedstatement' => PATH_t3lib . 'db/class.t3lib_db_PreparedStatement.php',
't3lib_diff' => PATH_t3lib . 'class.t3lib_diff.php',
't3lib_div' => PATH_t3lib . 'class.t3lib_div.php',
't3lib_exception' => PATH_t3lib . 'class.t3lib_exception.php',
--------------070602040709090700030606
Content-Type: text/plain;
name="15457-v3-v4.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="15457-v3-v4.diff"
diff -ur trunk-15457-v3/t3lib/class.t3lib_db.php trunk-15457-v4/t3lib/class.t3lib_db.php
--- trunk-15457-v3/t3lib/class.t3lib_db.php 2010-08-17 12:39:20.000000000 +0200
+++ trunk-15457-v4/t3lib/class.t3lib_db.php 2010-08-17 12:38:27.000000000 +0200
@@ -736,7 +736,7 @@
* @return pointer MySQL result pointer / DBAL object
* @access private
*/
- public function exec_PREPAREDquery ($query, array $queryComponents) {
+ public function exec_PREPAREDquery($query, array $queryComponents) {
$res = mysql_query($query, $this->link);
if ($this->debugOutput) {
$this->debug('stmt_execute', $query);
Nur in trunk-15457-v4/t3lib: class.t3lib_db.php.rej.
Nur in trunk-15457-v3/t3lib: class.t3lib_sqlparser.php.rej.
Nur in trunk-15457-v3/t3lib: core_autoload.php.rej.
diff -ur trunk-15457-v3/t3lib/db/class.t3lib_db_PreparedStatement.php trunk-15457-v4/t3lib/db/class.t3lib_db_PreparedStatement.php
--- trunk-15457-v3/t3lib/db/class.t3lib_db_PreparedStatement.php 2010-08-17 12:39:20.000000000 +0200
+++ trunk-15457-v4/t3lib/db/class.t3lib_db_PreparedStatement.php 2010-08-17 13:11:34.000000000 +0200
@@ -31,7 +31,7 @@
* USE:
* In all TYPO3 scripts when you need to create a prepared query:
* <code>
- * $statement = $GLOBALS['TYPO3_DB']->prepare_SELECTquery('*', 'pages', 'pid = :pid');
+ * $statement = $GLOBALS['TYPO3_DB']->prepare_SELECTquery('*', 'pages', 'uid = :uid');
* $statement->execute(array(':uid' => 2));
* while (($row = $statement->fetch()) !== FALSE) {
* // ...
@@ -170,7 +170,7 @@
*/
public function bindValues(array $values) {
foreach ($values as $parameter => $value) {
- $key = is_numeric($parameter) ? intval($parameter) + 1 : $parameter;
+ $key = is_int($parameter) ? $parameter + 1 : $parameter;
$this->bindValue($key, $value, self::PARAM_AUTOTYPE);
}
@@ -197,21 +197,25 @@
*
* @param mixed $parameter Parameter identifier. For a prepared statement using named placeholders, this will be a parameter name of the form :name. For a prepared statement using question mark placeholders, this will be the 1-indexed position of the parameter.
* @param mixed $value The value to bind to the parameter.
- * @param integer $data_type Explicit data type for the parameter using the t3lib_db_PreparedStatement::PARAM_* constants.
+ * @param integer $data_type Explicit data type for the parameter using the t3lib_db_PreparedStatement::PARAM_* constants. If not given, the PHP type of the value will be used instead (int, string, boolean)
* @return t3lib_db_PreparedStatement The current prepared statement to allow method chaining
* @api
*/
public function bindValue($parameter, $value, $data_type = self::PARAM_AUTOTYPE) {
switch ($data_type) {
case self::PARAM_INT:
+ if (!is_int($value)) {
+ throw new InvalidArgumentException('$value is not an integer as expected: ' . $value, 1281868686);
+ }
+ break;
case self::PARAM_BOOL:
- if (!is_numeric($value)) {
- throw new InvalidArgumentException('$value is not a numeric type: ' . $value, 1281868686);
+ if (!is_bool($value)) {
+ throw new InvalidArgumentException('$value is not a boolean as expected: ' . $value, 1281868687);
}
break;
}
- $key = is_numeric($parameter) ? intval($parameter) - 1 : $parameter;
+ $key = is_int($parameter) ? $parameter - 1 : $parameter;
$this->parameters[$key] = array(
'value' => $value,
'type' => ($data_type == self::PARAM_AUTOTYPE ? $this->guessValueType($value) : $data_type),
@@ -278,7 +282,7 @@
$row = $GLOBALS['TYPO3_DB']->sql_fetch_row($this->resource);
break;
default:
- throw new InvalidArgumentException('$fetch_style must be either FETCH_ASSOC or FETCH_NUM', 1281646455);
+ throw new InvalidArgumentException('$fetch_style must be either t3lib_db_PreparedStatement::FETCH_ASSOC or t3lib_db_PreparedStatement::FETCH_NUM', 1281646455);
}
return $row;
}
@@ -320,6 +324,19 @@
}
/**
+ * Move internal result pointer
+ *
+ * @param integer $rowNumber Where to place the result pointer (0 = start)
+ * @return boolean Returns TRUE on success or FALSE on failure.
+ * @api
+ */
+ public function seek($rowNumber) {
+ return $GLOBALS['TYPO3_DB']->sql_data_seek($this->resource, intval($rowNumber));
+ }
+
+
+
+ /**
* Returns the error number on the last execute() call.
*
* @return integer Driver specific error code.
@@ -360,7 +377,7 @@
$this->defaultFetchMode = $mode;
break;
default:
- throw new InvalidArgumentException('$mode must be either FETCH_ASSOC or FETCH_NUM', 1281875340);
+ throw new InvalidArgumentException('$mode must be either t3lib_db_PreparedStatement::FETCH_ASSOC or t3lib_db_PreparedStatement::FETCH_NUM', 1281875340);
}
}
@@ -373,9 +390,9 @@
protected function guessValueType($value) {
if (is_bool($value)) {
$type = self::PARAM_BOOL;
- } elseif (is_numeric($value)) {
+ } elseif (t3lib_div::testInt($value))) {
$type = self::PARAM_INT;
- } elseif (strtoupper($value) === 'NULL') {
+ } elseif (is_null($value) || strtoupper($value) === 'NULL') {
$type = self::PARAM_NULL;
} else {
$type = self::PARAM_STR;
@@ -399,7 +416,7 @@
$value = 'NULL';
break;
case self::PARAM_INT:
- $value = $typeValue['value'];
+ $value = intval($typeValue['value']);
break;
case self::PARAM_STR:
$value = $GLOBALS['TYPO3_DB']->fullQuoteStr($typeValue['value'], $this->table);
@@ -414,7 +431,7 @@
);
}
- if (is_numeric($key)) {
+ if (is_int($key)) {
if (count($precompiledQueryParts['queryParts']) > 0) {
$precompiledQueryParts['queryParts'][2 * $key + 1] = $value;
} else {
--------------070602040709090700030606--
More information about the TYPO3-team-core
mailing list