Newer
Older
foreach ($params as $i=>&$p) {
if (is_int($p) || is_bool($p))
elseif (is_float($p))
$types .= 'd';
elseif ($p instanceof DateTime) {
$types .= 's';
$p = $p->format('Y-m-d H:i:s');
elseif (is_object($p)) {
$types .= 's';
$p = (string) $p;
}
// TODO: Emit error if param is null
array_unshift($ps, $types);
call_user_func_array(array($this->stmt,'bind_param'), $ps);
}
function _setup_output() {
if (!($meta = $this->stmt->result_metadata()))
throw new OrmException('Unable to fetch statment metadata: ', $this->stmt->error);
$this->fields = $meta->fetch_fields();
}
// Iterator interface
function rewind() {
if (!isset($this->stmt))
$this->_prepare();
$this->stmt->data_seek(0);
}
function next() {
$status = $this->stmt->fetch();
if ($status === false)
throw new OrmException($this->stmt->error);
elseif ($status === null) {
$this->close();
return false;
}
return true;
}
function getArray() {
$output = array();
$variables = array();
if (!isset($this->stmt))
$this->_prepare();
foreach ($this->fields as $f)
$variables[] = &$output[$f->name]; // pass by reference
if (!call_user_func_array(array($this->stmt, 'bind_result'), $variables))
throw new OrmException('Unable to bind result: ' . $this->stmt->error);
if (!$this->next())
return false;
return $output;
}
function getRow() {
$output = array();
$variables = array();
if (!isset($this->stmt))
$this->_prepare();
foreach ($this->fields as $f)
$variables[] = &$output[]; // pass by reference
if (!call_user_func_array(array($this->stmt, 'bind_result'), $variables))
throw new OrmException('Unable to bind result: ' . $this->stmt->error);
if (!$this->next())
return false;
return $output;
}
function close() {
if (!$this->stmt)
return;
$this->stmt->close();
$this->stmt = null;
}
function affected_rows() {
return $this->stmt->affected_rows;
}
function insert_id() {
return $this->stmt->insert_id;
}
return preg_replace_callback("/:(\d+)(?=([^']*'[^']*')*[^']*$)/",
function($m) use ($self) {
$p = $self->params[$m[1]-1];
switch (true) {
case is_bool($p):
$p = (int) $p;
case is_int($p):
case is_float($p):
return $p;
case $p instanceof DateTime:
$p = $p->format('Y-m-d H:i:s');
return db_real_escape((string) $p, true);
}
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
/**
* 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;
var $constraints;
var $negated = false;
var $ored = false;
function __construct($filter=array(), $flags=0) {
if (!is_array($filter))
$filter = array($filter);
$this->constraints = $filter;
$this->negated = $flags & self::NEGATED;
$this->ored = $flags & self::ANY;
}
function isNegated() {
return $this->negated;
}
function isOred() {
return $this->ored;
}
function negate() {
$this->negated = !$this->negated;
return $this;
}
function union() {
$this->ored = true;
}
function add($constraints) {
if (is_array($constraints))
$this->constraints = array_merge($this->constraints, $constraints);
elseif ($constraints instanceof static)
$this->constraints[] = $constraints;
else
throw new InvalidArgumentException('Expected an instance of Q or an array thereof');
return $this;
}
static function not($constraints) {
return new static($constraints, self::NEGATED);
}
static function any($constraints) {
return new static($constraints, self::ANY);
static function all($constraints) {
return new static($constraints);
}
return serialize(array($this->negated, $this->ored, $this->constraints));
}
function unserialize($data) {
list($this->negated, $this->ored, $this->constraints) = unserialize($data);