source: pro-violet-viettel/sourcecode/application/libraries/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php @ 345

Last change on this file since 345 was 345, checked in by quyenla, 11 years ago

collaborator page

File size: 5.2 KB
Line 
1<?php
2/*
3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14 *
15 * This software consists of voluntary contributions made by many individuals
16 * and is licensed under the LGPL. For more information, see
17 * <http://www.doctrine-project.org>.
18 */
19
20namespace Doctrine\ORM\Query\Exec;
21
22use Doctrine\DBAL\Connection,
23    Doctrine\ORM\Query\AST;
24
25/**
26 * Executes the SQL statements for bulk DQL DELETE statements on classes in
27 * Class Table Inheritance (JOINED).
28 *
29 * @author      Roman Borschel <roman@code-factory.org>
30 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
31 * @link        http://www.doctrine-project.org
32 * @since       2.0
33 */
34class MultiTableDeleteExecutor extends AbstractSqlExecutor
35{
36    private $_createTempTableSql;
37    private $_dropTempTableSql;
38    private $_insertSql;
39
40    /**
41     * Initializes a new <tt>MultiTableDeleteExecutor</tt>.
42     *
43     * @param Node $AST The root AST node of the DQL query.
44     * @param SqlWalker $sqlWalker The walker used for SQL generation from the AST.
45     * @internal Any SQL construction and preparation takes place in the constructor for
46     *           best performance. With a query cache the executor will be cached.
47     */
48    public function __construct(AST\Node $AST, $sqlWalker)
49    {
50        $em = $sqlWalker->getEntityManager();
51        $conn = $em->getConnection();
52        $platform = $conn->getDatabasePlatform();
53
54        $primaryClass = $em->getClassMetadata($AST->deleteClause->abstractSchemaName);
55        $primaryDqlAlias = $AST->deleteClause->aliasIdentificationVariable;
56        $rootClass = $em->getClassMetadata($primaryClass->rootEntityName);
57
58        $tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName());
59        $idColumnNames = $rootClass->getIdentifierColumnNames();
60        $idColumnList = implode(', ', $idColumnNames);
61
62        // 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause()
63        $sqlWalker->setSQLTableAlias($primaryClass->getTableName(), 't0', $primaryDqlAlias);
64
65        $this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')'
66                . ' SELECT t0.' . implode(', t0.', $idColumnNames);
67
68        $rangeDecl = new AST\RangeVariableDeclaration($primaryClass->name, $primaryDqlAlias);
69        $fromClause = new AST\FromClause(array(new AST\IdentificationVariableDeclaration($rangeDecl, null, array())));
70        $this->_insertSql .= $sqlWalker->walkFromClause($fromClause);
71
72        // Append WHERE clause, if there is one.
73        if ($AST->whereClause) {
74            $this->_insertSql .= $sqlWalker->walkWhereClause($AST->whereClause);
75        }
76
77        // 2. Create ID subselect statement used in DELETE ... WHERE ... IN (subselect)
78        $idSubselect = 'SELECT ' . $idColumnList . ' FROM ' . $tempTable;
79
80        // 3. Create and store DELETE statements
81        $classNames = array_merge($primaryClass->parentClasses, array($primaryClass->name), $primaryClass->subClasses);
82        foreach (array_reverse($classNames) as $className) {
83            $tableName = $em->getClassMetadata($className)->getQuotedTableName($platform);
84            $this->_sqlStatements[] = 'DELETE FROM ' . $tableName
85                    . ' WHERE (' . $idColumnList . ') IN (' . $idSubselect . ')';
86        }
87
88        // 4. Store DDL for temporary identifier table.
89        $columnDefinitions = array();
90        foreach ($idColumnNames as $idColumnName) {
91            $columnDefinitions[$idColumnName] = array(
92                'notnull' => true,
93                'type' => \Doctrine\DBAL\Types\Type::getType($rootClass->getTypeOfColumn($idColumnName))
94            );
95        }
96        $this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' ('
97                . $platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
98        $this->_dropTempTableSql = $platform->getDropTemporaryTableSQL($tempTable);
99    }
100
101    /**
102     * {@inheritDoc}
103     */
104    public function execute(Connection $conn, array $params, array $types)
105    {
106        $numDeleted = 0;
107
108        // Create temporary id table
109        $conn->executeUpdate($this->_createTempTableSql);
110
111        // Insert identifiers
112        $numDeleted = $conn->executeUpdate($this->_insertSql, $params, $types);
113
114        // Execute DELETE statements
115        foreach ($this->_sqlStatements as $sql) {
116            $conn->executeUpdate($sql);
117        }
118
119        // Drop temporary table
120        $conn->executeUpdate($this->_dropTempTableSql);
121
122        return $numDeleted;
123    }
124}
Note: See TracBrowser for help on using the repository browser.