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    
025    package com.ninja_squad.dbsetup.operation;
026    
027    import java.sql.Connection;
028    import java.sql.SQLException;
029    import java.sql.Statement;
030    import java.util.ArrayList;
031    import java.util.Arrays;
032    import java.util.List;
033    
034    import javax.annotation.Nonnull;
035    import javax.annotation.concurrent.Immutable;
036    
037    import com.ninja_squad.dbsetup.bind.BinderConfiguration;
038    import com.ninja_squad.dbsetup.util.Preconditions;
039    
040    /**
041     * An operation which deletes everything from a given database table.
042     * @author JB Nizet
043     */
044    @Immutable
045    public final class DeleteAll implements Operation {
046    
047        private final String table;
048    
049        protected DeleteAll(String table) {
050            Preconditions.checkNotNull(table, "table may not be null");
051            this.table = table;
052        }
053    
054        @Override
055        public void execute(Connection connection, BinderConfiguration configuration) throws SQLException {
056            Statement stmt = connection.createStatement();
057            try {
058                stmt.executeUpdate("delete from " + table);
059            }
060            finally {
061                stmt.close();
062            }
063        }
064    
065        /**
066         * Returns an operation which deletes all the rows from the given table.
067         * @param table the table to delete everything from.
068         */
069        public static DeleteAll from(@Nonnull String table) {
070            return new DeleteAll(table);
071        }
072    
073        /**
074         * Returns a composite operation which deletes all the rows from the given tables, in the same order as the
075         * tables. If A has a foreign key to B, which has a foreign key to C, tables should be listed in the following
076         * order: A, B, C. Otherwise, referential constraint will break. If there is a cycle in the dependencies, you might
077         * want to use a sequence of {@link SqlOperation} to disable the foreign key constraints, then delete everything
078         * from the tables, then use another sequence of {@link SqlOperation} to re-enable the foreign key constraints.
079         * @param tables the tables to delete everything from.
080         */
081        public static Operation from(@Nonnull String... tables) {
082            return from(Arrays.asList(tables));
083        }
084    
085        /**
086         * Returns a composite operation which deletes all the rows from the given tables, in the same order as the
087         * tables. If A has a foreign key to B, which has a foreign key to C, tables should be listed in the following
088         * order: A, B, C. Otherwise, referential constraint will break. If there is a cycle in the dependencies, you might
089         * want to use a sequence of {@link SqlOperation} to disable the foreign key constraints, then delete everything
090         * from the tables, then use another sequence of {@link SqlOperation} to re-enable the foreign key constraints.
091         * @param tables the tables to delete everything from.
092         */
093        public static Operation from(@Nonnull List<String> tables) {
094            List<DeleteAll> operations = new ArrayList<DeleteAll>(tables.size());
095            for (String table : tables) {
096                operations.add(new DeleteAll(table));
097            }
098            return CompositeOperation.sequenceOf(operations);
099        }
100    
101        @Override
102        public String toString() {
103            return "delete from " + table;
104        }
105    
106        @Override
107        public int hashCode() {
108            return table.hashCode();
109        }
110    
111        @Override
112        public boolean equals(Object obj) {
113            if (this == obj) {
114                return true;
115            }
116            if (obj == null) {
117                return false;
118            }
119            if (getClass() != obj.getClass()) {
120                return false;
121            }
122            DeleteAll other = (DeleteAll) obj;
123            return this.table.equals(other.table);
124        }
125    }