diff --git a/include/class.orm.php b/include/class.orm.php index fc4c9b6c5e535f452f74e203ad0945fd135002a7..861a40b14843f712fc13b80543f690e6a0418e91 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -2897,7 +2897,7 @@ class MySqlCompiler extends SqlCompiler { } } -class MySqlExecutor { +class MySqlPreparedExecutor { var $stmt; var $fields = array(); @@ -3077,6 +3077,90 @@ class MySqlExecutor { } } +/** + * Simplified executor which uses the mysqli_query() function to process + * queries. This method is faster on MySQL as it doesn't require the PREPARE + * overhead, nor require two trips to the database per query. All parameters + * are escaped and placed directly into the SQL statement. With this style, + * it is possible that multiple parameters could compile a statement which + * exceeds the MySQL max_allowed_packet setting. + */ +class MySqlExecutor +extends MySqlPreparedExecutor { + function execute() { + $sql = $this->__toString(); + if (!($this->stmt = db_query($sql, true, !$this->unbuffered))) + throw new InconsistentModelException( + 'Unable to prepare query: '.db_error().' '.$sql); + // mysqli_query() return TRUE for UPDATE queries and friends + if ($this->stmt !== true) + $this->_setupCast(); + return true; + } + + function _setupCast() { + $fields = $this->stmt->fetch_fields(); + $this->types = array(); + foreach ($fields as $F) { + $this->types[] = $F->type; + } + } + + function _cast($record) { + $i=0; + foreach ($record as &$f) { + switch ($this->types[$i++]) { + case MYSQLI_TYPE_DECIMAL: + case MYSQLI_TYPE_NEWDECIMAL: + case MYSQLI_TYPE_LONGLONG: + case MYSQLI_TYPE_FLOAT: + case MYSQLI_TYPE_DOUBLE: + $f = isset($f) ? (double) $f : $f; + break; + + case MYSQLI_TYPE_BIT: + case MYSQLI_TYPE_TINY: + case MYSQLI_TYPE_SHORT: + case MYSQLI_TYPE_LONG: + case MYSQLI_TYPE_INT24: + $f = isset($f) ? (int) $f : $f; + break; + + default: + // No change (leave as string) + } + } + unset($f); + return $record; + } + + function getArray() { + if (!isset($this->stmt)) + $this->execute(); + + if (null === ($record = $this->stmt->fetch_assoc())) + return false; + return $this->_cast($record); + } + + function getRow() { + if (!isset($this->stmt)) + $this->execute(); + + if (null === ($record = $this->stmt->fetch_row())) + return false; + return $this->_cast($record); + } + + function affected_rows() { + return db_affected_rows(); + } + + function insert_id() { + return db_insert_id(); + } +} + class Q implements Serializable { const NEGATED = 0x0001; const ANY = 0x0002;