001/*
002 * The MIT License
003 *
004 * Copyright (c) 2012, Ninja Squad
005 *
006 * Permission is hereby granted, free of charge, to any person obtaining a copy
007 * of this software and associated documentation files (the "Software"), to deal
008 * in the Software without restriction, including without limitation the rights
009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010 * copies of the Software, and to permit persons to whom the Software is
011 * furnished to do so, subject to the following conditions:
012 *
013 * The above copyright notice and this permission notice shall be included in
014 * all copies or substantial portions of the Software.
015 *
016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
022 * THE SOFTWARE.
023 */
024
025package com.ninja_squad.dbsetup.operation;
026
027import java.sql.Connection;
028import java.sql.SQLException;
029import java.sql.Statement;
030import java.util.ArrayList;
031import java.util.Arrays;
032import java.util.List;
033
034import javax.annotation.Nonnull;
035import javax.annotation.concurrent.Immutable;
036
037import com.ninja_squad.dbsetup.bind.BinderConfiguration;
038
039/**
040 * An operation which deletes everything from a given database table using a TRUNCATE statement., which is sometimes
041 * faster that using a DELETE statement.
042 * @author JB Nizet
043 */
044@Immutable
045public final class Truncate implements Operation {
046
047    private final String tableToTruncate;
048
049    private Truncate(String table) {
050        this.tableToTruncate = table;
051    }
052
053    @Override
054    public void execute(Connection connection, BinderConfiguration configuration) throws SQLException {
055        Statement stmt = connection.createStatement();
056        try {
057            stmt.executeUpdate("truncate table " + tableToTruncate);
058        }
059        finally {
060            stmt.close();
061        }
062    }
063
064    /**
065     * Returns an operation which truncates the given table.
066     * @param table the table to delete everything from.
067     */
068    public static Truncate table(@Nonnull String table) {
069        return new Truncate(table);
070    }
071
072    /**
073     * Returns a composite operation which truncates the given tables, in the same order as the
074     * tables. If A has a foreign key to B, which has a foreign key to C, tables should be listed in the following
075     * order: A, B, C. Otherwise, referential constraint will break. If there is a cycle in the dependencies, you might
076     * want to use a sequence of {@link SqlOperation} to disable the foreign key constraints, then truncate the tables,
077     * then use another sequence of {@link SqlOperation} to re-enable the foreign key constraints.
078     * @param tables the tables to truncate.
079     */
080    public static Operation tables(String... tables) {
081        return tables(Arrays.asList(tables));
082    }
083
084    /**
085     * Returns a composite operation which truncates the given tables, in the same order as the
086     * tables. If A has a foreign key to B, which has a foreign key to C, tables should be listed in the following
087     * order: A, B, C. Otherwise, referential constraint will break. If there is a cycle in the dependencies, you might
088     * want to use a sequence of {@link SqlOperation} to disable the foreign key constraints, then truncate the tables,
089     * then use another sequence of {@link SqlOperation} to re-enable the foreign key constraints.
090     * @param tables the tables to truncate.
091     */
092    public static Operation tables(List<String> tables) {
093        List<Truncate> operations = new ArrayList<Truncate>(tables.size());
094        for (String table : tables) {
095            operations.add(new Truncate(table));
096        }
097        return CompositeOperation.sequenceOf(operations);
098    }
099
100    @Override
101    public String toString() {
102        return "truncate table " + tableToTruncate;
103    }
104
105    @Override
106    public int hashCode() {
107        return tableToTruncate.hashCode();
108    }
109
110    @Override
111    public boolean equals(Object obj) {
112        if (this == obj) {
113            return true;
114        }
115        if (obj == null) {
116            return false;
117        }
118        if (getClass() != obj.getClass()) {
119            return false;
120        }
121        Truncate other = (Truncate) obj;
122        return this.tableToTruncate.equals(other.tableToTruncate);
123    }
124}