/** * Delete this data object. * $this->onBeforeDelete() gets called. * Note that in Versioned objects, both Stage and Live will be deleted. * @uses DataExtension->augmentSQL() */ public function delete() { $this->brokenOnDelete = true; $this->onBeforeDelete(); if ($this->brokenOnDelete) { user_error("{$this->class} has a broken onBeforeDelete() function." . " Make sure that you call parent::onBeforeDelete().", E_USER_ERROR); } // Deleting a record without an ID shouldn't do anything if (!$this->ID) { throw new LogicException("DataObject::delete() called on a DataObject without an ID"); } // TODO: This is quite ugly. To improve: // - move the details of the delete code in the DataQuery system // - update the code to just delete the base table, and rely on cascading deletes in the DB to do the rest // obviously, that means getting requireTable() to configure cascading deletes ;-) $srcQuery = DataList::create($this->class, $this->model)->where("ID = {$this->ID}")->dataQuery()->query(); foreach ($srcQuery->queriedTables() as $table) { $delete = new SQLDelete("\"{$table}\"", array('"ID"' => $this->ID)); $delete->execute(); } // Remove this item out of any caches $this->flushCache(); $this->onAfterDelete(); $this->OldID = $this->ID; $this->ID = 0; }
/** * Remove all items from this many-many join. To remove a subset of items, * filter it first. * * @return void */ public function removeAll() { // Remove the join to the join table to avoid MySQL row locking issues. $query = $this->dataQuery(); $foreignFilter = $query->getQueryParam('Foreign.Filter'); $query->removeFilterOn($foreignFilter); // Select ID column $selectQuery = $query->query(); $dataClassIDColumn = DataObject::getSchema()->sqlColumnForField($this->dataClass(), 'ID'); $selectQuery->setSelect($dataClassIDColumn); $from = $selectQuery->getFrom(); unset($from[$this->joinTable]); $selectQuery->setFrom($from); $selectQuery->setOrderBy(); // ORDER BY in subselects breaks MS SQL Server and is not necessary here $selectQuery->setDistinct(false); // Use a sub-query as SQLite does not support setting delete targets in // joined queries. $delete = new SQLDelete(); $delete->setFrom("\"{$this->joinTable}\""); $delete->addWhere($this->foreignIDFilter()); $subSelect = $selectQuery->sql($parameters); $delete->addWhere(array("\"{$this->joinTable}\".\"{$this->localKey}\" IN ({$subSelect})" => $parameters)); $delete->execute(); }
/** * Remove all fixtures previously defined through {@link createObject()} * or {@link createRaw()}, both from the internal fixture mapping and the database. * If the $class argument is set, limit clearing to items of this class. * * @param String $class */ public function clear($limitToClass = null) { $classes = $limitToClass ? array($limitToClass) : array_keys($this->fixtures); foreach ($classes as $class) { $ids = $this->fixtures[$class]; foreach ($ids as $id => $dbId) { if (class_exists($class)) { $class::get()->byId($dbId)->delete(); } else { $table = $class; $delete = new SQLDelete("\"{$table}\"", array("\"{$table}\".\"ID\"" => $dbId)); $delete->execute(); } unset($this->fixtures[$class][$id]); } } }
/** * Return the DELETE clause ready for inserting into a query. * * @param SQLExpression $query The expression object to build from * @param array $parameters Out parameter for the resulting query parameters * @return string Completed delete part of statement */ public function buildDeleteFragment(SQLDelete $query, array &$parameters) { $text = 'DELETE'; // If doing a multiple table delete then list the target deletion tables here // Note that some schemas don't support multiple table deletion $delete = $query->getDelete(); if (!empty($delete)) { $text .= ' ' . implode(', ', $delete); } return $text; }