#496516 by Crell and Berdir: Moved query_alter() into a preExecute() method, so that modules can know the final query/arguments before they are run.
parent
e832899658
commit
fd164e9d02
|
|
@ -433,6 +433,8 @@ class InsertQuery extends Query {
|
||||||
* in multi-insert loops.
|
* in multi-insert loops.
|
||||||
*/
|
*/
|
||||||
public function execute() {
|
public function execute() {
|
||||||
|
// If validation fails, simply return NULL.
|
||||||
|
// Note that validation routines in preExecute() may throw exceptions instead.
|
||||||
if (!$this->preExecute()) {
|
if (!$this->preExecute()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -489,7 +491,7 @@ class InsertQuery extends Query {
|
||||||
* @return
|
* @return
|
||||||
* TRUE if the validation was successful, FALSE if not.
|
* TRUE if the validation was successful, FALSE if not.
|
||||||
*/
|
*/
|
||||||
protected function preExecute() {
|
public function preExecute() {
|
||||||
// Confirm that the user did not try to specify an identical
|
// Confirm that the user did not try to specify an identical
|
||||||
// field and default field.
|
// field and default field.
|
||||||
if (array_intersect($this->insertFields, $this->defaultFields)) {
|
if (array_intersect($this->insertFields, $this->defaultFields)) {
|
||||||
|
|
@ -721,13 +723,29 @@ class MergeQuery extends Query {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute() {
|
/**
|
||||||
|
* Generic preparation and validation for a MERGE query.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* TRUE if the validation was successful, FALSE if not.
|
||||||
|
*/
|
||||||
|
public function preExecute() {
|
||||||
|
|
||||||
// A merge query without any key field is invalid.
|
// A merge query without any key field is invalid.
|
||||||
if (count($this->keyFields) == 0) {
|
if (count($this->keyFields) == 0) {
|
||||||
throw new InvalidMergeQueryException("You need to specify key fields before executing a merge query");
|
throw new InvalidMergeQueryException("You need to specify key fields before executing a merge query");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute() {
|
||||||
|
// If validation fails, simply return NULL.
|
||||||
|
// Note that validation routines in preExecute() may throw exceptions instead.
|
||||||
|
if (!$this->preExecute()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// In the degenerate case of this query type, we have to run multiple
|
// In the degenerate case of this query type, we have to run multiple
|
||||||
// queries as there is no universal single-query mechanism that will work.
|
// queries as there is no universal single-query mechanism that will work.
|
||||||
// Our degenerate case is not designed for performance efficiency but
|
// Our degenerate case is not designed for performance efficiency but
|
||||||
|
|
|
||||||
|
|
@ -358,6 +358,19 @@ interface SelectQueryInterface extends QueryConditionInterface, QueryAlterableIn
|
||||||
*/
|
*/
|
||||||
public function countQuery();
|
public function countQuery();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if preExecute() has already been called on that object.
|
||||||
|
*/
|
||||||
|
public function isPrepared();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic preparation and validation for a SELECT query.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* TRUE if the validation was successful, FALSE if not.
|
||||||
|
*/
|
||||||
|
public function preExecute(SelectQueryInterface $query = NULL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone magic method.
|
* Clone magic method.
|
||||||
*
|
*
|
||||||
|
|
@ -501,7 +514,27 @@ class SelectQueryExtender implements SelectQueryInterface {
|
||||||
return $this->query->getArguments();
|
return $this->query->getArguments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isPrepared() {
|
||||||
|
return $this->query->isPrepared();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function preExecute(SelectQueryInterface $query = NULL) {
|
||||||
|
// If no query object is passed in, use $this.
|
||||||
|
if (is_null($query)) {
|
||||||
|
$query = $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->query->preExecute($query);
|
||||||
|
}
|
||||||
|
|
||||||
public function execute() {
|
public function execute() {
|
||||||
|
// By calling preExecute() here, we force it to preprocess the extender
|
||||||
|
// object rather than just the base query object. That means
|
||||||
|
// hook_query_alter() gets access to the extended object.
|
||||||
|
if (!$this->preExecute($this)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->query->execute();
|
return $this->query->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -718,6 +751,12 @@ class SelectQuery extends Query implements SelectQueryInterface {
|
||||||
*/
|
*/
|
||||||
protected $range;
|
protected $range;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if preExecute() has already been called.
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $prepared = FALSE;
|
||||||
|
|
||||||
public function __construct($table, $alias = NULL, DatabaseConnection $connection, $options = array()) {
|
public function __construct($table, $alias = NULL, DatabaseConnection $connection, $options = array()) {
|
||||||
$options['return'] = Database::RETURN_STATEMENT;
|
$options['return'] = Database::RETURN_STATEMENT;
|
||||||
parent::__construct($connection, $options);
|
parent::__construct($connection, $options);
|
||||||
|
|
@ -880,14 +919,46 @@ class SelectQuery extends Query implements SelectQueryInterface {
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute() {
|
/**
|
||||||
|
* Indicates if preExecute() has already been called on that object.
|
||||||
|
*/
|
||||||
|
public function isPrepared() {
|
||||||
|
return $this->prepared;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic preparation and validation for a SELECT query.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* TRUE if the validation was successful, FALSE if not.
|
||||||
|
*/
|
||||||
|
public function preExecute(SelectQueryInterface $query = NULL) {
|
||||||
|
// If no query object is passed in, use $this.
|
||||||
|
if (is_null($query)) {
|
||||||
|
$query = $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only execute this once.
|
||||||
|
if ($query->isPrepared()) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Modules may alter all queries or only those having a particular tag.
|
// Modules may alter all queries or only those having a particular tag.
|
||||||
drupal_alter('query', $this);
|
drupal_alter('query', $query);
|
||||||
if (isset($this->alterTags)) {
|
if (isset($this->alterTags)) {
|
||||||
foreach ($this->alterTags as $tag => $value) {
|
foreach ($this->alterTags as $tag => $value) {
|
||||||
drupal_alter("query_$tag", $this);
|
drupal_alter("query_$tag", $query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return $this->prepared = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute() {
|
||||||
|
// If validation fails, simply return NULL.
|
||||||
|
// Note that validation routines in preExecute() may throw exceptions instead.
|
||||||
|
if (!$this->preExecute()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
$args = $this->getArguments();
|
$args = $this->getArguments();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,14 @@ class PagerDefault extends SelectQueryExtender {
|
||||||
*/
|
*/
|
||||||
protected $customCountQuery = FALSE;
|
protected $customCountQuery = FALSE;
|
||||||
|
|
||||||
|
public function __construct(SelectQueryInterface $query, DatabaseConnection $connection) {
|
||||||
|
parent::__construct($query, $connection);
|
||||||
|
|
||||||
|
// Add pager tag. Do this here to ensure that it is always added before
|
||||||
|
// preExecute() is called.
|
||||||
|
$this->addTag('pager');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override the execute method.
|
* Override the execute method.
|
||||||
*
|
*
|
||||||
|
|
@ -52,6 +60,13 @@ class PagerDefault extends SelectQueryExtender {
|
||||||
public function execute() {
|
public function execute() {
|
||||||
global $pager_page_array, $pager_total, $pager_total_items, $pager_limits;
|
global $pager_page_array, $pager_total, $pager_total_items, $pager_limits;
|
||||||
|
|
||||||
|
// Add convenience tag to mark that this is an extended query. We have to
|
||||||
|
// do this in the constructor to ensure that it is set before preExecute()
|
||||||
|
// gets called.
|
||||||
|
if (!$this->preExecute($this)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// A NULL limit is the "kill switch" for pager queries.
|
// A NULL limit is the "kill switch" for pager queries.
|
||||||
if (empty($this->limit)) {
|
if (empty($this->limit)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,22 @@ class TableSort extends SelectQueryExtender {
|
||||||
*/
|
*/
|
||||||
protected $header = array();
|
protected $header = array();
|
||||||
|
|
||||||
public function execute() {
|
public function __construct(SelectQueryInterface $query, DatabaseConnection $connection) {
|
||||||
return $this->query->execute();
|
parent::__construct($query, $connection);
|
||||||
|
|
||||||
|
// Add convenience tag to mark that this is an extended query. We have to
|
||||||
|
// do this in the constructor to ensure that it is set before preExecute()
|
||||||
|
// gets called.
|
||||||
|
$this->addTag('tablesort');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order the query based on a header array.
|
||||||
|
*
|
||||||
|
* @see theme_table()
|
||||||
|
* @param $header
|
||||||
|
* Table header array.
|
||||||
|
*/
|
||||||
public function orderByHeader(Array $header) {
|
public function orderByHeader(Array $header) {
|
||||||
$this->header = $header;
|
$this->header = $header;
|
||||||
$ts = $this->init();
|
$ts = $this->init();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue