Table.java
/*-
* ========================LICENSE_START=================================
* flyway-core
* ========================================================================
* Copyright (C) 2010 - 2025 Red Gate Software Ltd
* ========================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =========================LICENSE_END==================================
*/
package org.flywaydb.core.internal.database.base;
import org.flywaydb.core.internal.exception.FlywaySqlException;
import org.flywaydb.core.internal.jdbc.JdbcTemplate;
import org.flywaydb.core.internal.jdbc.JdbcUtils;
import java.sql.ResultSet;
import java.sql.SQLException;
public abstract class Table<D extends Database, S extends Schema> extends SchemaObject<D, S> {
/**
* Keeps track of the locks on a table since calls to lock the table can be nested.
*/
protected int lockDepth = 0;
/**
* @param jdbcTemplate The JDBC template for communicating with the DB.
* @param database The database-specific support.
* @param schema The schema this table lives in.
* @param name The name of the table.
*/
public Table(JdbcTemplate jdbcTemplate, D database, S schema, String name) {
super(jdbcTemplate, database, schema, name);
}
public boolean exists() {
try {
return doExists();
} catch (SQLException e) {
throw new FlywaySqlException("Unable to check whether table " + this + " exists", e);
}
}
/**
* Checks whether this table exists.
*
* @throws SQLException when the check failed.
*/
protected abstract boolean doExists() throws SQLException;
/**
* Checks whether the database contains a table matching the given criteria.
*
* @param catalog The catalog where the table resides. (optional)
* @param schema The schema where the table resides. (optional)
* @param table The name of the table. (optional)
* @param tableTypes The types of table to look for (e.g. TABLE). (optional)
* @throws SQLException when the check failed.
*/
protected boolean exists(Schema catalog, Schema schema, String table, String... tableTypes) throws SQLException {
String[] types = tableTypes;
if (types.length == 0) {
types = null;
}
ResultSet resultSet = null;
boolean found;
try {
resultSet = database.jdbcMetaData.getTables(
catalog == null ? null : catalog.getName(),
schema == null ? null : schema.getName(),
table,
types);
found = resultSet.next();
} finally {
JdbcUtils.closeResultSet(resultSet);
}
return found;
}
/**
* Locks this table in this schema using a read/write pessimistic lock until the end of the current transaction.
* Note that {@code unlock()} still needs to be called even if your database unlocks the table implicitly
* (in which case {@code doUnlock()} may be a no-op) in order to maintain the lock count correctly.
*/
public void lock() {
if (!exists()) {
return;
}
try {
doLock();
lockDepth++;
} catch (SQLException e) {
throw new FlywaySqlException("Unable to lock table " + this, e);
}
}
/**
* Locks this table in this schema using a read/write pessimistic lock until the end of the current transaction.
* Note that {@code unlock()} still needs to be called even if your database unlocks the table implicitly
* (in which case {@code doUnlock()} may be a no-op) in order to maintain the lock count correctly.
*
* @throws SQLException when this table in this schema could not be locked.
*/
protected abstract void doLock() throws SQLException;
/**
* For databases that require an explicit unlocking, not an implicit end-of-transaction one.
*/
public void unlock() {
// lockDepth can be zero if this table didn't exist at the time of the call to lock()
if (!exists() || lockDepth == 0) {
return;
}
try {
doUnlock();
lockDepth--;
} catch (SQLException e) {
throw new FlywaySqlException("Unable to unlock table " + this, e);
}
}
/**
* For databases that require an explicit unlocking, not an implicit end-of-transaction one.
*
* @throws SQLException when this table in this schema could not be unlocked.
*/
protected void doUnlock() throws SQLException {}
}