/** * Excecute query. * Returns DB_MySQL_Result for 'SELECT', 'SHOW', etc queries, returns new id for 'INSERT' query, returns TRUE for other * * @param mixed $statement String or a query statement object * @param array $args Arguments to be parsed into the query on placeholders * @return DB_MySQL_Result */ public function query($statement, $args = array()) { // Get statement out of object if (is_object($statement)) { $source = $statement->getBaseTable(); $statement = $statement->getStatement(); } // Parse arguments if (func_num_args() > 2) { $args = func_get_args(); array_shift($args); } if (!empty($args)) { $statement = $this->parse($statement, $args); } // Extract (child) subqueries for cascading data $tree = $this->sqlSplitter->extractTree($statement); // Execute query statement $result = $this->nativeQuery($tree[0]); if (!$result) { $match = null; if ($this->native->errno == 1451 && preg_match('/^Cannot delete or update a parent row: a foreign key constraint fails \\(`.*?`\\.`(.*?)`, CONSTRAINT `.*?` FOREIGN KEY \\(`(.*?)`\\) REFERENCES `(.*?)` \\(`(.*?)`\\)\\)/', $this->native->error, $match)) { throw new DB_ConstraintException($this->native->error, $this->native->errno, $match[3], $match[4], $match[1], $match[2]); } throw new DB_QueryException($this->native->error, $tree[0], $this->native->errno); } // Return value if query did not return a mysql_result object if (!is_object($result)) { return $this->native->insert_id ? $this->native->insert_id : $result; } // Create result object $class = count($tree) > 1 ? self::$classes['Result_Tree'] : self::$classes['Result']; while ($field = $result->fetch_field()) { if ($field->name === self::NESTED_LEFT) { $class = self::$classes['Result_NestedSet']; break; } } load_class($class); $ob = new $class(isset($source) ? $source : $this, $result, $statement); // If statement has any childqueries, create tree result if (count($tree) > 1) { for ($i = 1, $m = count($tree); $i < $m; $i++) { // array(index, statement, format, filter(bool)) $child_result = $tree[$i][3] ? $this->query($tree[$i][1], $ob->getColumn($tree[$i][0])) : $this->query($tree[$i][1]); $ob->addChild($ob->getFieldIndex($tree[$i][0]), $child_result, $tree[$i][2]); } } // Pass base table definition if any and return result return $ob; }
/** * Create query to update rows of a table. * * @param string $table * @param array $columns Assasioted array as (column=>value, ...) * @param string|array $criteria WHERE expression or array(column=>value, ...) * @param int $flags Options as bitset * @return string */ public static function buildUpdateStatement($table = null, $columns = null, $criteria = null, $flags = 0) { $sql_set = array(); foreach ($columns as $column => &$value) { $sql_set[] = self::quoteIdentifier($column) . '=' . self::quote($value); } if (!is_scalar($criteria)) { array_walk($criteria, function (&$value, $key) use($table) { $value = DB_MySQL_SQLSplitter::buildWhere(DB_MySQL_SQLSplitter::makeIdentifier($table, $key, null, $flags), $value); }); $criteria = join($flags & DB::GLUE_OR ? ' OR ' : ' AND ', $criteria); } return "UPDATE" . (isset($table) ? ' ' . self::quoteIdentifier($table, $flags) : null) . (!empty($sql_set) ? " SET " . join(', ', $sql_set) : null) . (isset($criteria) ? " WHERE {$criteria}" : null); }