sql >> データベース >  >> RDS >> PostgreSQL

JDBCを使用したカスタムタイプの配列を使用したPostgresへのCSVコピー

    https://git.mikael.io/mikaelhg/pg -object-csv-copy-poc / 必要なことを実行するJUnitテストを使用するプロジェクトの場合。

    基本的に、配列項目を区切ることと型フィールドを区切ることの2つの目的でコンマを使用できるようにする必要がありますが、CSV解析でコンマをフィールドデリニエーターとして解釈することは望ましくありません。

    だから

    1. 行全体を1つの文字列、1つのフィールドと見なすように、CSVパーサーに指示します。これは、一重引用符で囲み、CSVパーサーにこれを通知することで実行できます。
    2. PGフィールドパーサーで、各配列アイテムタイプのインスタンスが二重引用符で囲まれていると見なされるようにします。

    コード:

    copyManager.copyIn("COPY my_table (addresses) FROM STDIN WITH CSV QUOTE ''''", reader);
    

    DMLの例1:

    COPY my_table (addresses) FROM STDIN WITH CSV QUOTE ''''
    

    CSVの例1:

    '{"(10.0.0.1,1)","(10.0.0.2,2)"}'
    '{"(10.10.10.1,80)","(10.10.10.2,443)"}'
    '{"(10.10.10.3,8080)","(10.10.10.4,4040)"}'
    

    DMLの例2、二重引用符をエスケープする:

    COPY my_table (addresses) FROM STDIN WITH CSV
    

    CSVの例2、二重引用符をエスケープする:

    "{""(10.0.0.1,1)"",""(10.0.0.2,2)""}"
    "{""(10.10.10.1,80)"",""(10.10.10.2,443)""}"
    "{""(10.10.10.3,8080)"",""(10.10.10.4,4040)""}"
    

    完全なJUnitテストクラス:

    package io.mikael.poc;
    
    import com.google.common.io.CharStreams;
    import org.junit.*;
    import org.postgresql.PGConnection;
    import org.postgresql.copy.CopyManager;
    import org.testcontainers.containers.PostgreSQLContainer;
    
    import java.io.*;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    
    import static java.nio.charset.StandardCharsets.UTF_8;
    
    public class CopyTest {
    
        private Reader reader;
    
        private Connection connection;
    
        private CopyManager copyManager;
    
        private static final String CREATE_TYPE = "CREATE TYPE address AS (ip inet, port int)";
    
        private static final String CREATE_TABLE = "CREATE TABLE my_table (addresses  address[] NULL)";
    
        private String loadCsvFromFile(final String fileName) throws IOException {
            try (InputStream is = getClass().getResourceAsStream(fileName)) {
                return CharStreams.toString(new InputStreamReader(is, UTF_8));
            }
        }
    
        @ClassRule
        public static PostgreSQLContainer db = new PostgreSQLContainer("postgres:10-alpine");
    
        @BeforeClass
        public static void beforeClass() throws Exception {
            Class.forName("org.postgresql.Driver");
        }
    
        @Before
        public void before() throws Exception {
            String input = loadCsvFromFile("/data_01.csv");
            reader = new StringReader(input);
    
            connection = DriverManager.getConnection(db.getJdbcUrl(), db.getUsername(), db.getPassword());
            copyManager = connection.unwrap(PGConnection.class).getCopyAPI();
    
            connection.setAutoCommit(false);
            connection.beginRequest();
    
            connection.prepareCall(CREATE_TYPE).execute();
            connection.prepareCall(CREATE_TABLE).execute();
        }
    
        @After
        public void after() throws Exception {
            connection.rollback();
        }
    
        @Test
        public void copyTest01() throws Exception {
            copyManager.copyIn("COPY my_table (addresses) FROM STDIN WITH CSV QUOTE ''''", reader);
    
            final StringWriter writer = new StringWriter();
            copyManager.copyOut("COPY my_table TO STDOUT WITH CSV", writer);
            System.out.printf("roundtrip:%n%s%n", writer.toString());
    
            final ResultSet rs = connection.prepareStatement(
                    "SELECT array_to_json(array_agg(t)) FROM (SELECT addresses FROM my_table) t")
                    .executeQuery();
            rs.next();
            System.out.printf("json:%n%s%n", rs.getString(1));
        }
    
    }
    

    テスト出力:

    roundtrip:
    "{""(10.0.0.1,1)"",""(10.0.0.2,2)""}"
    "{""(10.10.10.1,80)"",""(10.10.10.2,443)""}"
    "{""(10.10.10.3,8080)"",""(10.10.10.4,4040)""}"
    
    json:
    [{"addresses":[{"ip":"10.0.0.1","port":1},{"ip":"10.0.0.2","port":2}]},{"addresses":[{"ip":"10.10.10.1","port":80},{"ip":"10.10.10.2","port":443}]},{"addresses":[{"ip":"10.10.10.3","port":8080},{"ip":"10.10.10.4","port":4040}]}]
    


    1. 現在のアイテムIDの前後のN個の前のアイテムとM個の次のアイテムを選択します

    2. psycopg2を使用したpostgresqlDBの作成

    3. 別の分野のようなMySQL

    4. ORA-28040 sqlplusクライアントバージョン11.1を使用してSQLPLUSからOracle12cDBに接続するときに、一致する認証プロトコルがありません