package jef.database.support;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import jef.database.Field;
import jef.database.dialect.ColumnType;
import jef.database.dialect.type.ColumnMapping;
import jef.database.meta.Column;
import jef.database.meta.ColumnModification;
import jef.database.meta.ITableMetadata;
import jef.database.wrapper.executor.StatementExecutor;
/**
* 表结构变更时,整个操作过程进度的事件监听器(可以干涉修改表的过程)
*
* <ol>
* 按事件的时间顺序如下
* <li>{@linkplain #beforeTableRefresh(ITableMetadata, String) 变更表之前 (可以控制是否继续刷新操作)} </li>
* <li>{@linkplain #onTableCreate(ITableMetadata, String) 如果表不存在,创建表之前(可以控制是否建表)}</li>
* <li>{@linkplain #onCompareColumns(String, List, Map) 如果表存在,在比较表之前(可以控制是否继续刷新操作)}</li>
* <li>{@linkplain #onColumnsCompared(String, ITableMetadata, Map, List, List) 数据库中的表和元数据比较完成后}</li>
* <li>{@linkplain #beforeAlterTable(String, ITableMetadata, Connection, List) 比较完成并生成SQL后,在操作表之前}</li>
* <li>{@linkplain #onAlterSqlFinished(String, String, List, int, long) 在每句SQL执行成功后}</li>
* <li>{@linkplain #onSqlExecuteError(SQLException, String, String, List, int) 在任何一句SQL执行失败后}</li>
* <li>{@linkplain #onTableFinished(ITableMetadata, String) 在所有SQL都执行完成后}</li>
* </ol>
* @author jiyi
*
*/
public interface MetadataEventListener {
/**
* 当开始变更一张表时执行
* @param meta 表的元数据
* @param table 数据库中的表名
* @return false,则放弃变更此表
*/
boolean beforeTableRefresh(ITableMetadata meta, String table);
/**
* 表不存在,将会创建表
* @param meta 表的元数据
* @param tablename 数据库中的表名
* @return false,则放弃创建此表
*/
boolean onTableCreate(ITableMetadata meta, String tablename);
/**
* 表结构比较完成后出发,提供了表的对比结果供用户判断。<br>
* 在这个方法中,实现类可以直接修改传入的比较结果,让后续的程序按修改后的比较结果执行ALTER TABLE语句。
*
* @param tablename 表名
* @param meta 表的元数据
* @param insert 将要增加的数据库列(列名、数据类型)
* @param changed 数据格式发生了变更的列
* @param delete 将要删除的列
* @return false则放弃变更此表
*/
boolean onColumnsCompared(String tablename, ITableMetadata meta, Map<String, ColumnType> insert, List<ColumnModification> changed, List<String> delete);
/**
* 框架根据表对比结果,生成SQL语句后触发此事件,用户事件中可以获得所有的SQL语句。
* @param tablename 表名
* @param meta 元数据
* @param conn 数据库连接
* @param sql 所有的SQL语句
*/
void beforeAlterTable(String tablename, ITableMetadata meta, StatementExecutor conn, List<String> sql);
/**
* 每一句SQL语句执行完成后
* @param tablename 表名
* @param sql 刚完成的SQL语句
* @param n 序号,第几句SQL,编号从0开始
* @param size 总的SQL语句数量
* @param cost 刚才的SQL语句耗时(ms)
*/
void onAlterSqlFinished(String tablename, String sql, List<String> sqls, int n,long cost);
/**
* 当某句SQL语句执行失败后触发
* @param e 异常
* @param tablename 表名
* @param sql 出错的SQL语句
* @param sqls 所有SQL语句
* @param n 出错的SQL语句序号
* @return 如果返回true,表示继续执行后续的语句,如果返回false表示不再向后执行
*/
boolean onSqlExecuteError(SQLException e, String tablename, String sql, List<String> sqls, int n);
/**
* 表变更完成
* @param meta 表元数据
* @param tablename 表名
*/
void onTableFinished(ITableMetadata meta, String tablename);
/**
* 开始进行表结构的比较
* @param tablename 表名
* @param columns 数据库中的所有列
* @param defined 表模型中的所有列
* @return 是否继续比较这张表
*/
boolean onCompareColumns(String tablename, List<Column> columns, Map<Field, ColumnMapping> defined);
}