From 8dc4f37917ac9a7685c6d10c19bf97b825270eb7 Mon Sep 17 00:00:00 2001 From: Jared Hancock <jared@osticket.com> Date: Tue, 10 Jun 2014 16:26:18 -0500 Subject: [PATCH] orm: Fix issues surrounding MySQL commands OoS Several places in the code initialize a list of objects from the database and only fetch one item. In certain instances (which seem almost like a race condition), MySQL will feel like there are more records available in the database and will complain with "Commands out of sync, you can't run the command now". This patch addresses the issue by utilizing the ::one() method of the QuerySet where only one record is expected. The ::one() method is further designed to fetch all one results (which satisfies the MySQL client library) and return the first item. --- include/class.dynamic_forms.php | 13 +++++++------ include/class.orm.php | 22 ++++++++++++++-------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index 46c8460ef..8dfbb94c4 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -220,8 +220,7 @@ class UserForm extends DynamicForm { static function getUserForm() { if (!isset(static::$form)) { - $o = static::objects(); - static::$form = $o[0]; + static::$form = static::objects()->one(); } return static::$form; } @@ -233,8 +232,8 @@ class UserForm extends DynamicForm { } static function getNewInstance() { - $o = static::objects(); - static::$instance = $o[0]->instanciate(); + $o = static::objects()->one(); + static::$instance = $o->instanciate(); return static::$instance; } } @@ -263,8 +262,8 @@ class TicketForm extends DynamicForm { } static function getNewInstance() { - $o = static::objects(); - static::$instance = $o[0]->instanciate(); + $o = static::objects()->one(); + static::$instance = $o->instanciate(); return static::$instance; } @@ -1094,6 +1093,8 @@ class SelectionField extends FormField { } function to_php($value, $id=false) { + if ($value === null && $id === null) + return null; if ($id && is_int($id)) $item = DynamicListItem::lookup($id); # Attempt item lookup by name too diff --git a/include/class.orm.php b/include/class.orm.php index b4f65e551..1d8810919 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -167,9 +167,7 @@ class VerySimpleModel { if (!is_array($criteria)) // Model::lookup(1), where >1< is the pk value $criteria = array(static::$meta['pk'][0] => $criteria); - $list = static::objects()->filter($criteria)->limit(1); - // TODO: Throw error if more than one result from database - return $list[0]; + return static::objects()->filter($criteria)->one(); } function delete($pk=false) { @@ -333,7 +331,8 @@ class QuerySet implements IteratorAggregate, ArrayAccess { } function one() { - $this->limit(1); + $list = $this->limit(1)->all(); + // TODO: Throw error if more than one result from database return $this[0]; } @@ -987,7 +986,8 @@ class MysqlExecutor { function _prepare() { $this->execute(); $this->_setup_output(); - $this->stmt->store_result(); + if (!$this->stmt->store_result()) + throw new OrmException('Unable to process query: '.$this->stmt->error); } function execute() { @@ -1024,9 +1024,11 @@ class MysqlExecutor { } function _setup_output() { - $meta = $this->stmt->result_metadata(); + if (!($meta = $this->stmt->result_metadata())) + throw new OrmException('Unable to fetch statment metadata: ', $this->stmt->error); while ($f = $meta->fetch_field()) $this->fields[] = $f; + $meta->free_result(); } // Iterator interface @@ -1057,7 +1059,9 @@ class MysqlExecutor { foreach ($this->fields as $f) $variables[] = &$output[$f->name]; // pass by reference - call_user_func_array(array($this->stmt, 'bind_result'), $variables); + 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; @@ -1073,7 +1077,9 @@ class MysqlExecutor { foreach ($this->fields as $f) $variables[] = &$output[]; // pass by reference - call_user_func_array(array($this->stmt, 'bind_result'), $variables); + 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; -- GitLab