Sfoglia il codice sorgente

开源表结构自动维护特性

hubin 2 anni fa
parent
commit
0c5704d6bf

+ 54 - 0
mybatis-plus-boot-starter/src/main/java/com/baomidou/mybatisplus/autoconfigure/DdlApplicationRunner.java

@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * 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.
+ */
+package com.baomidou.mybatisplus.autoconfigure;
+
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.extension.ddl.DdlHelper;
+import com.baomidou.mybatisplus.extension.ddl.IDdl;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+
+import java.util.List;
+
+/**
+ * DDL 启动应用后执行
+ *
+ * @author hubin
+ * @since 2021-06-22
+ */
+@Slf4j
+public class DdlApplicationRunner implements ApplicationRunner {
+    private List<IDdl> ddlList;
+
+    public DdlApplicationRunner(List<IDdl> ddlList) {
+        this.ddlList = ddlList;
+    }
+
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+        log.debug("  ...  DDL start create  ...  ");
+        if (ObjectUtils.isNotEmpty(ddlList)) {
+            /**
+             * 执行 SQL 脚本
+             * <p>多数据源情况可按需初始化</p>
+             */
+            ddlList.forEach(ddl -> ddl.runScript(dataSource -> DdlHelper.runScript(ddl.getDdlGenerator(),
+                    dataSource, ddl.getSqlFiles(), true)));
+        }
+        log.debug("  ...  DDL end create  ...  ");
+    }
+}

+ 12 - 0
mybatis-plus-boot-starter/src/main/java/com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.java

@@ -23,6 +23,7 @@ import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
 import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
 import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
 import com.baomidou.mybatisplus.core.injector.ISqlInjector;
+import com.baomidou.mybatisplus.extension.ddl.IDdl;
 import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.mapping.DatabaseIdProvider;
@@ -41,6 +42,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanWrapper;
 import org.springframework.beans.BeanWrapperImpl;
 import org.springframework.beans.factory.*;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -58,6 +60,7 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
+import org.springframework.core.annotation.Order;
 import org.springframework.core.env.Environment;
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.ResourceLoader;
@@ -379,4 +382,13 @@ public class MybatisPlusAutoConfiguration implements InitializingBean {
                 "Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer.");
         }
     }
+
+    @Order
+    @Bean
+    public DdlApplicationRunner ddlApplicationRunner(@Autowired(required = false) List<IDdl> ddlList) {
+        if (ObjectUtils.isEmpty(ddlList)) {
+            return null;
+        }
+        return new DdlApplicationRunner(ddlList);
+    }
 }

+ 2 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/StringPool.java

@@ -64,6 +64,7 @@ public interface StringPool {
     String N = "n";
     String NO = "no";
     String NULL = "null";
+    String NUM = "NUM";
     String OFF = "off";
     String ON = "on";
     String PERCENT = "%";
@@ -81,6 +82,7 @@ public interface StringPool {
     String SINGLE_QUOTE = "'";
     String BACKTICK = "`";
     String SPACE = " ";
+    String SQL = "sql";
     String TILDA = "~";
     String LEFT_SQ_BRACKET = "[";
     String RIGHT_SQ_BRACKET = "]";

+ 151 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/DdlHelper.java

@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * 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.
+ */
+package com.baomidou.mybatisplus.extension.ddl;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.extension.ddl.history.IDdlGenerator;
+import com.baomidou.mybatisplus.extension.ddl.history.MysqlDdlGenerator;
+import com.baomidou.mybatisplus.extension.ddl.history.OracleDdlGenerator;
+import com.baomidou.mybatisplus.extension.ddl.history.PostgresDdlGenerator;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.jdbc.ScriptRunner;
+import org.apache.ibatis.jdbc.SqlRunner;
+import org.springframework.core.io.ClassPathResource;
+
+import javax.sql.DataSource;
+import java.io.*;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * DDL 辅助类
+ *
+ * @author hubin
+ * @since 2021-06-22
+ */
+@Slf4j
+public class DdlHelper {
+
+    /**
+     * 允许 SQL 脚本文件
+     *
+     * @param ddlGenerator DDL 生成器
+     * @param dataSource   数据源
+     * @param sqlFiles     SQL 文件列表
+     * @param autoCommit   字段提交事务
+     * @throws Exception
+     */
+    public static void runScript(IDdlGenerator ddlGenerator, DataSource dataSource, List<String> sqlFiles, boolean autoCommit) {
+        try {
+            // 执行自定义 DDL 信息
+            Connection connection = dataSource.getConnection();
+            final String jdbcUrl = connection.getMetaData().getURL();
+            final String schema = DdlHelper.getDatabase(jdbcUrl);
+            SqlRunner sqlRunner = new SqlRunner(connection);
+            ScriptRunner scriptRunner = getScriptRunner(connection, autoCommit);
+            if (null == ddlGenerator) {
+                ddlGenerator = getDdlGenerator(jdbcUrl);
+            }
+            if (!ddlGenerator.existTable(schema, sql -> {
+                try {
+                    Map<String, Object> resultMap = sqlRunner.selectOne(sql);
+                    if (null != resultMap && !StringPool.ZERO.equals(String.valueOf(resultMap.get(StringPool.NUM)))) {
+                        return true;
+                    }
+                } catch (SQLException e) {
+                    log.error("run script sql:{} , error: {}", sql, e.getMessage());
+                }
+                return false;
+            })) {
+                scriptRunner.runScript(new StringReader(ddlGenerator.createDdlHistory()));
+            }
+            // 执行 SQL 脚本
+            for (String sqlFile : sqlFiles) {
+                try {
+                    List<Map<String, Object>> objectMap = sqlRunner.selectAll(ddlGenerator.selectDdlHistory(sqlFile, StringPool.SQL));
+                    if (null == objectMap || objectMap.isEmpty()) {
+                        log.debug("run script file: {}", sqlFile);
+                        File file = new File(sqlFile);
+                        if (file.exists()) {
+                            scriptRunner.runScript(new FileReader(file));
+                        } else {
+                            scriptRunner.runScript(new InputStreamReader(getInputStream(sqlFile)));
+                        }
+                        sqlRunner.insert(ddlGenerator.insertDdlHistory(sqlFile, StringPool.SQL, getNowTime()));
+                    }
+                } catch (Exception e) {
+                    log.error("run script sql:{} , error: {} , Please check if the table `ddl_history` exists", sqlFile, e.getMessage());
+                }
+            }
+        } catch (Exception e) {
+            log.error("run script error: {}", e.getMessage());
+        }
+    }
+
+    public static InputStream getInputStream(String path) throws Exception {
+        return new ClassPathResource(path).getInputStream();
+    }
+
+    protected static String getNowTime() {
+        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
+    }
+
+    public static ScriptRunner getScriptRunner(Connection connection, boolean autoCommit) {
+        ScriptRunner scriptRunner = new ScriptRunner(connection);
+        scriptRunner.setAutoCommit(autoCommit);
+        scriptRunner.setStopOnError(true);
+        return scriptRunner;
+    }
+
+    protected static IDdlGenerator getDdlGenerator(String jdbcUrl) throws Exception {
+        jdbcUrl = jdbcUrl.toLowerCase();
+        if (jdbcUrl.contains(":mysql:")
+                || jdbcUrl.contains(":mariadb:")
+                || jdbcUrl.contains(":gbase:")
+                || jdbcUrl.contains(":oscar:")
+                || jdbcUrl.contains(":xugu:")
+                || jdbcUrl.contains(":clickhouse:")
+                || jdbcUrl.contains(":oceanbase:")
+                || jdbcUrl.contains(":cobar:")) {
+            return MysqlDdlGenerator.newInstance();
+        } else if (jdbcUrl.contains(":postgresql:")
+                || jdbcUrl.contains(":h2:")
+                || jdbcUrl.contains(":sqlite:")
+                || jdbcUrl.contains(":hsqldb:")
+                || jdbcUrl.contains(":kingbase\\d*:")
+                || jdbcUrl.contains(":phoenix:")) {
+            return PostgresDdlGenerator.newInstance();
+        } else if (jdbcUrl.contains(":oracle:")) {
+            return OracleDdlGenerator.newInstance();
+        }
+        throw new RuntimeException("The database is not supported");
+    }
+
+    public static String getDatabase(String jdbcUrl) {
+        String[] urlArr = jdbcUrl.split("://");
+        if (urlArr.length == 2) {
+            String[] dataArr = urlArr[1].split("/");
+            if (dataArr.length > 1) {
+                return dataArr[1].split("\\?")[0];
+            }
+        }
+        return null;
+    }
+}

+ 87 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/DdlScript.java

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * 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.
+ */
+package com.baomidou.mybatisplus.extension.ddl;
+
+import com.baomidou.mybatisplus.extension.ddl.history.IDdlGenerator;
+
+import javax.sql.DataSource;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.List;
+
+/**
+ * Ddl 脚本执行
+ *
+ * @author hubin
+ * @since 2021-07-23
+ */
+public class DdlScript {
+    private DataSource dataSource;
+    private IDdlGenerator ddlGenerator;
+    private boolean autoCommit;
+
+    public DdlScript(DataSource dataSource) {
+        this(dataSource, null);
+    }
+
+    public DdlScript(DataSource dataSource, IDdlGenerator ddlGenerator) {
+        this(dataSource, ddlGenerator, false);
+    }
+
+    public DdlScript(DataSource dataSource, IDdlGenerator ddlGenerator, boolean autoCommit) {
+        this.dataSource = dataSource;
+        this.ddlGenerator = ddlGenerator;
+        this.autoCommit = autoCommit;
+    }
+
+    public void run(List<String> sqlFiles) {
+        this.run(sqlFiles, this.autoCommit);
+    }
+
+    /**
+     * 执行 SQL 脚本文件
+     *
+     * @param sqlFiles SQL 脚本文件列表
+     */
+    public void run(List<String> sqlFiles, boolean autoCommit) {
+        DdlHelper.runScript(this.ddlGenerator, this.dataSource, sqlFiles, autoCommit);
+    }
+
+    /**
+     * 执行 SQL 脚本
+     *
+     * @param sqlScript SQL 脚本内容
+     * @throws Exception
+     */
+    public void run(String sqlScript) throws Exception {
+        this.run(new StringReader(sqlScript));
+    }
+
+    public void run(Reader reader) throws Exception {
+        this.run(reader, this.autoCommit);
+    }
+
+    /**
+     * 执行 SQL 脚本
+     *
+     * @param reader     SQL 脚本内容
+     * @param autoCommit 自动提交事务
+     * @throws Exception
+     */
+    public void run(Reader reader, boolean autoCommit) throws Exception {
+        DdlHelper.getScriptRunner(dataSource.getConnection(), autoCommit).runScript(reader);
+    }
+}

+ 53 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/IDdl.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * 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.
+ */
+package com.baomidou.mybatisplus.extension.ddl;
+
+import com.baomidou.mybatisplus.extension.ddl.history.IDdlGenerator;
+
+import javax.sql.DataSource;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * DDL 处理器
+ *
+ * @author hubin
+ * @since 2021-06-22
+ */
+public interface IDdl {
+
+    /**
+     * 执行 SQL 脚本
+     *
+     * @param consumer 指定数据源执行
+     */
+    void runScript(Consumer<DataSource> consumer);
+
+    /**
+     * DDL 生成器
+     */
+    default IDdlGenerator getDdlGenerator() {
+        return null;
+    }
+
+    /**
+     * 执行 SQL 脚本
+     * <p>Resources.getResourceAsReader("db/test.sql")</p>
+     *
+     * @return SQL 脚本文件列表
+     */
+    List<String> getSqlFiles();
+}

+ 42 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * 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.
+ */
+package com.baomidou.mybatisplus.extension.ddl;
+
+import javax.annotation.Resource;
+import javax.sql.DataSource;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * 非多数据源 DDL 实现
+ *
+ * @author hubin
+ * @since 2021-09-23
+ */
+public class SimpleDdl implements IDdl {
+    @Resource
+    private DataSource dataSource;
+
+    @Override
+    public void runScript(Consumer<DataSource> consumer) {
+        consumer.accept(dataSource);
+    }
+
+    @Override
+    public List<String> getSqlFiles() {
+        return null;
+    }
+}

+ 82 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/history/IDdlGenerator.java

@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * 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.
+ */
+package com.baomidou.mybatisplus.extension.ddl.history;
+
+import java.util.function.Function;
+
+/**
+ * DDL 生成器接口
+ *
+ * @author hubin
+ * @since 2021-06-22
+ */
+public interface IDdlGenerator {
+
+    /**
+     * 表是否存在
+     *
+     * @param databaseName    数据库名称
+     * @param executeFunction 执行判断函数
+     * @return exist or no
+     */
+    boolean existTable(String databaseName, Function<String, Boolean> executeFunction);
+
+    /**
+     * 返回 DDL_HISTORY 表名
+     *
+     * @return SQL
+     */
+    default String getDdlHistory() {
+        return "ddl_history";
+    }
+
+    /**
+     * ddl_history sql
+     *
+     * @return SQL
+     */
+    String createDdlHistory();
+
+    /**
+     * select ddl_history sql
+     *
+     * @param script Sql Script
+     * @param type   Execute Type
+     * @return SQL
+     */
+    default String selectDdlHistory(String script, String type) {
+        StringBuffer sql = new StringBuffer();
+        sql.append("SELECT version FROM ").append(getDdlHistory()).append(" WHERE script='").append(script);
+        sql.append("' AND type='").append(type).append("'");
+        return sql.toString();
+    }
+
+    /**
+     * insert ddl_history sql
+     *
+     * @param script  Sql Script
+     * @param type    Execute Type
+     * @param version Execute Version
+     * @return SQL
+     */
+    default String insertDdlHistory(String script, String type, String version) {
+        StringBuffer sql = new StringBuffer();
+        sql.append("INSERT INTO ").append(getDdlHistory()).append("(script,type,version) VALUES ('");
+        sql.append(script).append("','").append(type).append("','").append(version).append("')");
+        return sql.toString();
+    }
+
+}

+ 56 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/history/MysqlDdlGenerator.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * 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.
+ */
+package com.baomidou.mybatisplus.extension.ddl.history;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+
+import java.util.function.Function;
+
+/**
+ * Mysql DDL 生成器
+ *
+ * @author hubin
+ * @since 2021-06-22
+ */
+public class MysqlDdlGenerator implements IDdlGenerator {
+
+    public static IDdlGenerator newInstance() {
+        return new MysqlDdlGenerator();
+    }
+
+    @Override
+    public boolean existTable(String databaseName, Function<String, Boolean> executeFunction) {
+        StringBuffer sql = new StringBuffer();
+        sql.append("SELECT COUNT(1) AS NUM from INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='");
+        sql.append(getDdlHistory()).append("' AND TABLE_TYPE='BASE TABLE'");
+        if (StringUtils.isNotBlank(databaseName)) {
+            sql.append(" AND TABLE_SCHEMA='").append(databaseName).append("'");
+        }
+        return executeFunction.apply(sql.toString());
+    }
+
+    @Override
+    public String createDdlHistory() {
+        StringBuffer sql = new StringBuffer();
+        sql.append("CREATE TABLE IF NOT EXISTS `").append(getDdlHistory()).append("` (");
+        sql.append("`script` varchar(500) NOT NULL COMMENT '脚本',");
+        sql.append("`type` varchar(30) NOT NULL COMMENT '类型',");
+        sql.append("`version` varchar(30) NOT NULL COMMENT '版本',");
+        sql.append("PRIMARY KEY (`script`)");
+        sql.append(") COMMENT = 'DDL 版本';");
+        return sql.toString();
+    }
+}

+ 53 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/history/OracleDdlGenerator.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * 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.
+ */
+package com.baomidou.mybatisplus.extension.ddl.history;
+
+import java.util.function.Function;
+
+/**
+ * Oracle DDL 生成器
+ *
+ * @author hubin
+ * @since 2021-06-22
+ */
+public class OracleDdlGenerator implements IDdlGenerator {
+
+    public static IDdlGenerator newInstance() {
+        return new OracleDdlGenerator();
+    }
+
+    @Override
+    public boolean existTable(String databaseName, Function<String, Boolean> executeFunction) {
+        return executeFunction.apply("SELECT COUNT(1) AS NUM FROM user_tables WHERE table_name='"
+                + getDdlHistory() + "'");
+    }
+
+    @Override
+    public String getDdlHistory() {
+        return "DDL_HISTORY";
+    }
+
+    @Override
+    public String createDdlHistory() {
+        StringBuffer sql = new StringBuffer();
+        sql.append("CREATE TABLE ").append(getDdlHistory()).append("(");
+        sql.append("script NVARCHAR2(500) NOT NULL,");
+        sql.append("type NVARCHAR2(30) NOT NULL,");
+        sql.append("version NVARCHAR2(30) NOT NULL");
+        sql.append(");");
+        return sql.toString();
+    }
+}

+ 65 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/history/PostgresDdlGenerator.java

@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * 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.
+ */
+package com.baomidou.mybatisplus.extension.ddl.history;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.function.Function;
+
+/**
+ * Mysql DDL 生成器
+ *
+ * @author hubin
+ * @since 2021-06-22
+ */
+public class PostgresDdlGenerator implements IDdlGenerator {
+
+    public static IDdlGenerator newInstance() {
+        return new PostgresDdlGenerator();
+    }
+    @Override
+    public boolean existTable(String databaseName, Function<String, Boolean> executeFunction) {
+        StringBuffer sql = new StringBuffer();
+        sql.append("SELECT COUNT(1) AS NUM from INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='ddl_history' AND TABLE_TYPE='BASE TABLE'");
+        if (StringUtils.isNoneBlank(this.getSchema())) {
+            sql.append(" AND TABLE_SCHEMA='").append(this.getSchema()).append("'");
+        }
+        return executeFunction.apply(sql.toString());
+    }
+    @Override
+    public String getDdlHistory() {
+        return "\"" + this.getSchema() + "\".\"ddl_history\"";
+    }
+    @Override
+    public String createDdlHistory() {
+        StringBuffer sql = new StringBuffer();
+        String ddlHistory = this.getDdlHistory();
+        sql.append("CREATE TABLE IF NOT EXISTS ").append(ddlHistory).append(" (");
+        sql.append("\"script\" varchar(500) NOT NULL,");
+        sql.append("\"type\" varchar(30) NOT NULL,");
+        sql.append("\"version\" varchar(30) NOT NULL");
+        sql.append(");");
+        sql.append("COMMENT ON COLUMN ").append(ddlHistory).append(".\"script\" IS '脚本';");
+        sql.append("COMMENT ON COLUMN ").append(ddlHistory).append(".\"type\" IS '类型';");
+        sql.append("COMMENT ON COLUMN ").append(ddlHistory).append(".\"version\" IS '版本';");
+        sql.append("COMMENT ON TABLE ").append(ddlHistory).append(" IS 'DDL 版本';");
+        return sql.toString();
+    }
+
+    protected String getSchema() {
+        return "public";
+    }
+}