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;
038import com.ninja_squad.dbsetup.util.Preconditions;
039
040/**
041 * An operation which simply executes a SQL statement (using {@link Statement#executeUpdate(String)}). It can be useful,
042 * for example, to disable or re-enable constraints before/after deleting everything from tables, or inserting into
043 * tables having cross references.
044 * @author JB Nizet
045 */
046@Immutable
047public final class SqlOperation implements Operation {
048
049    private final String sql;
050
051    /**
052     * Constructor
053     * @param sql the SQL query to execute
054     */
055    private SqlOperation(String sql) {
056        Preconditions.checkNotNull(sql, "sql may not be null");
057        this.sql = sql;
058    }
059
060    @Override
061    public void execute(Connection connection, BinderConfiguration configuration) throws SQLException {
062        Statement stmt = connection.createStatement();
063        try {
064            stmt.executeUpdate(sql);
065        }
066        finally {
067            stmt.close();
068        }
069    }
070
071    /**
072     * Creates a SqlOperation for the given SQL statement
073     * @param sqlStatement the SQL statement to execute
074     * @return the created SqlOperation
075     */
076    public static SqlOperation of(@Nonnull String sqlStatement) {
077        return new SqlOperation(sqlStatement);
078    }
079
080    /**
081     * Creates a sequence of SqlOperation for the given SQL statements.
082     * @param sqlStatements the SQL statements to execute
083     * @return the created sequence of operations
084     */
085    public static Operation of(@Nonnull String... sqlStatements) {
086        return of(Arrays.asList(sqlStatements));
087    }
088
089    /**
090     * Creates a sequence of SqlOperation for the given SQL statements.
091     * @param sqlStatements the SQL statements to execute
092     * @return the created sequence of operations
093     */
094    public static Operation of(@Nonnull List<String> sqlStatements) {
095        List<SqlOperation> operations = new ArrayList<SqlOperation>(sqlStatements.size());
096        for (String sql : sqlStatements) {
097            operations.add(new SqlOperation(sql));
098        }
099        return CompositeOperation.sequenceOf(operations);
100    }
101
102    @Override
103    public String toString() {
104        return sql;
105    }
106
107    @Override
108    public int hashCode() {
109        return sql.hashCode();
110    }
111
112    @Override
113    public boolean equals(Object o) {
114        if (o == this) {
115            return true;
116        }
117        if (o == null) {
118            return false;
119        }
120        if (o.getClass() != this.getClass()) {
121            return false;
122        }
123
124        SqlOperation other = (SqlOperation) o;
125        return this.sql.equals(other.sql);
126    }
127}