Add explain method to query builder

This commit is contained in:
Timothy Warren 2014-02-04 20:59:30 -05:00
parent 6dc9ed0d52
commit 8dc2079d43
14 changed files with 212 additions and 11 deletions

View File

@ -32,6 +32,14 @@ interface iDB_SQL {
*/
public function limit($sql, $limit, $offset=FALSE);
/**
* Modify the query to get the query plan
*
* @param string $sql
* @return string
*/
public function explain($sql);
/**
* Get the sql for random ordering
*

View File

@ -88,6 +88,15 @@ interface iQuery_Builder {
// --------------------------------------------------------------------------
/**
* Shows the query plan for the query
*
* @return $this
*/
public function explain();
// --------------------------------------------------------------------------
/**
* Specify the database table to select from
*
@ -181,9 +190,10 @@ interface iQuery_Builder {
*
* @param mixed $key
* @param mixed $val
@ @param bool $escape
* @return $this
*/
public function where($key, $val=array());
public function where($key, $val=array(), $escape = NULL);
// --------------------------------------------------------------------------

View File

@ -93,6 +93,9 @@ class Query_Builder implements iQuery_Builder {
// List of sql queries executed
public $queries;
// Whether to do only an explain on the query
protected $explain = FALSE;
// --------------------------------------------------------------------------
// ! Methods
// --------------------------------------------------------------------------
@ -270,6 +273,19 @@ class Query_Builder implements iQuery_Builder {
// --------------------------------------------------------------------------
/**
* Tell the database to give you the query plan instead of result set
*
* @return $this
*/
public function explain()
{
$this->explain = TRUE;
return $this;
}
// --------------------------------------------------------------------------
/**
* Specify the database table to select from
*
@ -593,9 +609,10 @@ class Query_Builder implements iQuery_Builder {
*
* @param mixed $key
* @param mixed $val
* @param mixed $escape
* @return $this
*/
public function where($key, $val=array())
public function where($key, $val=array(), $escape=NULL)
{
return $this->_where_string($key, $val, 'AND');
}
@ -1383,6 +1400,12 @@ class Query_Builder implements iQuery_Builder {
$sql = $this->sql->limit($sql, $this->limit, $this->offset);
}
// See what needs to happen to only return the query plan
if (isset($this->explain) && $this->explain === TRUE)
{
$sql = $this->sql->explain($sql);
}
return $sql;
}
}

View File

@ -48,6 +48,19 @@ class Firebird_SQL implements iDB_SQL {
// --------------------------------------------------------------------------
/**
* Get the query plan for the sql query
*
* @param string $sql
* @return string
*/
public function explain($sql)
{
return $sql;
}
// --------------------------------------------------------------------------
/**
* Random ordering keyword
*

View File

@ -41,6 +41,19 @@ class MySQL_SQL implements iDB_SQL {
// --------------------------------------------------------------------------
/**
* Get the query plan for the sql query
*
* @param string $sql
* @return string
*/
public function explain($sql)
{
return "EXPLAIN EXTENDED {$sql}";
}
// --------------------------------------------------------------------------
/**
* Random ordering keyword
*

View File

@ -36,6 +36,19 @@ class ODBC_SQL implements iDB_SQL {
// --------------------------------------------------------------------------
/**
* Get the query plan for the sql query
*
* @param string $sql
* @return string
*/
public function explain($sql)
{
return $sql;
}
// --------------------------------------------------------------------------
/**
* Random ordering keyword
*

View File

@ -42,6 +42,19 @@ class PgSQL_SQL implements iDB_SQL {
// --------------------------------------------------------------------------
/**
* Get the query plan for the sql query
*
* @param string $sql
* @return string
*/
public function explain($sql)
{
return "EXPLAIN VERBOSE {$sql}";
}
// --------------------------------------------------------------------------
/**
* Random ordering keyword
*

View File

@ -41,6 +41,19 @@ class SQLite_SQL implements iDB_SQL {
// --------------------------------------------------------------------------
/**
* Get the query plan for the sql query
*
* @param string $sql
* @return string
*/
public function explain($sql)
{
return "EXPLAIN QUERY PLAN {$sql}";
}
// --------------------------------------------------------------------------
/**
* Random ordering keyword
*

View File

@ -90,4 +90,5 @@ class FirebirdQBTest extends QBTest {
$this->assertTrue(is_array($res));
}
}

View File

@ -49,4 +49,35 @@ class MySQLQBTest extends QBTest {
{
$this->assertTrue(in_array('mysql', PDO::getAvailableDrivers()));
}
// --------------------------------------------------------------------------
public function testQueryExplain()
{
$query = $this->db->select('id, key as k, val')
->explain()
->where('id >', 1)
->where('id <', 900)
->get('create_test', 2, 1);
$res = $query->fetchAll(PDO::FETCH_ASSOC);
$expected = array (
array (
'id' => '1',
'select_type' => 'SIMPLE',
'table' => 'create_test',
'type' => 'range',
'possible_keys' => 'PRIMARY',
'key' => 'PRIMARY',
'key_len' => '4',
'ref' => NULL,
'rows' => '1',
'filtered' => '100.00',
'Extra' => 'Using where',
)
);
$this->assertEqual($expected, $res);
}
}

View File

@ -48,4 +48,43 @@ class PgSQLQBTest extends QBTest {
{
$this->assertTrue(in_array('pgsql', PDO::getAvailableDrivers()));
}
// --------------------------------------------------------------------------
public function testQueryExplain()
{
$query = $this->db->select('id, key as k, val')
->explain()
->where('id >', 1)
->where('id <', 900)
->get('create_test', 2, 1);
$res = $query->fetchAll(PDO::FETCH_ASSOC);
$expected = array (
array (
'QUERY PLAN' => 'Limit (cost=6.41..10.64 rows=2 width=68)',
),
array (
'QUERY PLAN' => ' Output: id, key, val',
),
array (
'QUERY PLAN' => ' -> Bitmap Heap Scan on public.create_test (cost=4.29..12.76 rows=4 width=68)',
),
array (
'QUERY PLAN' => ' Output: id, key, val',
),
array (
'QUERY PLAN' => ' Recheck Cond: ((create_test.id > 1) AND (create_test.id < 900))',
),
array (
'QUERY PLAN' => ' -> Bitmap Index Scan on create_test_pkey (cost=0.00..4.29 rows=4 width=0)',
),
array (
'QUERY PLAN' => ' Index Cond: ((create_test.id > 1) AND (create_test.id < 900))',
),
);
$this->assertEqual($expected, $res);
}
}

View File

@ -60,4 +60,28 @@
$this->assertNull($query);
}
// --------------------------------------------------------------------------
public function testQueryExplain()
{
$query = $this->db->select('id, key as k, val')
->explain()
->where('id >', 1)
->where('id <', 900)
->get('create_test', 2, 1);
$res = $query->fetchAll(PDO::FETCH_ASSOC);
$expected = array (
array (
'selectid' => '0',
'order' => '0',
'from' => '0',
'detail' => 'SEARCH TABLE create_test USING INTEGER PRIMARY KEY (rowid>? AND rowid<?)',
),
);
$this->assertEqual($expected, $res);
}
}