2008-07-17 03:51:29 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* dibi - tiny'n'smart database abstraction layer
|
|
|
|
* ----------------------------------------------
|
|
|
|
*
|
2008-12-31 00:13:40 +00:00
|
|
|
* Copyright (c) 2005, 2009 David Grudl (http://davidgrudl.com)
|
2008-07-17 03:51:29 +00:00
|
|
|
*
|
|
|
|
* This source file is subject to the "dibi license" that is bundled
|
|
|
|
* with this package in the file license.txt.
|
|
|
|
*
|
|
|
|
* For more information please see http://dibiphp.com
|
|
|
|
*
|
2008-12-31 00:13:40 +00:00
|
|
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
2008-07-17 03:51:29 +00:00
|
|
|
* @license http://dibiphp.com/license dibi license
|
|
|
|
* @link http://dibiphp.com
|
|
|
|
* @package dibi
|
|
|
|
* @version $Id$
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Default implementation of IDataSource for dibi.
|
|
|
|
*
|
|
|
|
* @author David Grudl
|
2008-12-31 00:13:40 +00:00
|
|
|
* @copyright Copyright (c) 2005, 2009 David Grudl
|
2008-07-17 03:51:29 +00:00
|
|
|
* @package dibi
|
|
|
|
*/
|
2008-09-05 05:35:15 +00:00
|
|
|
class DibiDataSource extends DibiObject implements IDataSource
|
2008-07-17 03:51:29 +00:00
|
|
|
{
|
|
|
|
/** @var DibiConnection */
|
|
|
|
private $connection;
|
|
|
|
|
|
|
|
/** @var string */
|
|
|
|
private $sql;
|
|
|
|
|
2009-02-05 23:13:29 +00:00
|
|
|
/** @var DibiResult */
|
|
|
|
private $result;
|
|
|
|
|
2008-07-17 03:51:29 +00:00
|
|
|
/** @var int */
|
|
|
|
private $count;
|
|
|
|
|
2009-02-08 21:15:54 +00:00
|
|
|
/** @var int */
|
|
|
|
private $totalCount;
|
|
|
|
|
2009-02-05 21:10:50 +00:00
|
|
|
/** @var array */
|
|
|
|
private $cols = array();
|
|
|
|
|
|
|
|
/** @var array */
|
|
|
|
private $sorting = array();
|
|
|
|
|
|
|
|
/** @var array */
|
|
|
|
private $conds = array();
|
|
|
|
|
2009-02-05 23:13:29 +00:00
|
|
|
/** @var int */
|
|
|
|
private $offset;
|
|
|
|
|
|
|
|
/** @var int */
|
|
|
|
private $limit;
|
|
|
|
|
2008-07-17 03:51:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string SQL command or table name, as data source
|
|
|
|
* @param DibiConnection connection
|
|
|
|
*/
|
2009-02-05 23:13:29 +00:00
|
|
|
public function __construct($sql, DibiConnection $connection)
|
2008-07-17 03:51:29 +00:00
|
|
|
{
|
2009-02-05 23:13:29 +00:00
|
|
|
if (strpos($sql, ' ') === FALSE) {
|
|
|
|
$this->sql = $sql; // table name
|
|
|
|
} else {
|
|
|
|
$this->sql = '(' . $sql . ') AS t'; // SQL command
|
|
|
|
}
|
|
|
|
$this->connection = $connection;
|
2008-07-17 03:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2009-02-23 03:55:47 +00:00
|
|
|
* Selects columns to query.
|
|
|
|
* @param string|array column name or array of column names
|
|
|
|
* @param string column alias
|
|
|
|
* @return DibiDataSource provides a fluent interface
|
2008-07-17 03:51:29 +00:00
|
|
|
*/
|
2009-02-23 03:55:47 +00:00
|
|
|
public function select($col, $as = NULL)
|
2008-07-17 03:51:29 +00:00
|
|
|
{
|
2009-02-23 03:55:47 +00:00
|
|
|
if (is_array($col)) {
|
|
|
|
$this->cols = $col;
|
|
|
|
} else {
|
|
|
|
$this->cols[$col] = $as;
|
|
|
|
}
|
|
|
|
$this->result = NULL;
|
|
|
|
return $this;
|
2008-07-17 03:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2009-02-23 03:55:47 +00:00
|
|
|
* Adds conditions to query.
|
|
|
|
* @param mixed conditions
|
|
|
|
* @return DibiDataSource provides a fluent interface
|
2008-07-17 03:51:29 +00:00
|
|
|
*/
|
2009-02-23 03:55:47 +00:00
|
|
|
public function where($cond)
|
2008-07-17 03:51:29 +00:00
|
|
|
{
|
2009-02-23 03:55:47 +00:00
|
|
|
if (is_array($cond)) {
|
|
|
|
// TODO: not consistent with select and orderBy
|
|
|
|
$this->conds[] = $cond;
|
|
|
|
} else {
|
|
|
|
$this->conds[] = func_get_args();
|
2009-02-08 21:15:54 +00:00
|
|
|
}
|
2009-02-23 03:55:47 +00:00
|
|
|
$this->result = $this->count = NULL;
|
|
|
|
return $this;
|
2009-02-08 21:15:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2009-02-23 03:55:47 +00:00
|
|
|
* Selects columns to order by.
|
|
|
|
* @param string|array column name or array of column names
|
|
|
|
* @param string sorting direction
|
|
|
|
* @return DibiDataSource provides a fluent interface
|
2009-02-08 21:15:54 +00:00
|
|
|
*/
|
2009-02-23 03:55:47 +00:00
|
|
|
public function orderBy($row, $sorting = 'ASC')
|
2009-02-08 21:15:54 +00:00
|
|
|
{
|
2009-02-23 03:55:47 +00:00
|
|
|
if (is_array($row)) {
|
|
|
|
$this->sorting = $row;
|
|
|
|
} else {
|
|
|
|
$this->sorting[$row] = $sorting;
|
2008-07-17 03:51:29 +00:00
|
|
|
}
|
2009-02-23 03:55:47 +00:00
|
|
|
$this->result = NULL;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Limits number of rows.
|
|
|
|
* @param int limit
|
|
|
|
* @param int offset
|
|
|
|
* @return DibiDataSource provides a fluent interface
|
|
|
|
*/
|
|
|
|
public function applyLimit($limit, $offset = NULL)
|
|
|
|
{
|
|
|
|
$this->limit = $limit;
|
|
|
|
$this->offset = $offset;
|
|
|
|
$this->result = $this->count = NULL;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the dibi connection.
|
|
|
|
* @return DibiConnection
|
|
|
|
*/
|
|
|
|
final public function getConnection()
|
|
|
|
{
|
|
|
|
return $this->connection;
|
2008-07-17 03:51:29 +00:00
|
|
|
}
|
|
|
|
|
2009-02-05 21:10:50 +00:00
|
|
|
|
|
|
|
|
2009-02-23 03:55:47 +00:00
|
|
|
/********************* executing ****************d*g**/
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-02-05 23:13:29 +00:00
|
|
|
/**
|
|
|
|
* Returns (and queries) DibiResult.
|
|
|
|
* @return DibiResult
|
|
|
|
*/
|
|
|
|
public function getResult()
|
|
|
|
{
|
|
|
|
if ($this->result === NULL) {
|
|
|
|
$this->result = $this->connection->nativeQuery($this->__toString());
|
|
|
|
}
|
|
|
|
return $this->result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-05 21:10:50 +00:00
|
|
|
|
2009-02-23 03:55:47 +00:00
|
|
|
/**
|
|
|
|
* @return DibiResultIterator
|
|
|
|
*/
|
|
|
|
public function getIterator()
|
|
|
|
{
|
|
|
|
return $this->getResult()->getIterator();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates, executes SQL query and fetches the single row.
|
|
|
|
* @return DibiRow|FALSE array on success, FALSE if no next record
|
|
|
|
*/
|
|
|
|
public function fetch()
|
|
|
|
{
|
|
|
|
return $this->getResult()->fetch();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Like fetch(), but returns only first field.
|
|
|
|
* @return mixed value on success, FALSE if no next record
|
|
|
|
*/
|
|
|
|
public function fetchSingle()
|
|
|
|
{
|
|
|
|
return $this->getResult()->fetchSingle();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetches all records from table.
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function fetchAll()
|
|
|
|
{
|
|
|
|
return $this->getResult()->fetchAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetches all records from table and returns associative tree.
|
|
|
|
* @param string associative descriptor
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function fetchAssoc($assoc)
|
|
|
|
{
|
|
|
|
return $this->getResult()->fetchAssoc($assoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetches all records from table like $key => $value pairs.
|
|
|
|
* @param string associative key
|
|
|
|
* @param string value
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function fetchPairs($key = NULL, $value = NULL)
|
|
|
|
{
|
|
|
|
return $this->getResult()->fetchPairs($key, $value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/********************* exporting ****************d*g**/
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-02-05 21:10:50 +00:00
|
|
|
/**
|
2009-02-05 23:13:29 +00:00
|
|
|
* Returns this data source wrapped in DibiFluent object.
|
2009-02-05 21:10:50 +00:00
|
|
|
* @return DibiFluent
|
|
|
|
*/
|
|
|
|
public function toFluent()
|
|
|
|
{
|
2009-02-08 21:15:54 +00:00
|
|
|
return $this->connection->select('*')->from('(%SQL) AS t', $this->__toString());
|
2009-02-05 21:10:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2009-02-05 23:13:29 +00:00
|
|
|
* Returns this data source wrapped in DibiDataSource object.
|
2009-02-05 21:10:50 +00:00
|
|
|
* @return DibiDataSource
|
|
|
|
*/
|
|
|
|
public function toDataSource()
|
|
|
|
{
|
|
|
|
return new self($this->__toString(), $this->connection);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns SQL query.
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
final public function __toString()
|
|
|
|
{
|
|
|
|
return $this->connection->sql('
|
|
|
|
SELECT %n', (empty($this->cols) ? '*' : $this->cols), '
|
2009-02-05 23:13:29 +00:00
|
|
|
FROM %SQL', $this->sql, '
|
2009-02-05 21:10:50 +00:00
|
|
|
WHERE %and', $this->conds, '
|
|
|
|
ORDER BY %by', $this->sorting, '
|
2009-02-05 23:13:29 +00:00
|
|
|
%ofs %lmt', $this->offset, $this->limit
|
|
|
|
);
|
2009-02-05 21:10:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-02-23 03:55:47 +00:00
|
|
|
/********************* counting ****************d*g**/
|
2009-02-05 21:10:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2009-02-23 03:55:47 +00:00
|
|
|
* Returns the number of rows in a given data source.
|
|
|
|
* @return int
|
2009-02-05 21:10:50 +00:00
|
|
|
*/
|
2009-02-23 03:55:47 +00:00
|
|
|
public function count()
|
2009-02-05 21:10:50 +00:00
|
|
|
{
|
2009-02-23 03:55:47 +00:00
|
|
|
if ($this->count === NULL) {
|
|
|
|
$this->count = $this->conds || $this->offset || $this->limit
|
|
|
|
? (int) $this->connection->nativeQuery(
|
|
|
|
'SELECT COUNT(*) FROM (' . $this->__toString() . ') AS t'
|
|
|
|
)->fetchSingle()
|
|
|
|
: $this->getTotalCount();
|
2009-02-05 21:10:50 +00:00
|
|
|
}
|
2009-02-23 03:55:47 +00:00
|
|
|
return $this->count;
|
2009-02-05 21:10:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2009-02-23 03:55:47 +00:00
|
|
|
* Returns the number of rows in a given data source.
|
|
|
|
* @return int
|
2009-02-05 21:10:50 +00:00
|
|
|
*/
|
2009-02-23 03:55:47 +00:00
|
|
|
public function getTotalCount()
|
2009-02-05 21:10:50 +00:00
|
|
|
{
|
2009-02-23 03:55:47 +00:00
|
|
|
if ($this->totalCount === NULL) {
|
|
|
|
$this->totalCount = (int) $this->connection->nativeQuery(
|
|
|
|
'SELECT COUNT(*) FROM ' . $this->sql
|
|
|
|
)->fetchSingle();
|
2009-02-05 21:10:50 +00:00
|
|
|
}
|
2009-02-23 03:55:47 +00:00
|
|
|
return $this->totalCount;
|
2009-02-05 21:10:50 +00:00
|
|
|
}
|
|
|
|
|
2008-07-17 03:51:29 +00:00
|
|
|
}
|