20
20
package org .flywaydb .community .database .questdb ;
21
21
22
22
import org .flywaydb .core .Flyway ;
23
- import org .junit .ClassRule ;
23
+ import org .flywaydb .core .api .output .MigrateResult ;
24
+ import org .junit .Rule ;
24
25
import org .junit .Test ;
25
26
import org .testcontainers .containers .GenericContainer ;
26
27
import org .testcontainers .utility .DockerImageName ;
@@ -33,37 +34,172 @@ public class QuestDBTest {
33
34
private static final DockerImageName QUESTDB_IMAGE = DockerImageName .parse ("questdb/questdb:nightly" );
34
35
private static final int HTTP_PORT = 9000 ;
35
36
private static final int PG_PORT = 8812 ;
37
+ private static final String LOCATION = "classpath:questdb/migration" ;
38
+ private static final String USER = "admin" ;
39
+ private static final String PWD = "quest" ;
36
40
37
- @ ClassRule
38
- public static GenericContainer <?> questdb = new GenericContainer <>(QUESTDB_IMAGE )
41
+ @ Rule
42
+ public GenericContainer <?> questdb = new GenericContainer <>(QUESTDB_IMAGE )
39
43
.withExposedPorts (HTTP_PORT , PG_PORT )
40
44
.withLogConsumer (outputFrame -> System .out .println (outputFrame .getUtf8String ()));
41
-
45
+
46
+ @ Test
47
+ public void testMigration1_CreateTable () throws SQLException {
48
+ assertMigration (
49
+ "1" ,
50
+ "select table_name, designatedTimestamp, partitionBy,walEnabled from tables()" ,
51
+ "table_name\t designatedTimestamp\t partitionBy\t walEnabled\n " +
52
+ "trades\t ts\t DAY\t t\n " +
53
+ "flyway_schema_history\t installed_on\t DAY\t t\n "
54
+ );
55
+ }
56
+
57
+ @ Test
58
+ public void testMigration2_InsertData () throws SQLException {
59
+ assertMigration (
60
+ "2" ,
61
+ "trades" ,
62
+ "instrument\t side\t qty\t price\t ts\n " +
63
+ "SYM1\t BUY\t 100.0\t 12.56\t 2025-05-09 00:01:00.000000\n " +
64
+ "SYM2\t BUY\t 120.0\t 10.11\t 2025-05-09 00:02:00.000000\n " +
65
+ "SYM1\t SELL\t 50.0\t 12.44\t 2025-05-09 00:03:00.000000\n "
66
+ );
67
+ }
68
+
69
+ @ Test
70
+ public void testMigration3_RenameTable () throws SQLException {
71
+ assertMigration (
72
+ "3" ,
73
+ "trades_table" ,
74
+ "instrument\t side\t qty\t price\t ts\n " +
75
+ "SYM1\t BUY\t 100.0\t 12.56\t 2025-05-09 00:01:00.000000\n " +
76
+ "SYM2\t BUY\t 120.0\t 10.11\t 2025-05-09 00:02:00.000000\n " +
77
+ "SYM1\t SELL\t 50.0\t 12.44\t 2025-05-09 00:03:00.000000\n "
78
+ );
79
+ }
80
+
81
+ @ Test
82
+ public void testMigration4_AddColumn () throws SQLException {
83
+ assertMigration (
84
+ "4" ,
85
+ "show create table trades" ,
86
+ "ddl\n " +
87
+ "CREATE TABLE 'trades' ( \n " +
88
+ "\t instrument SYMBOL CAPACITY 256 CACHE,\n " +
89
+ "\t side SYMBOL CAPACITY 256 CACHE,\n " +
90
+ "\t qty DOUBLE,\n " +
91
+ "\t price DOUBLE,\n " +
92
+ "\t ts TIMESTAMP,\n " +
93
+ "\t venue VARCHAR\n " +
94
+ ") timestamp(ts) PARTITION BY DAY WAL\n " +
95
+ "WITH maxUncommittedRows=500000, o3MaxLag=600000000us;\n "
96
+ );
97
+ }
98
+
99
+ @ Test
100
+ public void testMigration5_AlterColumnType () throws SQLException {
101
+ assertMigration (
102
+ "5" ,
103
+ "show create table trades" ,
104
+ "ddl\n " +
105
+ "CREATE TABLE 'trades' ( \n " +
106
+ "\t instrument SYMBOL CAPACITY 256 CACHE,\n " +
107
+ "\t side SYMBOL CAPACITY 256 CACHE,\n " +
108
+ "\t qty DOUBLE,\n " +
109
+ "\t price DOUBLE,\n " +
110
+ "\t ts TIMESTAMP,\n " +
111
+ "\t venue SYMBOL CAPACITY 256 CACHE\n " +
112
+ ") timestamp(ts) PARTITION BY DAY WAL\n " +
113
+ "WITH maxUncommittedRows=500000, o3MaxLag=600000000us;\n "
114
+ );
115
+ }
116
+
117
+ @ Test
118
+ public void testMigration6_DropColumn () throws SQLException {
119
+ assertMigration (
120
+ "6" ,
121
+ "show create table trades" ,
122
+ "ddl\n " +
123
+ "CREATE TABLE 'trades' ( \n " +
124
+ "\t instrument SYMBOL CAPACITY 256 CACHE,\n " +
125
+ "\t side SYMBOL CAPACITY 256 CACHE,\n " +
126
+ "\t qty DOUBLE,\n " +
127
+ "\t price DOUBLE,\n " +
128
+ "\t ts TIMESTAMP\n " +
129
+ ") timestamp(ts) PARTITION BY DAY WAL\n " +
130
+ "WITH maxUncommittedRows=500000, o3MaxLag=600000000us;\n "
131
+ );
132
+ }
133
+
42
134
@ Test
43
- public void testQuestDBContainer () throws SQLException {
135
+ public void testMigration7_DropTable () throws SQLException {
136
+ assertMigration (
137
+ "7" ,
138
+ "select table_name, designatedTimestamp, partitionBy,walEnabled from tables()" ,
139
+ "table_name\t designatedTimestamp\t partitionBy\t walEnabled\n " +
140
+ "flyway_schema_history\t installed_on\t DAY\t t\n "
141
+ );
142
+ }
143
+
144
+ private void assertMigration (String version , String query , String expectedResult ) throws SQLException {
145
+ final String jdbcUrl = jdbcUrl ();
146
+
147
+ final Flyway flyway = flyway (jdbcUrl , version );
148
+ final MigrateResult migrateResult = flyway .migrate ();
149
+ assertEquals (0 , migrateResult .getFailedMigrations ().size ());
150
+
151
+ assertQuery (jdbcUrl , query , expectedResult );
152
+ }
153
+
154
+ private String jdbcUrl () {
44
155
final String host = questdb .getHost ();
45
156
final int port = questdb .getMappedPort (PG_PORT );
157
+ return "jdbc:postgresql://" + host + ":" + port + "/default" ;
158
+ }
159
+
160
+ private static Flyway flyway (String jdbcUrl , String version ) {
161
+ return Flyway
162
+ .configure ()
163
+ .locations (LOCATION )
164
+ .dataSource (jdbcUrl , USER , PWD )
165
+ .target (version )
166
+ .load ();
167
+ }
46
168
47
- try (Connection connection = DriverManager .getConnection (
48
- "jdbc:postgresql://" + host + ":" + port + "/qdb" , "admin" , "quest"
49
- )) {
169
+ private static void assertQuery (String jdbcUrl , String query , String expectedResult ) throws SQLException {
170
+ try (Connection connection = DriverManager .getConnection (jdbcUrl , USER , PWD )) {
50
171
try (Statement statement = connection .createStatement ();
51
- ResultSet resultSet = statement .executeQuery ("select 1" )) {
52
- resultSet .next ();
53
- assertEquals (1 , resultSet .getInt (1 ));
172
+ ResultSet resultSet = statement .executeQuery (query )) {
173
+ assertEquals (expectedResult , resultSetToString (resultSet ));
54
174
}
55
175
}
56
176
}
57
-
58
- @ Test
59
- public void testQuestDBFlyway () {
60
- final String host = questdb .getHost ();
61
- final int port = questdb .getMappedPort (PG_PORT );
62
177
63
- final Flyway flyway = Flyway .configure ().dataSource (
64
- "jdbc:postgresql://" + host + ":" + port + "/qdb" , "admin" , "quest"
65
- ).load ();
178
+ private static String resultSetToString (ResultSet rs ) throws SQLException {
179
+ final StringBuilder sb = new StringBuilder ();
180
+ final ResultSetMetaData metaData = rs .getMetaData ();
181
+ final int columnCount = metaData .getColumnCount ();
182
+
183
+ // Print column headers
184
+ for (int i = 1 ; i <= columnCount ; i ++) {
185
+ sb .append (metaData .getColumnName (i ));
186
+ if (i < columnCount ) {
187
+ sb .append ("\t " );
188
+ }
189
+ }
190
+ sb .append ("\n " );
191
+
192
+ // Print rows
193
+ while (rs .next ()) {
194
+ for (int i = 1 ; i <= columnCount ; i ++) {
195
+ sb .append (rs .getString (i ));
196
+ if (i < columnCount ) {
197
+ sb .append ("\t " );
198
+ }
199
+ }
200
+ sb .append ("\n " );
201
+ }
66
202
67
- flyway . migrate ();
203
+ return sb . toString ();
68
204
}
69
205
}
0 commit comments