2008-07-17 03:51:29 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
2010-09-14 18:40:41 +02:00
|
|
|
* This file is part of the "dibi" - smart database abstraction layer.
|
2012-01-02 20:24:16 +01:00
|
|
|
* Copyright (c) 2005 David Grudl (http://davidgrudl.com)
|
2008-07-17 03:51:29 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Default implementation of IDataSource for dibi.
|
|
|
|
*
|
2010-09-14 18:40:41 +02:00
|
|
|
* @author David Grudl
|
2012-01-03 04:50:11 +01:00
|
|
|
* @package dibi
|
2010-04-22 12:12:11 +02:00
|
|
|
*
|
|
|
|
* @property-read DibiConnection $connection
|
|
|
|
* @property-read DibiResult $result
|
|
|
|
* @property-read DibiResultIterator $iterator
|
|
|
|
* @property-read int $totalCount
|
2008-07-17 03:51:29 +00:00
|
|
|
*/
|
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
|
|
|
|
|
|
|
/**
|
2009-06-13 19:05:23 +00:00
|
|
|
* @param string SQL command or table or view name, as data source
|
2008-07-17 03:51:29 +00:00
|
|
|
* @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
|
|
|
{
|
2010-02-16 19:19:32 +01:00
|
|
|
if (strpbrk($sql, " \t\r\n") === FALSE) {
|
2009-06-13 19:05:23 +00:00
|
|
|
$this->sql = $connection->getDriver()->escape($sql, dibi::IDENTIFIER); // table name
|
2009-02-05 23:13:29 +00:00
|
|
|
} else {
|
2009-04-26 15:35:39 +00:00
|
|
|
$this->sql = '(' . $sql . ') t'; // SQL command
|
2009-02-05 23:13:29 +00:00
|
|
|
}
|
|
|
|
$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
|
2013-06-22 16:54:51 +02:00
|
|
|
* @param string column alias
|
2013-07-02 18:42:55 +02:00
|
|
|
* @return self
|
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
|
2013-07-02 18:42:55 +02:00
|
|
|
* @return self
|
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
|
2013-06-22 16:54:51 +02:00
|
|
|
* @param string sorting direction
|
2013-07-02 18:42:55 +02:00
|
|
|
* @return self
|
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
|
2013-07-02 18:42:55 +02:00
|
|
|
* @return self
|
2009-02-23 03:55:47 +00:00
|
|
|
*/
|
|
|
|
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-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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-02 02:22:36 +00:00
|
|
|
/**
|
|
|
|
* Discards the internal cache.
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function release()
|
|
|
|
{
|
2009-06-02 22:04:54 +00:00
|
|
|
$this->result = $this->count = $this->totalCount = NULL;
|
2009-03-02 02:22:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-23 03:55:47 +00:00
|
|
|
/********************* 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()
|
|
|
|
{
|
2011-02-16 17:48:47 +01:00
|
|
|
return $this->connection->select('*')->from('(%SQL) 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
|
|
|
|
*/
|
2009-10-03 00:17:31 +08:00
|
|
|
public function __toString()
|
2009-02-05 21:10:50 +00:00
|
|
|
{
|
2012-01-19 02:25:30 +01:00
|
|
|
try {
|
|
|
|
return $this->connection->translate('
|
2012-01-19 06:00:38 +01:00
|
|
|
SELECT %n', (empty($this->cols) ? '*' : $this->cols), '
|
|
|
|
FROM %SQL', $this->sql, '
|
|
|
|
%ex', $this->conds ? array('WHERE %and', $this->conds) : NULL, '
|
|
|
|
%ex', $this->sorting ? array('ORDER BY %by', $this->sorting) : NULL, '
|
|
|
|
%ofs %lmt', $this->offset, $this->limit
|
2012-01-19 02:25:30 +01:00
|
|
|
);
|
|
|
|
} catch (Exception $e) {
|
|
|
|
trigger_error($e->getMessage(), E_USER_ERROR);
|
|
|
|
}
|
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(
|
2011-02-16 17:48:47 +01:00
|
|
|
'SELECT COUNT(*) FROM (' . $this->__toString() . ') t'
|
2009-02-23 03:55:47 +00:00
|
|
|
)->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
|
|
|
}
|