mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #4457 from tractorcow/pulls/4.0/no-query
API Remove SQLQuery
This commit is contained in:
commit
ef35c2bb6b
@ -175,7 +175,7 @@ Provided `filter` values are automatically escaped and do not require any escapi
|
||||
|
||||
## Lazy Loading
|
||||
|
||||
The `ORM` doesn't actually execute the [api:SQLQuery] until you iterate on the result with a `foreach()` or `<% loop %>`.
|
||||
The `ORM` doesn't actually execute the [api:SQLSelect] until you iterate on the result with a `foreach()` or `<% loop %>`.
|
||||
|
||||
It's smart enough to generate a single efficient query at the last moment in time without needing to post-process the
|
||||
result set in PHP. In `MySQL` the query generated by the ORM may look something like this
|
||||
|
@ -1,9 +1,9 @@
|
||||
title: SQLQuery
|
||||
summary: Write and modify direct database queries through SQLQuery.
|
||||
title: SQLSelect
|
||||
summary: Write and modify direct database queries through SQLSelect.
|
||||
|
||||
# SQLQuery
|
||||
# SQLSelect
|
||||
|
||||
A [api:SQLQuery] object represents a SQL query, which can be serialized into a SQL statement. Dealing with low-level
|
||||
A [api:SQLSelect] object represents a SQL query, which can be serialized into a SQL statement. Dealing with low-level
|
||||
SQL such as `mysql_query()` is not encouraged, since the ORM provides powerful abstraction API's.
|
||||
|
||||
For example, if you want to run a simple `COUNT` SQL statement, the following three statements are functionally
|
||||
@ -13,8 +13,8 @@ equivalent:
|
||||
// Through raw SQL.
|
||||
$count = DB::query('SELECT COUNT(*) FROM "Member"')->value();
|
||||
|
||||
// Through SQLQuery abstraction layer.
|
||||
$query = new SQLQuery();
|
||||
// Through SQLSelect abstraction layer.
|
||||
$query = new SQLSelect();
|
||||
$count = $query->setFrom('Member')->setSelect('COUNT(*)')->value();
|
||||
|
||||
// Through the ORM.
|
||||
@ -22,7 +22,7 @@ equivalent:
|
||||
|
||||
|
||||
<div class="info">
|
||||
The SQLQuery object is used by the SilverStripe ORM internally. By understanding SQLQuery, you can modify the SQL that
|
||||
The SQLSelect object is used by the SilverStripe ORM internally. By understanding SQLSelect, you can modify the SQL that
|
||||
the ORM creates.
|
||||
</div>
|
||||
|
||||
@ -31,12 +31,12 @@ the ORM creates.
|
||||
### Select
|
||||
|
||||
:::php
|
||||
$sqlQuery = new SQLQuery();
|
||||
$sqlQuery = new SQLSelect();
|
||||
$sqlQuery->setFrom('Player');
|
||||
$sqlQuery->selectField('FieldName', 'Name');
|
||||
$sqlQuery->selectField('YEAR("Birthday")', 'Birthyear');
|
||||
$sqlQuery->addLeftJoin('Team','"Player"."TeamID" = "Team"."ID"');
|
||||
$sqlQuery->addWhere('YEAR("Birthday") = 1982');
|
||||
$sqlQuery->addWhere(array('YEAR("Birthday") = ?' => 1982));
|
||||
|
||||
// $sqlQuery->setOrderBy(...);
|
||||
// $sqlQuery->setGroupBy(...);
|
||||
@ -66,7 +66,7 @@ The `$result` is an array lightly wrapped in a database-specific subclass of `[a
|
||||
### Insert / Update
|
||||
|
||||
<div class="alert" markdown="1">
|
||||
Currently not supported through the `SQLQuery` class, please use raw `DB::query()` calls instead.
|
||||
Currently not supported through the `SQLSelect` class, please use raw `DB::query()` calls instead.
|
||||
</div>
|
||||
|
||||
:::php
|
||||
@ -75,10 +75,10 @@ Currently not supported through the `SQLQuery` class, please use raw `DB::query(
|
||||
### Joins
|
||||
|
||||
:::php
|
||||
$sqlQuery = new SQLQuery();
|
||||
$sqlQuery = new SQLSelect();
|
||||
$sqlQuery->setFrom('Player');
|
||||
$sqlQuery->addSelect('COUNT("Player"."ID")');
|
||||
$sqlQuery->addWhere('"Team"."ID" = 99');
|
||||
$sqlQuery->addWhere(array('"Team"."ID" => 99));
|
||||
$sqlQuery->addLeftJoin('Team', '"Team"."ID" = "Player"."TeamID"');
|
||||
|
||||
$count = $sqlQuery->execute()->value();
|
||||
@ -88,7 +88,7 @@ Currently not supported through the `SQLQuery` class, please use raw `DB::query(
|
||||
Creates a map based on the first two columns of the query result.
|
||||
|
||||
:::php
|
||||
$sqlQuery = new SQLQuery();
|
||||
$sqlQuery = new SQLSelect();
|
||||
$sqlQuery->setFrom('Player');
|
||||
$sqlQuery->setSelect('ID');
|
||||
$sqlQuery->selectField('CONCAT("Name", ' - ', YEAR("Birthdate")', 'NameWithBirthyear');
|
||||
@ -108,7 +108,7 @@ Creates a map based on the first two columns of the query result.
|
||||
## API Documentation
|
||||
|
||||
* [api:DataObject]
|
||||
* [api:SQLQuery]
|
||||
* [api:SQLSelect]
|
||||
* [api:DB]
|
||||
* [api:Query]
|
||||
* [api:Database]
|
@ -33,7 +33,7 @@ Example:
|
||||
$records = DataObject::get_by_id('MyClass', 3);
|
||||
$records = DataObject::get_one('MyClass', array('"ID" = ?' => 3));
|
||||
$records = MyClass::get()->byID(3);
|
||||
$records = SQLQuery::create()->addWhere(array('"ID"' => 3))->execute();
|
||||
$records = SQLSelect::create()->addWhere(array('"ID"' => 3))->execute();
|
||||
|
||||
Parameterised updates and inserts are also supported, but the syntax is a little different
|
||||
|
||||
@ -98,7 +98,7 @@ As a rule of thumb, whenever you're creating SQL queries (or just chunks of SQL)
|
||||
but there may be cases where you need to take care of escaping yourself. See [coding-conventions](/getting_started/coding-conventions)
|
||||
and [datamodel](/developer_guides/model) for ways to parameterise, cast, and convert your data.
|
||||
|
||||
* `SQLQuery`
|
||||
* `SQLSelect`
|
||||
* `DB::query()`
|
||||
* `DB::prepared_query()`
|
||||
* `Director::urlParams()`
|
||||
|
@ -7,7 +7,7 @@ summary: Configure the search form within ModelAdmin using the SearchContext cla
|
||||
input parameters. [api:SearchContext] is intentionally decoupled from any controller-logic, it just receives a set of
|
||||
search parameters and an object class it acts on.
|
||||
|
||||
The default output of a [api:SearchContext] is either a [api:SQLQuery] object for further refinement, or a
|
||||
The default output of a [api:SearchContext] is either a [api:SQLSelect] object for further refinement, or a
|
||||
[api:DataObject] instance.
|
||||
|
||||
<div class="notice" markdown="1">
|
||||
@ -110,7 +110,7 @@ the `$fields` constructor parameter.
|
||||
### Pagination
|
||||
|
||||
For pagination records on multiple pages, you need to wrap the results in a
|
||||
`PaginatedList` object. This object is also passed the generated `SQLQuery`
|
||||
`PaginatedList` object. This object is also passed the generated `SQLSelect`
|
||||
in order to read page limit information. It is also passed the current
|
||||
`SS_HTTPRequest` object so it can read the current page from a GET var.
|
||||
|
||||
|
@ -130,6 +130,12 @@ forced on during development. If this is off, combined files is only enabled in
|
||||
|
||||
## Upgrading
|
||||
|
||||
### Update code that uses SQLQuery
|
||||
|
||||
Where your code once used SQLQuery you should now use SQLSelect in all cases, as this has been removed.
|
||||
|
||||
See the [3.2.0](3.2.0) upgrading notes for details on how existing code should be upgraded.
|
||||
|
||||
### New asset storage mechanism
|
||||
|
||||
File system has been abstracted into an abstract interface. By default, the out of the box filesystem
|
||||
|
@ -1,211 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package framework
|
||||
* @subpackage model
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representing a SQL SELECT query.
|
||||
* The various parts of the SQL query can be manipulated individually.
|
||||
*
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
class SQLQuery extends SQLSelect {
|
||||
|
||||
/**
|
||||
* If this is true, this statement will delete rather than select.
|
||||
*
|
||||
* @deprecated since version 4.0
|
||||
* @var boolean
|
||||
*/
|
||||
protected $isDelete = false;
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function __construct($select = "*", $from = array(), $where = array(), $orderby = array(),
|
||||
$groupby = array(), $having = array(), $limit = array()
|
||||
) {
|
||||
parent::__construct($select, $from, $where, $orderby, $groupby, $having, $limit);
|
||||
Deprecation::notice('4.0', 'Use SQLSelect instead');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function setDelete($value) {
|
||||
Deprecation::notice('4.0', 'SQLQuery::setDelete is deprecated. Use toDelete instead');
|
||||
$this->isDelete = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
public function getDelete() {
|
||||
Deprecation::notice('4.0', 'SQLQuery::getDelete is deprecated. Use SQLSelect or SQLDelete instead');
|
||||
return $this->isDelete;
|
||||
}
|
||||
|
||||
public function sql(&$parameters = array()) {
|
||||
return $this->toAppropriateExpression()->sql($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get helper class for flattening parameterised conditions
|
||||
*
|
||||
* @return SQLQuery_ParameterInjector
|
||||
*/
|
||||
protected function getParameterInjector() {
|
||||
return Injector::inst()->get('SQLQuery_ParameterInjector');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of SQL where conditions (flattened as a list of strings)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getWhere() {
|
||||
Deprecation::notice(
|
||||
'4.0',
|
||||
'SQLQuery::getWhere is non-parameterised for backwards compatibility. '.
|
||||
'Use ->toAppropriateExpression()->getWhere() instead'
|
||||
);
|
||||
$conditions = parent::getWhere();
|
||||
|
||||
// This is where any benefits of parameterised queries die
|
||||
return $this
|
||||
->getParameterInjector()
|
||||
->injectConditions($conditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this SQLQuery to a SQLExpression based on its
|
||||
* internal $delete state (Normally SQLSelect or SQLDelete)
|
||||
*
|
||||
* @return SQLExpression
|
||||
*/
|
||||
public function toAppropriateExpression() {
|
||||
if($this->isDelete) {
|
||||
return parent::toDelete();
|
||||
} else {
|
||||
return parent::toSelect();
|
||||
}
|
||||
}
|
||||
|
||||
public function toSelect() {
|
||||
if($this->isDelete) {
|
||||
user_error(
|
||||
'SQLQuery::toSelect called when $isDelete is true. Use ' .
|
||||
'toAppropriateExpression() instead',
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
return parent::toSelect();
|
||||
}
|
||||
|
||||
public function toDelete() {
|
||||
if(!$this->isDelete) {
|
||||
user_error(
|
||||
'SQLQuery::toDelete called when $isDelete is false. Use ' .
|
||||
'toAppropriateExpression() instead',
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
parent::toDelete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides conversion of parameterised SQL to flattened SQL strings
|
||||
*
|
||||
* @deprecated since version 4.0
|
||||
*/
|
||||
class SQLQuery_ParameterInjector {
|
||||
|
||||
public function __construct() {
|
||||
Deprecation::notice('4.0', "Use SQLSelect / SQLDelete instead of SQLQuery");
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of parameterised conditions, return a flattened
|
||||
* list of condition strings
|
||||
*
|
||||
* @param array $conditions
|
||||
* @return array
|
||||
*/
|
||||
public function injectConditions($conditions) {
|
||||
$result = array();
|
||||
foreach($conditions as $condition) {
|
||||
// Evaluate the result of SQLConditionGroup here
|
||||
if($condition instanceof SQLConditionGroup) {
|
||||
$predicate = $condition->conditionSQL($parameters);
|
||||
if(!empty($predicate)) {
|
||||
$result[] = $this->injectValues($predicate, $parameters);
|
||||
}
|
||||
} else {
|
||||
foreach($condition as $predicate => $parameters) {
|
||||
$result[] = $this->injectValues($predicate, $parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge parameters into a SQL prepared condition
|
||||
*
|
||||
* @param string $sql
|
||||
* @param array $parameters
|
||||
* @return string
|
||||
*/
|
||||
protected function injectValues($sql, $parameters) {
|
||||
$segments = preg_split('/\?/', $sql);
|
||||
$joined = '';
|
||||
$inString = false;
|
||||
for($i = 0; $i < count($segments); $i++) {
|
||||
// Append next segment
|
||||
$joined .= $segments[$i];
|
||||
// Don't add placeholder after last segment
|
||||
if($i === count($segments) - 1) {
|
||||
break;
|
||||
}
|
||||
// check string escape on previous fragment
|
||||
if($this->checkStringTogglesLiteral($segments[$i])) {
|
||||
$inString = !$inString;
|
||||
}
|
||||
// Append placeholder replacement
|
||||
if($inString) {
|
||||
// Literal questionmark
|
||||
$joined .= '?';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Encode and insert next parameter
|
||||
$next = array_shift($parameters);
|
||||
if(is_array($next) && isset($next['value'])) {
|
||||
$next = $next['value'];
|
||||
}
|
||||
$joined .= "'".Convert::raw2sql($next)."'";
|
||||
}
|
||||
return $joined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the SQL fragment either breaks into or out of a string literal
|
||||
* by counting single quotes
|
||||
*
|
||||
* Handles double-quote escaped quotes as well as slash escaped quotes
|
||||
*
|
||||
* @param string $input The SQL fragment
|
||||
* @return boolean True if the string breaks into or out of a string literal
|
||||
*/
|
||||
protected function checkStringTogglesLiteral($input) {
|
||||
// Remove escaped backslashes, count them!
|
||||
$input = preg_replace('/\\\\\\\\/', '', $input);
|
||||
// Count quotes
|
||||
$totalQuotes = substr_count($input, "'"); // Includes double quote escaped quotes
|
||||
$escapedQuotes = substr_count($input, "\\'");
|
||||
return (($totalQuotes - $escapedQuotes) % 2) !== 0;
|
||||
}
|
||||
}
|
@ -171,10 +171,10 @@ class DataQueryTest extends SapphireTest {
|
||||
}
|
||||
|
||||
public function testOrderByMultiple() {
|
||||
$dq = new DataQuery('SQLQueryTest_DO');
|
||||
$dq = new DataQuery('SQLSelectTest_DO');
|
||||
$dq = $dq->sort('"Name" ASC, MID("Name", 8, 1) DESC');
|
||||
$this->assertContains(
|
||||
'ORDER BY "SQLQueryTest_DO"."Name" ASC, "_SortColumn0" DESC',
|
||||
'ORDER BY "SQLSelectTest_DO"."Name" ASC, "_SortColumn0" DESC',
|
||||
$dq->sql($parameters)
|
||||
);
|
||||
}
|
||||
|
@ -4,14 +4,14 @@
|
||||
* @package framework
|
||||
* @subpackage tests
|
||||
*/
|
||||
class SQLQueryTest extends SapphireTest {
|
||||
class SQLSelectTest extends SapphireTest {
|
||||
|
||||
protected static $fixture_file = 'SQLQueryTest.yml';
|
||||
protected static $fixture_file = 'SQLSelectTest.yml';
|
||||
|
||||
protected $extraDataObjects = array(
|
||||
'SQLQueryTest_DO',
|
||||
'SQLQueryTestBase',
|
||||
'SQLQueryTestChild'
|
||||
'SQLSelectTest_DO',
|
||||
'SQLSelectTestBase',
|
||||
'SQLSelectTestChild'
|
||||
);
|
||||
|
||||
protected $oldDeprecation = null;
|
||||
@ -29,15 +29,15 @@ class SQLQueryTest extends SapphireTest {
|
||||
public function testCount() {
|
||||
|
||||
//basic counting
|
||||
$qry = SQLQueryTest_DO::get()->dataQuery()->getFinalisedQuery();
|
||||
$qry = SQLSelectTest_DO::get()->dataQuery()->getFinalisedQuery();
|
||||
$qry->setGroupBy('Common');
|
||||
$ids = $this->allFixtureIDs('SQLQueryTest_DO');
|
||||
$this->assertEquals(count($ids), $qry->count('"SQLQueryTest_DO"."ID"'));
|
||||
$ids = $this->allFixtureIDs('SQLSelectTest_DO');
|
||||
$this->assertEquals(count($ids), $qry->count('"SQLSelectTest_DO"."ID"'));
|
||||
|
||||
//test with `having`
|
||||
if (DB::get_conn() instanceof MySQLDatabase) {
|
||||
$qry->setHaving('"Date" > 2012-02-01');
|
||||
$this->assertEquals(1, $qry->count('"SQLQueryTest_DO"."ID"'));
|
||||
$this->assertEquals(1, $qry->count('"SQLSelectTest_DO"."ID"'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,7 +419,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
public function testSelectFirst() {
|
||||
// Test first from sequence
|
||||
$query = new SQLSelect();
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy('"Name"');
|
||||
$result = $query->firstRow()->execute();
|
||||
|
||||
@ -433,7 +433,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
|
||||
// Test first from empty sequence
|
||||
$query = new SQLSelect();
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy('"Name"');
|
||||
$query->setWhere(array('"Name"' => 'Nonexistent Object'));
|
||||
$result = $query->firstRow()->execute();
|
||||
@ -447,7 +447,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
|
||||
// Test that given the last item, the 'first' in this list matches the last
|
||||
$query = new SQLSelect();
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy('"Name"');
|
||||
$query->setLimit(1, 1);
|
||||
$result = $query->firstRow()->execute();
|
||||
@ -464,7 +464,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
public function testSelectLast() {
|
||||
// Test last in sequence
|
||||
$query = new SQLSelect();
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy('"Name"');
|
||||
$result = $query->lastRow()->execute();
|
||||
|
||||
@ -478,7 +478,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
|
||||
// Test last from empty sequence
|
||||
$query = new SQLSelect();
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy('"Name"');
|
||||
$query->setWhere(array("\"Name\" = 'Nonexistent Object'"));
|
||||
$result = $query->lastRow()->execute();
|
||||
@ -492,7 +492,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
|
||||
// Test that given the first item, the 'last' in this list matches the first
|
||||
$query = new SQLSelect();
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy('"Name"');
|
||||
$query->setLimit(1);
|
||||
$result = $query->lastRow()->execute();
|
||||
@ -511,7 +511,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
*/
|
||||
public function testAggregate() {
|
||||
$query = new SQLSelect('"Common"');
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setGroupBy('"Common"');
|
||||
|
||||
$queryClone = $query->aggregate('COUNT(*)', 'cnt');
|
||||
@ -524,7 +524,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
*/
|
||||
public function testAggregateNoOrderByIfNoLimit() {
|
||||
$query = new SQLSelect();
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy('Common');
|
||||
$query->setLimit(array());
|
||||
|
||||
@ -534,7 +534,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
$this->assertEquals(array(), $limit);
|
||||
|
||||
$query = new SQLSelect();
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy('Common');
|
||||
$query->setLimit(2);
|
||||
|
||||
@ -553,7 +553,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
public function testOrderByContainingAggregateAndLimitOffset() {
|
||||
$query = new SQLSelect();
|
||||
$query->setSelect(array('"Name"', '"Meta"'));
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy(array('MAX("Date")'));
|
||||
$query->setGroupBy(array('"Name"', '"Meta"'));
|
||||
$query->setLimit('1', '1');
|
||||
@ -576,7 +576,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
if(DB::get_conn() instanceof MySQLDatabase) {
|
||||
$query = new SQLSelect();
|
||||
$query->setSelect(array('"Name"', '"Meta"'));
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->setOrderBy(array('MID("Name", 8, 1) DESC', '"Name" ASC'));
|
||||
|
||||
$records = array();
|
||||
@ -629,7 +629,7 @@ class SQLQueryTest extends SapphireTest {
|
||||
public function testLimitSetFromClauseString() {
|
||||
$query = new SQLSelect();
|
||||
$query->setSelect('*');
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
|
||||
$query->setLimit('20 OFFSET 10');
|
||||
$limit = $query->getLimit();
|
||||
@ -639,22 +639,22 @@ class SQLQueryTest extends SapphireTest {
|
||||
|
||||
public function testParameterisedInnerJoins() {
|
||||
$query = new SQLSelect();
|
||||
$query->setSelect(array('"SQLQueryTest_DO"."Name"', '"SubSelect"."Count"'));
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setSelect(array('"SQLSelectTest_DO"."Name"', '"SubSelect"."Count"'));
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->addInnerJoin(
|
||||
'(SELECT "Title", COUNT(*) AS "Count" FROM "SQLQueryTestBase" GROUP BY "Title" HAVING "Title" NOT LIKE ?)',
|
||||
'"SQLQueryTest_DO"."Name" = "SubSelect"."Title"',
|
||||
'(SELECT "Title", COUNT(*) AS "Count" FROM "SQLSelectTestBase" GROUP BY "Title" HAVING "Title" NOT LIKE ?)',
|
||||
'"SQLSelectTest_DO"."Name" = "SubSelect"."Title"',
|
||||
'SubSelect',
|
||||
20,
|
||||
array('%MyName%')
|
||||
);
|
||||
$query->addWhere(array('"SQLQueryTest_DO"."Date" > ?' => '2012-08-08 12:00'));
|
||||
$query->addWhere(array('"SQLSelectTest_DO"."Date" > ?' => '2012-08-08 12:00'));
|
||||
|
||||
$this->assertSQLEquals('SELECT "SQLQueryTest_DO"."Name", "SubSelect"."Count"
|
||||
FROM "SQLQueryTest_DO" INNER JOIN (SELECT "Title", COUNT(*) AS "Count" FROM "SQLQueryTestBase"
|
||||
GROUP BY "Title" HAVING "Title" NOT LIKE ?) AS "SubSelect" ON "SQLQueryTest_DO"."Name" =
|
||||
$this->assertSQLEquals('SELECT "SQLSelectTest_DO"."Name", "SubSelect"."Count"
|
||||
FROM "SQLSelectTest_DO" INNER JOIN (SELECT "Title", COUNT(*) AS "Count" FROM "SQLSelectTestBase"
|
||||
GROUP BY "Title" HAVING "Title" NOT LIKE ?) AS "SubSelect" ON "SQLSelectTest_DO"."Name" =
|
||||
"SubSelect"."Title"
|
||||
WHERE ("SQLQueryTest_DO"."Date" > ?)', $query->sql($parameters)
|
||||
WHERE ("SQLSelectTest_DO"."Date" > ?)', $query->sql($parameters)
|
||||
);
|
||||
$this->assertEquals(array('%MyName%', '2012-08-08 12:00'), $parameters);
|
||||
$query->execute();
|
||||
@ -662,123 +662,29 @@ class SQLQueryTest extends SapphireTest {
|
||||
|
||||
public function testParameterisedLeftJoins() {
|
||||
$query = new SQLSelect();
|
||||
$query->setSelect(array('"SQLQueryTest_DO"."Name"', '"SubSelect"."Count"'));
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setSelect(array('"SQLSelectTest_DO"."Name"', '"SubSelect"."Count"'));
|
||||
$query->setFrom('"SQLSelectTest_DO"');
|
||||
$query->addLeftJoin(
|
||||
'(SELECT "Title", COUNT(*) AS "Count" FROM "SQLQueryTestBase" GROUP BY "Title" HAVING "Title" NOT LIKE ?)',
|
||||
'"SQLQueryTest_DO"."Name" = "SubSelect"."Title"',
|
||||
'(SELECT "Title", COUNT(*) AS "Count" FROM "SQLSelectTestBase" GROUP BY "Title" HAVING "Title" NOT LIKE ?)',
|
||||
'"SQLSelectTest_DO"."Name" = "SubSelect"."Title"',
|
||||
'SubSelect',
|
||||
20,
|
||||
array('%MyName%')
|
||||
);
|
||||
$query->addWhere(array('"SQLQueryTest_DO"."Date" > ?' => '2012-08-08 12:00'));
|
||||
$query->addWhere(array('"SQLSelectTest_DO"."Date" > ?' => '2012-08-08 12:00'));
|
||||
|
||||
$this->assertSQLEquals('SELECT "SQLQueryTest_DO"."Name", "SubSelect"."Count"
|
||||
FROM "SQLQueryTest_DO" LEFT JOIN (SELECT "Title", COUNT(*) AS "Count" FROM "SQLQueryTestBase"
|
||||
GROUP BY "Title" HAVING "Title" NOT LIKE ?) AS "SubSelect" ON "SQLQueryTest_DO"."Name" =
|
||||
$this->assertSQLEquals('SELECT "SQLSelectTest_DO"."Name", "SubSelect"."Count"
|
||||
FROM "SQLSelectTest_DO" LEFT JOIN (SELECT "Title", COUNT(*) AS "Count" FROM "SQLSelectTestBase"
|
||||
GROUP BY "Title" HAVING "Title" NOT LIKE ?) AS "SubSelect" ON "SQLSelectTest_DO"."Name" =
|
||||
"SubSelect"."Title"
|
||||
WHERE ("SQLQueryTest_DO"."Date" > ?)', $query->sql($parameters)
|
||||
WHERE ("SQLSelectTest_DO"."Date" > ?)', $query->sql($parameters)
|
||||
);
|
||||
$this->assertEquals(array('%MyName%', '2012-08-08 12:00'), $parameters);
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test deprecation of SQLQuery::getWhere working appropriately
|
||||
*/
|
||||
public function testDeprecatedGetWhere() {
|
||||
// Temporarily disable deprecation
|
||||
Deprecation::notification_version(null);
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->setSelect(array('"SQLQueryTest_DO"."Name"'));
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->addWhere(array(
|
||||
'"SQLQueryTest_DO"."Date" > ?' => '2012-08-08 12:00'
|
||||
));
|
||||
$query->addWhere('"SQLQueryTest_DO"."Name" = \'Richard\'');
|
||||
$query->addWhere(array(
|
||||
'"SQLQueryTest_DO"."Meta" IN (?, \'Who?\', ?)' => array('Left', 'Right')
|
||||
));
|
||||
|
||||
$expectedSQL = <<<EOS
|
||||
SELECT "SQLQueryTest_DO"."Name"
|
||||
FROM "SQLQueryTest_DO"
|
||||
WHERE ("SQLQueryTest_DO"."Date" > ?)
|
||||
AND ("SQLQueryTest_DO"."Name" = 'Richard')
|
||||
AND ("SQLQueryTest_DO"."Meta" IN (?, 'Who?', ?))
|
||||
EOS
|
||||
;
|
||||
$expectedParameters = array('2012-08-08 12:00', 'Left', 'Right');
|
||||
|
||||
|
||||
// Check sql evaluation of this query maintains the parameters
|
||||
$sql = $query->sql($parameters);
|
||||
$this->assertSQLEquals($expectedSQL, $sql);
|
||||
$this->assertEquals($expectedParameters, $parameters);
|
||||
|
||||
// Check that ->toAppropriateExpression()->setWhere doesn't modify the query
|
||||
$query->setWhere($query->toAppropriateExpression()->getWhere());
|
||||
$sql = $query->sql($parameters);
|
||||
$this->assertSQLEquals($expectedSQL, $sql);
|
||||
$this->assertEquals($expectedParameters, $parameters);
|
||||
|
||||
// Check that getWhere are all flattened queries
|
||||
$expectedFlattened = array(
|
||||
'"SQLQueryTest_DO"."Date" > \'2012-08-08 12:00\'',
|
||||
'"SQLQueryTest_DO"."Name" = \'Richard\'',
|
||||
'"SQLQueryTest_DO"."Meta" IN (\'Left\', \'Who?\', \'Right\')'
|
||||
);
|
||||
$this->assertEquals($expectedFlattened, $query->getWhere());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test deprecation of SQLQuery::setDelete/getDelete
|
||||
*/
|
||||
public function testDeprecatedSetDelete() {
|
||||
// Temporarily disable deprecation
|
||||
Deprecation::notification_version(null);
|
||||
|
||||
$query = new SQLQuery();
|
||||
$query->setSelect(array('"SQLQueryTest_DO"."Name"'));
|
||||
$query->setFrom('"SQLQueryTest_DO"');
|
||||
$query->setWhere(array('"SQLQueryTest_DO"."Name"' => 'Andrew'));
|
||||
|
||||
// Check SQL for select
|
||||
$this->assertSQLEquals(<<<EOS
|
||||
SELECT "SQLQueryTest_DO"."Name" FROM "SQLQueryTest_DO"
|
||||
WHERE ("SQLQueryTest_DO"."Name" = ?)
|
||||
EOS
|
||||
,
|
||||
$query->sql($parameters)
|
||||
);
|
||||
$this->assertEquals(array('Andrew'), $parameters);
|
||||
|
||||
// Check setDelete works
|
||||
$query->setDelete(true);
|
||||
$this->assertSQLEquals(<<<EOS
|
||||
DELETE FROM "SQLQueryTest_DO"
|
||||
WHERE ("SQLQueryTest_DO"."Name" = ?)
|
||||
EOS
|
||||
,
|
||||
$query->sql($parameters)
|
||||
);
|
||||
$this->assertEquals(array('Andrew'), $parameters);
|
||||
|
||||
// Check that setDelete back to false restores the state
|
||||
$query->setDelete(false);
|
||||
$this->assertSQLEquals(<<<EOS
|
||||
SELECT "SQLQueryTest_DO"."Name" FROM "SQLQueryTest_DO"
|
||||
WHERE ("SQLQueryTest_DO"."Name" = ?)
|
||||
EOS
|
||||
,
|
||||
$query->sql($parameters)
|
||||
);
|
||||
$this->assertEquals(array('Andrew'), $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
class SQLQueryTest_DO extends DataObject implements TestOnly {
|
||||
class SQLSelectTest_DO extends DataObject implements TestOnly {
|
||||
private static $db = array(
|
||||
"Name" => "Varchar",
|
||||
"Meta" => "Varchar",
|
||||
@ -787,17 +693,14 @@ class SQLQueryTest_DO extends DataObject implements TestOnly {
|
||||
);
|
||||
}
|
||||
|
||||
class SQLQueryTestBase extends DataObject implements TestOnly {
|
||||
class SQLSelectTestBase extends DataObject implements TestOnly {
|
||||
private static $db = array(
|
||||
"Title" => "Varchar",
|
||||
);
|
||||
}
|
||||
|
||||
class SQLQueryTestChild extends SQLQueryTestBase {
|
||||
class SQLSelectTestChild extends SQLSelectTestBase {
|
||||
private static $db = array(
|
||||
"Name" => "Varchar",
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
SQLQueryTest_DO:
|
||||
SQLSelectTest_DO:
|
||||
test1:
|
||||
Name: 'Object 1'
|
||||
Meta: 'Details 1'
|
Loading…
Reference in New Issue
Block a user