diff --git a/model/Database.php b/model/Database.php index 020564069..024c6cf19 100644 --- a/model/Database.php +++ b/model/Database.php @@ -1050,211 +1050,4 @@ abstract class SS_Database { public function releaseLock($name) { return false; } -} - -/** - * Abstract query-result class. - * Once again, this should be subclassed by an actual database implementation. It will only - * ever be constructed by a subclass of SS_Database. The result of a database query - an iteratable object - * that's returned by DB::SS_Query - * - * Primarily, the SS_Query class takes care of the iterator plumbing, letting the subclasses focusing - * on providing the specific data-access methods that are required: {@link nextRecord()}, {@link numRecords()} - * and {@link seek()} - * @package framework - * @subpackage model - */ -abstract class SS_Query implements Iterator { - /** - * The current record in the interator. - * @var array - */ - private $currentRecord = null; - - /** - * The number of the current row in the interator. - * @var int - */ - private $rowNum = -1; - - /** - * Flag to keep track of whether iteration has begun, to prevent unnecessary seeks - */ - private $queryHasBegun = false; - - /** - * Return an array containing all the values from a specific column. If no column is set, then the first will be - * returned - * - * @param string $column - * @return array - */ - public function column($column = null) { - $result = array(); - - while($record = $this->next()) { - if($column) $result[] = $record[$column]; - else $result[] = $record[key($record)]; - } - - return $result; - } - - /** - * Return an array containing all values in the leftmost column, where the keys are the - * same as the values. - * @return array - */ - public function keyedColumn() { - $column = array(); - foreach($this as $record) { - $val = $record[key($record)]; - $column[$val] = $val; - } - return $column; - } - - /** - * Return a map from the first column to the second column. - * @return array - */ - public function map() { - $column = array(); - foreach($this as $record) { - $key = reset($record); - $val = next($record); - $column[$key] = $val; - } - return $column; - } - - /** - * Returns the next record in the iterator. - * @return array - */ - public function record() { - return $this->next(); - } - - /** - * Returns the first column of the first record. - * @return string - */ - public function value() { - $record = $this->next(); - if($record) return $record[key($record)]; - } - - /** - * Return an HTML table containing the full result-set - */ - public function table() { - $first = true; - $result = "\n"; - - foreach($this as $record) { - if($first) { - $result .= ""; - foreach($record as $k => $v) { - $result .= " "; - } - $result .= " \n"; - } - - $result .= ""; - foreach($record as $k => $v) { - $result .= " "; - } - $result .= " \n"; - - $first = false; - } - $result .= "
" . Convert::raw2xml($k) . "
" . Convert::raw2xml($v) . "
\n"; - - if($first) return "No records found"; - return $result; - } - - /** - * Iterator function implementation. Rewind the iterator to the first item and return it. - * Makes use of {@link seek()} and {@link numRecords()}, takes care of the plumbing. - * @return array - */ - public function rewind() { - if($this->queryHasBegun && $this->numRecords() > 0) { - $this->queryHasBegun = false; - return $this->seek(0); - } - } - - /** - * Iterator function implementation. Return the current item of the iterator. - * @return array - */ - public function current() { - if(!$this->currentRecord) { - return $this->next(); - } else { - return $this->currentRecord; - } - } - - /** - * Iterator function implementation. Return the first item of this iterator. - * @return array - */ - public function first() { - $this->rewind(); - return $this->current(); - } - - /** - * Iterator function implementation. Return the row number of the current item. - * @return int - */ - public function key() { - return $this->rowNum; - } - - /** - * Iterator function implementation. Return the next record in the iterator. - * Makes use of {@link nextRecord()}, takes care of the plumbing. - * @return array - */ - public function next() { - $this->queryHasBegun = true; - $this->currentRecord = $this->nextRecord(); - $this->rowNum++; - return $this->currentRecord; - } - - /** - * Iterator function implementation. Check if the iterator is pointing to a valid item. - * @return boolean - */ - public function valid() { - if(!$this->queryHasBegun) $this->next(); - return $this->currentRecord !== false; - } - - /** - * Return the next record in the query result. - * @return array - */ - abstract public function nextRecord(); - - /** - * Return the total number of items in the query result. - * @return int - */ - abstract public function numRecords(); - - /** - * Go to a specific row number in the query result and return the record. - * @param int $rowNum Tow number to go to. - * @return array - */ - abstract public function seek($rowNum); -} - - +} \ No newline at end of file diff --git a/model/MySQLDatabase.php b/model/MySQLDatabase.php index 3ed99ec72..e35a92f2b 100644 --- a/model/MySQLDatabase.php +++ b/model/MySQLDatabase.php @@ -1209,53 +1209,4 @@ class MySQLDatabase extends SS_Database { // Prefix with database name return Convert::raw2sql($this->database . '_' . Convert::raw2sql($name)); } -} - -/** - * A result-set from a MySQL database. - * @package framework - * @subpackage model - */ -class MySQLQuery extends SS_Query { - /** - * The MySQLDatabase object that created this result set. - * @var MySQLDatabase - */ - protected $database; - - /** - * The internal MySQL handle that points to the result set. - * @var resource - */ - protected $handle; - - /** - * Hook the result-set given into a Query class, suitable for use by SilverStripe. - * @param database The database object that created this query. - * @param handle the internal mysql handle that is points to the resultset. - */ - public function __construct(MySQLDatabase $database, $handle) { - $this->database = $database; - $this->handle = $handle; - } - - public function __destruct() { - if(is_object($this->handle)) $this->handle->free(); - } - - public function seek($row) { - if(is_object($this->handle)) return $this->handle->data_seek($row); - } - - public function numRecords() { - if(is_object($this->handle)) return $this->handle->num_rows; - } - - public function nextRecord() { - if(is_object($this->handle) && ($data = $this->handle->fetch_assoc())) { - return $data; - } else { - return false; - } - } -} +} \ No newline at end of file diff --git a/model/MySQLQuery.php b/model/MySQLQuery.php new file mode 100644 index 000000000..b1366233f --- /dev/null +++ b/model/MySQLQuery.php @@ -0,0 +1,69 @@ +database = $database; + $this->handle = $handle; + } + + public function __destruct() { + if(is_object($this->handle)) { + $this->handle->free(); + } + } + + /** + * {@inheritdoc} + */ + public function seek($row) { + if(is_object($this->handle)) { + return $this->handle->data_seek($row); + } + } + + /** + * {@inheritdoc} + */ + public function numRecords() { + if(is_object($this->handle)) { + return $this->handle->num_rows; + } + } + + /** + * {@inheritdoc} + */ + public function nextRecord() { + if(is_object($this->handle) && ($data = $this->handle->fetch_assoc())) { + return $data; + } else { + return false; + } + } +} diff --git a/model/Query.php b/model/Query.php new file mode 100644 index 000000000..e63caa1ca --- /dev/null +++ b/model/Query.php @@ -0,0 +1,252 @@ +next()) { + if($column) { + $result[] = $record[$column]; + } else { + $result[] = $record[key($record)]; + } + } + + return $result; + } + + /** + * Return an array containing all values in the leftmost column, where the + * keys are the same as the values. + * + * @return array + */ + public function keyedColumn() { + $column = array(); + + foreach($this as $record) { + $val = $record[key($record)]; + $column[$val] = $val; + } + + return $column; + } + + /** + * Return a map from the first column to the second column. + * + * @return array + */ + public function map() { + $column = array(); + + foreach($this as $record) { + $key = reset($record); + $val = next($record); + $column[$key] = $val; + } + + return $column; + } + + /** + * Returns the next record in the iterator. + * + * @return array + */ + public function record() { + return $this->next(); + } + + /** + * Returns the first column of the first record. + * + * @return string + */ + public function value() { + $record = $this->next(); + + if($record) { + return $record[key($record)]; + } + } + + /** + * Return an HTML table containing the full result-set. + */ + public function table() { + $first = true; + $result = "\n"; + + foreach($this as $record) { + if($first) { + $result .= ""; + foreach($record as $k => $v) { + $result .= " "; + } + $result .= " \n"; + } + + $result .= ""; + foreach($record as $k => $v) { + $result .= " "; + } + $result .= " \n"; + + $first = false; + } + $result .= "
" . Convert::raw2xml($k) . "
" . Convert::raw2xml($v) . "
\n"; + + if($first) return "No records found"; + return $result; + } + + /** + * Iterator function implementation. Rewind the iterator to the first item + * and return it. + * + * Makes use of {@link seek()} and {@link numRecords()}, takes care of the + * plumbing. + * + * @return array + */ + public function rewind() { + if($this->queryHasBegun && $this->numRecords() > 0) { + $this->queryHasBegun = false; + + return $this->seek(0); + } + } + + /** + * Iterator function implementation. Return the current item of the + * iterator. + * + * @return array + */ + public function current() { + if(!$this->currentRecord) { + return $this->next(); + } else { + return $this->currentRecord; + } + } + + /** + * Iterator function implementation. Return the first item of this iterator. + * @return array + */ + public function first() { + $this->rewind(); + + return $this->current(); + } + + /** + * Iterator function implementation. Return the row number of the current + * item. + * + * @return int + */ + public function key() { + return $this->rowNum; + } + + /** + * Iterator function implementation. Return the next record in the iterator. + * + * Makes use of {@link nextRecord()}, takes care of the plumbing. + * + * @return array + */ + public function next() { + $this->queryHasBegun = true; + $this->currentRecord = $this->nextRecord(); + $this->rowNum++; + return $this->currentRecord; + } + + /** + * Iterator function implementation. Check if the iterator is pointing to a + * valid item. + * + * @return boolean + */ + public function valid() { + if(!$this->queryHasBegun) { + $this->next(); + } + + return $this->currentRecord !== false; + } + + /** + * Return the next record in the query result. + * + * @return array + */ + abstract public function nextRecord(); + + /** + * Return the total number of items in the query result. + * + * @return int + */ + abstract public function numRecords(); + + /** + * Go to a specific row number in the query result and return the record. + * + * @param int $rowNum Tow number to go to. + * + * @return array + */ + abstract public function seek($rowNum); +} \ No newline at end of file