diff --git a/README.md b/README.md index e32053fc..a7bbc54c 100644 --- a/README.md +++ b/README.md @@ -505,7 +505,7 @@ service.run(); ## 八、项目推荐 -SQLREST是一款SQL2API的低代码开源工具:[https://gitee.com/inrgihc/sqlrest](https://gitee.com/inrgihc/sqlrest) +一款SQL2API的低代码开源工具SQLREST:[https://gitee.com/inrgihc/sqlrest](https://gitee.com/inrgihc/sqlrest) ## 九、社区推荐 @@ -517,7 +517,7 @@ SQLREST是一款SQL2API的低代码开源工具:[https://gitee.com/inrgihc/sqlre ## 十、问题反馈 -如果您看到并使用了本工具,或您觉得本工具对您有价值,请为此项目**点个赞**,以表示对本项目的支持,多谢!如果您在使用时遇到了bug,欢迎在issue中反馈。也可扫描下方二维码入群讨论:(加好友请注明:"程序交流") +如果您看到并使用了本工具,或您觉得本工具对您有价值,请为此项目**点个赞**,以表示对本项目的支持,多谢!如果您在使用时遇到了bug,欢迎在issue中反馈。也可扫描下方二维码入群讨论:(加好友请注明:"dbswitch程序交流") ![structure](images/weixin.PNG) diff --git a/dbswitch-admin/pom.xml b/dbswitch-admin/pom.xml index cea23ee2..484ae190 100644 --- a/dbswitch-admin/pom.xml +++ b/dbswitch-admin/pom.xml @@ -56,6 +56,11 @@ mysql-connector-java + + com.h2database + h2 + + org.quartz-scheduler quartz diff --git a/dbswitch-admin/src/main/resources/application-h2.yml b/dbswitch-admin/src/main/resources/application-h2.yml new file mode 100644 index 00000000..66c6f9ec --- /dev/null +++ b/dbswitch-admin/src/main/resources/application-h2.yml @@ -0,0 +1,13 @@ +spring: + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:~/dbswitch_db;MODE=MySQL;CASE_INSENSITIVE_IDENTIFIERS=TRUE;DATABASE_TO_UPPER=FALSE;DATABASE_TO_LOWER=FALSE + username: root + password: 123456 + validation-query: SELECT 1 + test-on-borrow: true + flyway: + locations: classpath:db/h2 + baseline-on-migrate: true + table: DBSWITCH_SCHEMA_HISTORY + enabled: true diff --git a/dbswitch-admin/src/main/resources/application.yml b/dbswitch-admin/src/main/resources/application.yml index fc00cd17..39ef2f7d 100644 --- a/dbswitch-admin/src/main/resources/application.yml +++ b/dbswitch-admin/src/main/resources/application.yml @@ -1,6 +1,7 @@ spring: profiles: - include: mysql + include: h2 + #include: mysql #include: postgres application: name: dbswitch-admin diff --git a/dbswitch-admin/src/main/resources/db/h2/V1_0_0__quartz-ddl.sql b/dbswitch-admin/src/main/resources/db/h2/V1_0_0__quartz-ddl.sql new file mode 100644 index 00000000..4ca9c9d4 --- /dev/null +++ b/dbswitch-admin/src/main/resources/db/h2/V1_0_0__quartz-ddl.sql @@ -0,0 +1,248 @@ +-- Thanks to Amir Kibbar and Peter Rietzler for contributing the schema for H2 database, +-- and verifying that it works with Quartz's StdJDBCDelegate +-- +-- Note, Quartz depends on row-level locking which means you must use the MVCC=TRUE +-- setting on your H2 database, or you will experience dead-locks +-- +-- +-- In your Quartz properties file, you'll need to set +-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate + +CREATE TABLE DBSWITCH_CALENDARS ( + SCHED_NAME VARCHAR(120) NOT NULL, + CALENDAR_NAME VARCHAR (200) NOT NULL , + CALENDAR IMAGE NOT NULL +); + +CREATE TABLE DBSWITCH_CRON_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR (200) NOT NULL , + TRIGGER_GROUP VARCHAR (200) NOT NULL , + CRON_EXPRESSION VARCHAR (120) NOT NULL , + TIME_ZONE_ID VARCHAR (80) +); + +CREATE TABLE DBSWITCH_FIRED_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + ENTRY_ID VARCHAR (95) NOT NULL , + TRIGGER_NAME VARCHAR (200) NOT NULL , + TRIGGER_GROUP VARCHAR (200) NOT NULL , + INSTANCE_NAME VARCHAR (200) NOT NULL , + FIRED_TIME BIGINT NOT NULL , + SCHED_TIME BIGINT NOT NULL , + PRIORITY INTEGER NOT NULL , + STATE VARCHAR (16) NOT NULL, + JOB_NAME VARCHAR (200) NULL , + JOB_GROUP VARCHAR (200) NULL , + IS_NONCONCURRENT BOOLEAN NULL , + REQUESTS_RECOVERY BOOLEAN NULL +); + +CREATE TABLE DBSWITCH_PAUSED_TRIGGER_GRPS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_GROUP VARCHAR (200) NOT NULL +); + +CREATE TABLE DBSWITCH_SCHEDULER_STATE ( + SCHED_NAME VARCHAR(120) NOT NULL, + INSTANCE_NAME VARCHAR (200) NOT NULL , + LAST_CHECKIN_TIME BIGINT NOT NULL , + CHECKIN_INTERVAL BIGINT NOT NULL +); + +CREATE TABLE DBSWITCH_LOCKS ( + SCHED_NAME VARCHAR(120) NOT NULL, + LOCK_NAME VARCHAR (40) NOT NULL +); + +CREATE TABLE DBSWITCH_JOB_DETAILS ( + SCHED_NAME VARCHAR(120) NOT NULL, + JOB_NAME VARCHAR (200) NOT NULL , + JOB_GROUP VARCHAR (200) NOT NULL , + DESCRIPTION VARCHAR (250) NULL , + JOB_CLASS_NAME VARCHAR (250) NOT NULL , + IS_DURABLE BOOLEAN NOT NULL , + IS_NONCONCURRENT BOOLEAN NOT NULL , + IS_UPDATE_DATA BOOLEAN NOT NULL , + REQUESTS_RECOVERY BOOLEAN NOT NULL , + JOB_DATA IMAGE NULL +); + +CREATE TABLE DBSWITCH_SIMPLE_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR (200) NOT NULL , + TRIGGER_GROUP VARCHAR (200) NOT NULL , + REPEAT_COUNT BIGINT NOT NULL , + REPEAT_INTERVAL BIGINT NOT NULL , + TIMES_TRIGGERED BIGINT NOT NULL +); + +CREATE TABLE DBSWITCH_SIMPROP_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + STR_PROP_1 VARCHAR(512) NULL, + STR_PROP_2 VARCHAR(512) NULL, + STR_PROP_3 VARCHAR(512) NULL, + INT_PROP_1 INTEGER NULL, + INT_PROP_2 INTEGER NULL, + LONG_PROP_1 BIGINT NULL, + LONG_PROP_2 BIGINT NULL, + DEC_PROP_1 NUMERIC(13,4) NULL, + DEC_PROP_2 NUMERIC(13,4) NULL, + BOOL_PROP_1 BOOLEAN NULL, + BOOL_PROP_2 BOOLEAN NULL +); + +CREATE TABLE DBSWITCH_BLOB_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR (200) NOT NULL , + TRIGGER_GROUP VARCHAR (200) NOT NULL , + BLOB_DATA IMAGE NULL +); + +CREATE TABLE DBSWITCH_TRIGGERS ( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR (200) NOT NULL , + TRIGGER_GROUP VARCHAR (200) NOT NULL , + JOB_NAME VARCHAR (200) NOT NULL , + JOB_GROUP VARCHAR (200) NOT NULL , + DESCRIPTION VARCHAR (250) NULL , + NEXT_FIRE_TIME BIGINT NULL , + PREV_FIRE_TIME BIGINT NULL , + PRIORITY INTEGER NULL , + TRIGGER_STATE VARCHAR (16) NOT NULL , + TRIGGER_TYPE VARCHAR (8) NOT NULL , + START_TIME BIGINT NOT NULL , + END_TIME BIGINT NULL , + CALENDAR_NAME VARCHAR (200) NULL , + MISFIRE_INSTR SMALLINT NULL , + JOB_DATA IMAGE NULL +); + +ALTER TABLE DBSWITCH_CALENDARS ADD + CONSTRAINT PK_DBSWITCH_CALENDARS PRIMARY KEY + ( + SCHED_NAME, + CALENDAR_NAME + ); + +ALTER TABLE DBSWITCH_CRON_TRIGGERS ADD + CONSTRAINT PK_DBSWITCH_CRON_TRIGGERS PRIMARY KEY + ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ); + +ALTER TABLE DBSWITCH_FIRED_TRIGGERS ADD + CONSTRAINT PK_DBSWITCH_FIRED_TRIGGERS PRIMARY KEY + ( + SCHED_NAME, + ENTRY_ID + ); + +ALTER TABLE DBSWITCH_PAUSED_TRIGGER_GRPS ADD + CONSTRAINT PK_DBSWITCH_PAUSED_TRIGGER_GRPS PRIMARY KEY + ( + SCHED_NAME, + TRIGGER_GROUP + ); + +ALTER TABLE DBSWITCH_SCHEDULER_STATE ADD + CONSTRAINT PK_DBSWITCH_SCHEDULER_STATE PRIMARY KEY + ( + SCHED_NAME, + INSTANCE_NAME + ); + +ALTER TABLE DBSWITCH_LOCKS ADD + CONSTRAINT PK_DBSWITCH_LOCKS PRIMARY KEY + ( + SCHED_NAME, + LOCK_NAME + ); + +ALTER TABLE DBSWITCH_JOB_DETAILS ADD + CONSTRAINT PK_DBSWITCH_JOB_DETAILS PRIMARY KEY + ( + SCHED_NAME, + JOB_NAME, + JOB_GROUP + ); + +ALTER TABLE DBSWITCH_SIMPLE_TRIGGERS ADD + CONSTRAINT PK_DBSWITCH_SIMPLE_TRIGGERS PRIMARY KEY + ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ); + +ALTER TABLE DBSWITCH_SIMPROP_TRIGGERS ADD + CONSTRAINT PK_DBSWITCH_SIMPROP_TRIGGERS PRIMARY KEY + ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ); + +ALTER TABLE DBSWITCH_TRIGGERS ADD + CONSTRAINT PK_DBSWITCH_TRIGGERS PRIMARY KEY + ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ); + +ALTER TABLE DBSWITCH_CRON_TRIGGERS ADD + CONSTRAINT FK_DBSWITCH_CRON_TRIGGERS_DBSWITCH_TRIGGERS FOREIGN KEY + ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ) REFERENCES DBSWITCH_TRIGGERS ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ) ON DELETE CASCADE; + + +ALTER TABLE DBSWITCH_SIMPLE_TRIGGERS ADD + CONSTRAINT FK_DBSWITCH_SIMPLE_TRIGGERS_DBSWITCH_TRIGGERS FOREIGN KEY + ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ) REFERENCES DBSWITCH_TRIGGERS ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ) ON DELETE CASCADE; + +ALTER TABLE DBSWITCH_SIMPROP_TRIGGERS ADD + CONSTRAINT FK_DBSWITCH_SIMPROP_TRIGGERS_DBSWITCH_TRIGGERS FOREIGN KEY + ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ) REFERENCES DBSWITCH_TRIGGERS ( + SCHED_NAME, + TRIGGER_NAME, + TRIGGER_GROUP + ) ON DELETE CASCADE; + + +ALTER TABLE DBSWITCH_TRIGGERS ADD + CONSTRAINT FK_DBSWITCH_TRIGGERS_DBSWITCH_JOB_DETAILS FOREIGN KEY + ( + SCHED_NAME, + JOB_NAME, + JOB_GROUP + ) REFERENCES DBSWITCH_JOB_DETAILS ( + SCHED_NAME, + JOB_NAME, + JOB_GROUP + ); + +COMMIT; diff --git a/dbswitch-admin/src/main/resources/db/h2/V1_0_1__system-ddl.sql b/dbswitch-admin/src/main/resources/db/h2/V1_0_1__system-ddl.sql new file mode 100644 index 00000000..16557f0d --- /dev/null +++ b/dbswitch-admin/src/main/resources/db/h2/V1_0_1__system-ddl.sql @@ -0,0 +1,118 @@ +create table `DBSWITCH_SYSTEM_USER` ( + `id` bigint(20) not null auto_increment comment '主键id', + `username` varchar(255) not null comment '登录名称', + `password` varchar(128) not null comment '登录密码', + `salt` varchar(128) not null comment '密码盐值', + `real_name` varchar(255) not null default '' comment '实际姓名', + `email` varchar(255) not null default '' comment '电子邮箱', + `address` varchar(255) not null default '' comment '所在地址', + `locked` tinyint(1) not null default 0 comment '是否锁定', + `create_time` timestamp not null default current_timestamp comment '创建时间', + `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间', + primary key (`id`), + unique key (`username`) +) engine = innodb auto_increment = 1 character set = utf8 comment = '系统用户表'; + +create table `DBSWITCH_SYSTEM_LOG` ( + `id` bigint(20) unsigned not null auto_increment comment '主键', + `type` smallint not null default 0 comment '日志类型:0-访问日志;1-操作日志', + `username` varchar(64) not null default '' comment '操作用户', + `ip_address` varchar(64) not null default '' comment '客户端ip', + `module_name` varchar(64) not null default '' comment '模块名', + `content` text comment '日志描述', + `url_path` varchar(64) not null default '' comment 'path路径', + `user_agent` varchar(255) not null default '' comment '客户端agent', + `failed` tinyint(1) not null default 0 comment '是否异常(0:否 1:是)', + `exception` longtext comment '异常堆栈信息', + `elapse_seconds` bigint(20) unsigned not null default 0 comment '执行时间(单位毫秒)', + `create_time` timestamp not null default current_timestamp comment '创建时间', +primary key (`id`) +) engine=innodb auto_increment=1 default charset=utf8 comment='操作日志'; + +create table `DBSWITCH_DATABASE_CONNECTION` ( + `id` bigint(20) unsigned not null auto_increment comment '主键', + `name` varchar(200) not null default '' comment '连接名称', + `type` varchar(200) not null default '' comment '数据库类型', + `version` varchar(255) not null default '' comment '驱动版本', + `driver` varchar(200) not null default '' comment '驱动类名称', + `address` varchar(200) not null default '' comment '连接地址', + `port` varchar(20) not null default '' comment '连接端口号', + `database_name` varchar(200) not null default '' comment '数据库名', + `character_encoding` varchar(20) not null default '' comment '编码格式', + `url` longtext comment 'jdbc-url连接串', + `username` varchar(200) not null default '' comment '连接账号', + `password` varchar(200) not null default '' comment '账号密码', + `create_time` timestamp not null default current_timestamp comment '创建时间', + `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间', + primary key (`id`), + unique key (`name`) +) engine=innodb auto_increment=1 default charset=utf8 comment='数据库连接'; + +create table `DBSWITCH_ASSIGNMENT_TASK` ( + `id` bigint(20) unsigned not null auto_increment comment '主键', + `name` varchar(200) not null default '' comment '任务名称', + `description` text comment '任务描述', + `schedule_mode` varchar(50) null default null comment '调度方式(cron/无调度)', + `cron_expression` varchar(200) not null default '' comment '调度cron表达式', + `published` tinyint(1) not null default 0 comment '是否已发布(0:否 1:是)', + `content` longtext comment '发布的配置JSON格式', + `job_key` varchar(128) null default '' comment 'JOB KEY', + `create_time` timestamp not null default current_timestamp comment '创建时间', + `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间', + primary key (`id`) +) engine=innodb auto_increment=1 default charset=utf8 comment='任务信息表'; + +create table `DBSWITCH_ASSIGNMENT_CONFIG` ( + `id` bigint(20) unsigned not null auto_increment comment '主键', + `assignment_id` bigint(20) unsigned not null comment '任务ID', + `source_connection_id` bigint(20) unsigned not null comment '来源端连接ID', + `source_schema` varchar(1024) not null default '' comment '来源端的schema', + `table_type` varchar(32) null default 'TABLE' COMMENT '表类型:TABLE;VIEW', + `source_tables` longtext comment '来源端的table列表', + `excluded_flag` tinyint(1) not null default 0 comment '是否排除(0:否 1:是)', + `target_connection_id` bigint(20) unsigned not null comment '目的端连接ID', + `target_schema` varchar(200) not null default '' comment '目的端的schema(一个)', + `target_only_create` tinyint(1) not null default '0' comment '是否只建表', + `target_drop_table` tinyint(1) not null default 0 comment '同步前是否先删除目的表(0:否 1:是)', + `table_name_map` longtext null comment '表名映射关系', + `column_name_map` longtext null comment '字段名映射关系', + `table_name_case` varchar(32) not null default 'none' comment '表名大小写转换策略', + `column_name_case` varchar(32) not null default 'none' comment '列名大小写转换策略', + `target_auto_increment` tinyint(1) not null default '0' comment '是否支持自增', + `target_sync_option` varchar(32) not null default 'insert_update_delete' comment '同步增删改选项', + `before_sql_scripts` varchar(4096) default null comment '目标端写入的前置执行sql脚本', + `after_sql_scripts` varchar(4096) default null comment '目标端写入的后置执行sql脚本', + `channel_size` bigint(20) unsigned not null default 100 comment '通道队列大小', + `batch_size` bigint(20) unsigned not null default 10000 comment '处理批次大小', + `first_flag` tinyint(1) not null default 1 comment '首次加载数据', + `create_time` timestamp not null default current_timestamp comment '创建时间', + primary key (`id`), + unique key (`assignment_id`), + foreign key (`assignment_id`) references `DBSWITCH_ASSIGNMENT_TASK` (`id`) on delete cascade on update cascade, + foreign key (`source_connection_id`) references `DBSWITCH_DATABASE_CONNECTION` (`id`) on delete cascade on update cascade, + foreign key (`target_connection_id`) references `DBSWITCH_DATABASE_CONNECTION` (`id`) on delete cascade on update cascade +) engine=innodb auto_increment=1 default charset=utf8 comment='任务配置表'; + +create table `DBSWITCH_ASSIGNMENT_JOB` ( + `id` bigint(20) unsigned not null auto_increment comment '主键', + `assignment_id` bigint(20) unsigned not null default 0 comment '任务ID', + `job_key` varchar(200) not null default '' comment 'Quartz的Job名', + `start_time` timestamp not null default current_timestamp comment '执行开始时间', + `finish_time` timestamp not null default current_timestamp comment '执行结束时间', + `schedule_mode` smallint not null default 0 comment '调度模式', + `status` smallint not null default 0 comment '执行状态:0-未执行;1-执行中;2-执行失败;3-执行成功', + `error_log` longtext comment '异常日志', + `create_time` timestamp not null default current_timestamp comment '创建时间', + `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间', + primary key (`id`), + foreign key (`assignment_id`) references `DBSWITCH_ASSIGNMENT_TASK` (`id`) on delete cascade on update cascade +) engine=innodb auto_increment=1 default charset=utf8 comment='JOB日志表'; + +CREATE TABLE IF NOT EXISTS `DBSWITCH_JOB_LOGBACK` ( + `id` bigint not null auto_increment comment '自增id', + `uuid` varchar(128) not null comment 'job id', + `content` longtext comment '日志内容', + `create_time` timestamp not null default current_timestamp comment '创建时间', + PRIMARY KEY (`id`), + KEY `uuid` (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='JOB执行日志'; diff --git a/dbswitch-admin/src/main/resources/db/h2/V1_0_2__system-dml.sql b/dbswitch-admin/src/main/resources/db/h2/V1_0_2__system-dml.sql new file mode 100644 index 00000000..fc53c9d8 --- /dev/null +++ b/dbswitch-admin/src/main/resources/db/h2/V1_0_2__system-dml.sql @@ -0,0 +1,2 @@ +insert into `DBSWITCH_SYSTEM_USER`(`username`,`password`,`salt`,`real_name`,`locked`,`email`) +values ('admin', '$2a$10$eUanVjvzV27BBxAb4zuBCugwnngHkRZ7ZB4iI5tdx9ETJ2tnXJJDy', '$2a$10$eUanVjvzV27BBxAb4zuBCu', '管理员', 0,'admin@126.com'); diff --git a/dbswitch-flyway/src/main/java/org/flywaydb/core/internal/database/h2/H2Database.java b/dbswitch-flyway/src/main/java/org/flywaydb/core/internal/database/h2/H2Database.java index 7f9ec9fc..57e0c232 100644 --- a/dbswitch-flyway/src/main/java/org/flywaydb/core/internal/database/h2/H2Database.java +++ b/dbswitch-flyway/src/main/java/org/flywaydb/core/internal/database/h2/H2Database.java @@ -15,6 +15,8 @@ */ package org.flywaydb.core.internal.database.h2; +import java.sql.Connection; +import java.sql.SQLException; import org.flywaydb.core.api.MigrationVersion; import org.flywaydb.core.api.configuration.Configuration; import org.flywaydb.core.internal.database.base.Database; @@ -22,196 +24,191 @@ import org.flywaydb.core.internal.database.base.Table; import org.flywaydb.core.internal.exception.FlywaySqlException; import org.flywaydb.core.internal.jdbc.JdbcConnectionFactory; -import java.sql.Connection; -import java.sql.SQLException; - /** * H2 database. */ public class H2Database extends Database { - /** - * A dummy user used in Oracle mode, where USER() can return null but nulls can't be inserted into the - * schema history table - */ - private static final String DEFAULT_USER = "<< default user >>"; - /** - * A dummy script marker used in Oracle mode, where a marker row is inserted with no corresponding script. - */ - private static final String DUMMY_SCRIPT_NAME = "<< history table creation script >>"; - /** - * The compatibility modes supported by H2. See http://h2database.com/html/features.html#compatibility - */ - private enum CompatibilityMode { - REGULAR, - DB2, - Derby, - HSQLDB, - MSSQLServer, - MySQL, - Oracle, - PostgreSQL, - Ignite + /** + * A dummy user used in Oracle mode, where USER() can return null but nulls can't be inserted into the schema history + * table + */ + private static final String DEFAULT_USER = "<< default user >>"; + /** + * A dummy script marker used in Oracle mode, where a marker row is inserted with no corresponding script. + */ + private static final String DUMMY_SCRIPT_NAME = "<< history table creation script >>"; + + /** + * The compatibility modes supported by H2. See http://h2database.com/html/features.html#compatibility + */ + private enum CompatibilityMode { + REGULAR, + DB2, + Derby, + HSQLDB, + MSSQLServer, + MySQL, + Oracle, + PostgreSQL, + Ignite + } + + /** + * Whether this version supports DROP SCHEMA ... CASCADE. + */ + boolean supportsDropSchemaCascade; + + /** + * The compatibility mode of the database + */ + CompatibilityMode compatibilityMode; + + /** + * Creates a new instance. + * + * @param configuration The Flyway configuration. + */ + public H2Database(Configuration configuration, JdbcConnectionFactory jdbcConnectionFactory) { + super(configuration, jdbcConnectionFactory); + + compatibilityMode = determineCompatibilityMode(); + } + + @Override + protected H2Connection doGetConnection(Connection connection) { + return new H2Connection(this, connection); + } + + @Override + protected MigrationVersion determineVersion() { + boolean requiresV2MetadataColumnNames = super.determineVersion().isAtLeast("2.0.0"); + String query = requiresV2MetadataColumnNames + ? "SELECT SETTING_VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE SETTING_NAME = 'info.BUILD_ID'" + : "SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'info.BUILD_ID'"; + try { + int buildId = getMainConnection().getJdbcTemplate().queryForInt(query); + return MigrationVersion.fromVersion(super.determineVersion().getVersion() + "." + buildId); + } catch (SQLException e) { + throw new FlywaySqlException("Unable to determine H2 build ID", e); } + } - /** - * Whether this version supports DROP SCHEMA ... CASCADE. - */ - boolean supportsDropSchemaCascade; - - /** - * The compatibility mode of the database - */ - CompatibilityMode compatibilityMode; - - /** - * Creates a new instance. - * - * @param configuration The Flyway configuration. - */ - public H2Database(Configuration configuration, JdbcConnectionFactory jdbcConnectionFactory - - - - ) { - super(configuration, jdbcConnectionFactory - - - - ); - - compatibilityMode = determineCompatibilityMode(); + private CompatibilityMode determineCompatibilityMode() { + boolean requiresV2MetadataColumnNames = super.determineVersion().isAtLeast("2.0.0"); + String query = requiresV2MetadataColumnNames + ? "SELECT SETTING_VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE SETTING_NAME = 'MODE'" + : "SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'MODE'"; + try { + String mode = getMainConnection().getJdbcTemplate().queryForString(query); + if (mode == null || "".equals(mode)) { + return CompatibilityMode.REGULAR; + } + return CompatibilityMode.valueOf(mode); + } catch (SQLException e) { + throw new FlywaySqlException("Unable to determine H2 compatibility mode", e); } + } - @Override - protected H2Connection doGetConnection(Connection connection) { - return new H2Connection(this, connection); + + @Override + public final void ensureSupported() { + ensureDatabaseIsRecentEnough("1.2.137"); + +// ensureDatabaseNotOlderThanOtherwiseRecommendUpgradeToFlywayEdition("1.4", +// org.flywaydb.core.internal.license.Edition.ENTERPRISE); + + recommendFlywayUpgradeIfNecessary("2.3.232"); + supportsDropSchemaCascade = getVersion().isAtLeast("1.4.200"); + } + + @Override + public String getRawCreateScript(Table table, boolean baseline) { + // In Oracle mode, empty strings in the marker row would be converted to NULLs. As the script column is + // defined as NOT NULL, we insert a dummy value when required. + String script = (compatibilityMode == CompatibilityMode.Oracle) + ? DUMMY_SCRIPT_NAME : ""; + + return "CREATE TABLE IF NOT EXISTS " + table + " (\n" + + " \"installed_rank\" INT NOT NULL,\n" + + " \"version\" VARCHAR(50),\n" + + " \"description\" VARCHAR(200) NOT NULL,\n" + + " \"type\" VARCHAR(20) NOT NULL,\n" + + " \"script\" VARCHAR(1000) NOT NULL,\n" + + " \"checksum\" INT,\n" + + " \"installed_by\" VARCHAR(100) NOT NULL,\n" + + " \"installed_on\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n" + + " \"execution_time\" INT NOT NULL,\n" + + " \"success\" BOOLEAN NOT NULL,\n" + + " CONSTRAINT \"" + table.getName() + "_pk\" PRIMARY KEY (\"installed_rank\")\n" + + ")" + + // Add special table created marker to compensate for the inability of H2 to lock empty tables + " AS SELECT -1, NULL, '<< Flyway Schema History table created >>', 'TABLE', '" + script + "', NULL, '" + + getInstalledBy() + "', CURRENT_TIMESTAMP, 0, TRUE;\n" + + (baseline ? getBaselineStatement(table) + ";\n" : "") + + "CREATE INDEX \"" + table.getSchema().getName() + "\".\"" + table.getName() + "_s_idx\" ON " + table + + " (\"success\");"; + } + + @Override + public String getSelectStatement(Table table) { + return "SELECT " + quote("installed_rank") + + "," + quote("version") + + "," + quote("description") + + "," + quote("type") + + "," + quote("script") + + "," + quote("checksum") + + "," + quote("installed_on") + + "," + quote("installed_by") + + "," + quote("execution_time") + + "," + quote("success") + + " FROM " + table + // Ignore special table created marker + + " WHERE " + quote("type") + " != 'TABLE'" + + " AND " + quote("installed_rank") + " > ?" + + " ORDER BY " + quote("installed_rank"); + } + + @Override + protected String doGetCurrentUser() throws SQLException { + // In Oracle mode, empty strings in the installed_by column of the history table would be converted to NULLs. + // As H2 supports a null user, we use a dummy value when required. + String user = getMainConnection().getJdbcTemplate().queryForString("SELECT USER()"); + + if (compatibilityMode == CompatibilityMode.Oracle && (user == null || "".equals(user))) { + return DEFAULT_USER; } + return user; + } - @Override - protected MigrationVersion determineVersion() { - try { - int buildId = getMainConnection().getJdbcTemplate().queryForInt( - "SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'info.BUILD_ID'"); - return MigrationVersion.fromVersion(super.determineVersion().getVersion() + "." + buildId); - } catch (SQLException e) { - throw new FlywaySqlException("Unable to determine H2 build ID", e); - } - } + @Override + public boolean supportsDdlTransactions() { + return false; + } - private CompatibilityMode determineCompatibilityMode() { - try { - String mode = getMainConnection().getJdbcTemplate().queryForString( - "SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME = 'MODE'"); - if (mode == null || "".equals(mode)) - return CompatibilityMode.REGULAR; - return CompatibilityMode.valueOf(mode); - } catch (SQLException e) { - throw new FlywaySqlException("Unable to determine H2 compatibility mode", e); - } - } + @Override + public boolean supportsChangingCurrentSchema() { + return true; + } + @Override + public String getBooleanTrue() { + return "1"; + } + @Override + public String getBooleanFalse() { + return "0"; + } + @Override + public String doQuote(String identifier) { + return "\"" + identifier + "\""; + } - - - - - @Override - public final void ensureSupported() { - ensureDatabaseIsRecentEnough("1.2.137"); - - ensureDatabaseNotOlderThanOtherwiseRecommendUpgradeToFlywayEdition("1.4", org.flywaydb.core.internal.license.Edition.ENTERPRISE); - - recommendFlywayUpgradeIfNecessary("1.4.200"); - supportsDropSchemaCascade = getVersion().isAtLeast("1.4.200"); - } - - @Override - public String getRawCreateScript(Table table, boolean baseline) { - // In Oracle mode, empty strings in the marker row would be converted to NULLs. As the script column is - // defined as NOT NULL, we insert a dummy value when required. - String script = (compatibilityMode == CompatibilityMode.Oracle) - ? DUMMY_SCRIPT_NAME : ""; - - return "CREATE TABLE IF NOT EXISTS " + table + " (\n" + - " \"installed_rank\" INT NOT NULL,\n" + - " \"version\" VARCHAR(50),\n" + - " \"description\" VARCHAR(200) NOT NULL,\n" + - " \"type\" VARCHAR(20) NOT NULL,\n" + - " \"script\" VARCHAR(1000) NOT NULL,\n" + - " \"checksum\" INT,\n" + - " \"installed_by\" VARCHAR(100) NOT NULL,\n" + - " \"installed_on\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n" + - " \"execution_time\" INT NOT NULL,\n" + - " \"success\" BOOLEAN NOT NULL,\n" + - " CONSTRAINT \"" + table.getName() + "_pk\" PRIMARY KEY (\"installed_rank\")\n" + - ")" + - // Add special table created marker to compensate for the inability of H2 to lock empty tables - " AS SELECT -1, NULL, '<< Flyway Schema History table created >>', 'TABLE', '" + script + "', NULL, '" + getInstalledBy() + "', CURRENT_TIMESTAMP, 0, TRUE;\n" + - (baseline ? getBaselineStatement(table) + ";\n" : "") + - "CREATE INDEX \"" + table.getSchema().getName() + "\".\"" + table.getName() + "_s_idx\" ON " + table + " (\"success\");"; - } - - @Override - public String getSelectStatement(Table table) { - return "SELECT " + quote("installed_rank") - + "," + quote("version") - + "," + quote("description") - + "," + quote("type") - + "," + quote("script") - + "," + quote("checksum") - + "," + quote("installed_on") - + "," + quote("installed_by") - + "," + quote("execution_time") - + "," + quote("success") - + " FROM " + table - // Ignore special table created marker - + " WHERE " + quote("type") + " != 'TABLE'" - + " AND " + quote("installed_rank") + " > ?" - + " ORDER BY " + quote("installed_rank"); - } - - @Override - protected String doGetCurrentUser() throws SQLException { - // In Oracle mode, empty strings in the installed_by column of the history table would be converted to NULLs. - // As H2 supports a null user, we use a dummy value when required. - String user = getMainConnection().getJdbcTemplate().queryForString("SELECT USER()"); - - if (compatibilityMode == CompatibilityMode.Oracle && (user == null || "".equals(user))) - return DEFAULT_USER; - return user; - } - - @Override - public boolean supportsDdlTransactions() { - return false; - } - - @Override - public boolean supportsChangingCurrentSchema() { - return true; - } - - @Override - public String getBooleanTrue() { - return "1"; - } - - @Override - public String getBooleanFalse() { - return "0"; - } - - @Override - public String doQuote(String identifier) { - return "\"" + identifier + "\""; - } - - @Override - public boolean catalogIsSchema() { - return false; - } + @Override + public boolean catalogIsSchema() { + return false; + } } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 86e3417b..31e9fec8 100644 --- a/pom.xml +++ b/pom.xml @@ -127,6 +127,12 @@ 5.1.47 + + com.h2database + h2 + 1.4.200 + + com.github.pagehelper pagehelper-spring-boot-starter