【问题标题】:Does flyway migrations support PostgreSQL's COPY?flyway 迁移是否支持 PostgreSQL 的 COPY?
【发布时间】:2012-07-16 16:28:47
【问题描述】:

在对现有 posgresql 模式执行 pg_dump 后,我有一个 sql 文件,其中包含许多使用副本的表填充语句。

COPY test_table (id, itm, factor, created_timestamp, updated_timestamp, updated_by_user, version) FROM stdin;
1   600 0.000   2012-07-17 18:12:42.360828  2012-07-17 18:12:42.360828  system  0
2   700 0.000   2012-07-17 18:12:42.360828  2012-07-17 18:12:42.360828  system  0
\.

虽然不标准,但这是 PostgreSQL 的 PLSQL 实现的一部分。

执行 flyway 迁移(通过 maven 插件)我得到:

[ERROR] Caused by org.postgresql.util.PSQLException: ERROR: unexpected message type 0x50 during COPY from stein

是我做错了什么,还是不支持?

谢谢。

【问题讨论】:

    标签: database postgresql flyway


    【解决方案1】:

    简短的回答是否。

    一个明确的问题是解析器当前无法处理这种特殊构造。

    另一个问题是jdbc 驱动支持。您能否尝试通过单个 createStatement 调用查看 jdbc 驱动程序是否普遍支持此语法?

    如果是,请在问题跟踪器中提交问题,我将扩展解析器。

    更新:现在支持

    【讨论】:

    • 据我所知,JDBC驱动不支持COPY .. FROM stdin。仅从文件中复制。
    • JDBC 驱动程序似乎支持COPY ... FROM stdin 构造,查看org.postgresql.copy 包中的类。
    • 谢谢 - 我遇到的问题让我重新评估了我的方法。但是,现在我有机会对此进行更深入的研究,它似乎没有“简单”的 JDBC 支持,通过 CopyManager answer showing example
    • 顺便说一句 - 简短的回答正是我所追求的;)谢谢
    • 当前版本似乎以某种方式支持它..见flywaydb.org/documentation/database/postgresql.html
    【解决方案2】:

    我已经使用 Postgres 完成了这项工作

    public abstract class SeedData implements JdbcMigration {
    
        protected static final String CSV_COPY_STRING = "COPY %s(%s) FROM STDIN HEADER DELIMITER ',' CSV ENCODING 'UTF-8'";
    
        protected CopyManager copyManager;
    
        @Override
        public void migrate(Connection connection) throws Exception {
            log.info(String.format("[%s] Populating database with seed data", getClass().getName()));
            copyManager = new CopyManager((BaseConnection) connection);
    
            Resource[] resources = scanForResources();
    
            List<Resource> res = Arrays.asList(resources);
            for (Resource resource : res) {
                load(resource);
            }
        }
    
        private void load(Resource resource) throws SQLException, IOException {
            String location = resource.getLocation();
    
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream(location);
            if (inputStream == null) {
                throw new FlywayException("Failure to load seed data. Unable to load from location: " + location);
            }
            if (!inputStream.markSupported()) {
                // Sanity check. We have to be able to mark the stream.
                throw new FlywayException(
                        "Failure to load seed data as mark is not supported. Unable to load from location: " + location);
            }
            // set our mark to something big
            inputStream.mark(1 << 32);
    
            String filename = resource.getFilename();
            // Strip the prefix (e.g. 01_) and the file extension (e.g. .csv)
            String table = filename.substring(3, filename.length() - 4);
            String columns = loadCsvHeader(location, inputStream);
    
            // reset to the mark
            inputStream.reset();
    
            // Use Postgres COPY command to bring it in
            long result = copyManager.copyIn(String.format(CSV_COPY_STRING, table, columns), inputStream);
            log.info(format("   %s - Inserted %d rows", location, result));
        }
    
        private String loadCsvHeader(String location, InputStream inputStream) {
            try {
                return new BufferedReader(new InputStreamReader(inputStream)).readLine();
            } catch (IOException e) {
                throw new FlywayException("Failure to load seed data. Unable to load from location: " + location, e);
            }
        }
    
        private Resource[] scanForResources() throws IOException {
            return new ClassPathScanner(getClass().getClassLoader()).scanForResources(getSeedDataLocation(), "", ".csv");
        }
    
        protected String getSeedDataLocation() {
            return getClass().getPackage().getName().replace('.', '/');
        }
    
    }
    

    使用适当的类路径实现类

    package db.devSeedData.dev;
    
    public class v0_90__seed extends db.devSeedData.v0_90__seed {
    }
    

    接下来需要在类路径中的 db/devSeedData 下包含格式为 01_tablename.csv 的 CSV 文件。列是从 CSV 的标题行中提取的。

    【讨论】:

      猜你喜欢
      • 2021-08-23
      • 2020-08-18
      • 2020-07-19
      • 2022-01-10
      • 1970-01-01
      • 2011-04-24
      • 2015-10-07
      • 2022-08-03
      • 2013-10-13
      相关资源
      最近更新 更多