Skip to content

Commit 28d4d9d

Browse files
committed
Add ! suffix and enhance error handling
1 parent 4979706 commit 28d4d9d

File tree

3 files changed

+64
-16
lines changed

3 files changed

+64
-16
lines changed

clickhouse-jdbc/src/main/java/com/clickhouse/jdbc/internal/ClickHouseStatementImpl.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -184,36 +184,48 @@ protected ClickHouseResponse processSqlStatement(ClickHouseSqlStatement stmt) th
184184
}
185185
return ClickHouseResponse.EMPTY;
186186
} else if (connection.getJdbcConfig().useLocalFile() && stmt.hasFile()) {
187-
final String file = ClickHouseUtils.unescape(stmt.getFile());
187+
String file = ClickHouseUtils.unescape(stmt.getFile());
188+
boolean suffix = file.lastIndexOf('!') == file.length() - 1;
189+
if (suffix) {
190+
file = file.substring(0, file.length() - 1);
191+
}
188192
if (stmt.getStatementType() == StatementType.SELECT) {
189-
ClickHouseFile f = ClickHouseFile.of(file);
190-
if (f.getFile().exists()) {
193+
ClickHouseFile f = ClickHouseFile.of(ClickHouseUtils.getFile(file));
194+
if (!suffix && f.getFile().exists()) {
191195
throw SqlExceptionUtils
192196
.clientError(ClickHouseUtils.format("Output file [%s] already exists!", f.getFile()));
193197
}
194198

199+
f = getFile(f, stmt);
195200
final ClickHouseResponseSummary summary = new ClickHouseResponseSummary(null, null);
196-
try (ClickHouseResponse response = request.query(stmt.getSQL()).output(getFile(f, stmt))
197-
.executeAndWait()) {
201+
try (ClickHouseResponse response = request.query(stmt.getSQL()).output(f).executeAndWait()) {
198202
summary.add(response.getSummary());
199203
} catch (ClickHouseException e) {
200204
throw SqlExceptionUtils.handle(e);
201205
}
202206
return ClickHouseSimpleResponse.of(getConfig(),
203207
Arrays.asList(ClickHouseColumn.of("file", ClickHouseDataType.String, false),
204-
ClickHouseColumn.of("rows", ClickHouseDataType.UInt64, false),
208+
ClickHouseColumn.of("format", ClickHouseDataType.String, false),
209+
ClickHouseColumn.of("compression", ClickHouseDataType.String, false),
210+
ClickHouseColumn.of("level", ClickHouseDataType.Int32, false),
205211
ClickHouseColumn.of("bytes", ClickHouseDataType.UInt64, false)),
206-
new Object[][] {
207-
{ file, summary.getReadRows(), summary.getReadBytes() }
208-
}, summary);
212+
new Object[][] { { file, f.getFormat().name(),
213+
f.hasCompression() ? f.getCompressionAlgorithm().encoding() : "none",
214+
f.getCompressionLevel(), f.getFile().length() } },
215+
summary);
209216
} else if (stmt.getStatementType() == StatementType.INSERT) {
210217
final Mutation m = request.write().query(stmt.getSQL());
211218
final ClickHouseResponseSummary summary = new ClickHouseResponseSummary(null, null);
212219
try {
213220
for (Path p : ClickHouseUtils.findFiles(file)) {
214221
ClickHouseFile f = ClickHouseFile.of(p.toFile());
215222
if (!f.getFile().exists()) {
216-
log.warn("Skip [%s] as it does not exist", f);
223+
if (suffix) {
224+
throw SqlExceptionUtils
225+
.clientError(ClickHouseUtils.format("File [%s] does not exist!", f.getFile()));
226+
} else {
227+
log.warn("Skip [%s] as it does not exist - perhaps it was just deleted somehow?", f);
228+
}
217229
} else {
218230
try (ClickHouseResponse response = m.data(getFile(f, stmt)).executeAndWait()) {
219231
summary.add(response.getSummary());
@@ -224,7 +236,7 @@ protected ClickHouseResponse processSqlStatement(ClickHouseSqlStatement stmt) th
224236
}
225237
}
226238
}
227-
if (summary.getUpdateCount() == 0) {
239+
if (suffix && summary.getUpdateCount() == 0) {
228240
throw SqlExceptionUtils.clientError("No file imported: " + file);
229241
}
230242
summary.seal();

clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHousePreparedStatementTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,15 @@ public void testOutFileAndInFile() throws SQLException {
12601260
Assert.assertFalse(rs.next());
12611261
}
12621262
Assert.assertTrue(f.exists());
1263+
1264+
stmt.setString(1, f.getName());
1265+
Assert.assertThrows(SQLException.class, () -> stmt.executeQuery());
1266+
stmt.setString(1, f.getName() + "!");
1267+
try (ResultSet rs = stmt.executeQuery()) {
1268+
Assert.assertTrue(rs.next());
1269+
Assert.assertEquals(rs.getString(1), f.getName());
1270+
Assert.assertFalse(rs.next());
1271+
}
12631272
}
12641273

12651274
try (PreparedStatement stmt = conn
@@ -1268,12 +1277,14 @@ public void testOutFileAndInFile() throws SQLException {
12681277
stmt.addBatch();
12691278
stmt.setString(1, f.getName());
12701279
stmt.addBatch();
1280+
stmt.setString(1, f.getName() + "!");
1281+
stmt.addBatch();
12711282
stmt.executeBatch();
12721283
}
12731284

12741285
try (ResultSet rs = s.executeQuery("select count(1), uniqExact(n) from test_load_infile_with_params")) {
12751286
Assert.assertTrue(rs.next(), "Should have at least one row");
1276-
Assert.assertEquals(rs.getInt(1), 999 * 2);
1287+
Assert.assertEquals(rs.getInt(1), 999 * 3);
12771288
Assert.assertEquals(rs.getInt(2), 999);
12781289
Assert.assertFalse(rs.next(), "Should have only one row");
12791290
}

clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,27 @@ public void testOutFileAndInFile() throws SQLException {
159159
}
160160

161161
try (ClickHouseConnection conn = newConnection(props)) {
162+
String sql1 = "select number n, toString(n) from numbers(1234) into outfile '" + f1.getName() + "'";
163+
try (ClickHouseStatement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql1)) {
164+
Assert.assertTrue(rs.next());
165+
Assert.assertFalse(rs.next());
166+
Assert.assertTrue(f1.exists());
167+
// end up with exception because the file already exists
168+
Assert.assertThrows(SQLException.class, () -> stmt.executeQuery(sql1));
169+
}
170+
171+
// try again with ! suffix to override the existing file
172+
String sql = "select number n, toString(n) from numbers(1234) into outfile '" + f1.getName() + "!'";
162173
try (ClickHouseStatement stmt = conn.createStatement();
163-
ResultSet rs = stmt.executeQuery(
164-
"select number n, toString(n) from numbers(1234) into outfile '" + f1.getName() + "'")) {
174+
ResultSet rs = stmt.executeQuery(sql)) {
165175
Assert.assertTrue(rs.next());
166176
Assert.assertFalse(rs.next());
177+
Assert.assertTrue(f1.exists());
167178
}
179+
180+
sql = "select number n, toString(n) from numbers(4321) into outfile '" + f2.getName() + "!'";
168181
try (ClickHouseStatement stmt = conn.createStatement();
169-
ResultSet rs = stmt.executeQuery(
170-
"select number n, toString(n) from numbers(4321) into outfile '" + f2.getName() + "'")) {
182+
ResultSet rs = stmt.executeQuery(sql)) {
171183
Assert.assertTrue(rs.next());
172184
Assert.assertFalse(rs.next());
173185
}
@@ -182,6 +194,19 @@ public void testOutFileAndInFile() throws SQLException {
182194
Assert.assertFalse(rs.next());
183195
}
184196
}
197+
198+
try (ClickHouseStatement stmt = conn.createStatement()) {
199+
// it's fine when no record was inserted
200+
stmt.executeUpdate("insert into test_load_infile from infile 'non-existent.csv'");
201+
// unless suffix ! was added...
202+
Assert.assertThrows(SQLException.class,
203+
() -> stmt.executeUpdate("insert into test_load_infile from infile 'non-existent.csv!'"));
204+
try (ResultSet rs = stmt.executeQuery("select count(1) from test_load_infile")) {
205+
Assert.assertTrue(rs.next());
206+
Assert.assertEquals(rs.getInt(1), 5555);
207+
Assert.assertFalse(rs.next());
208+
}
209+
}
185210
}
186211
}
187212

0 commit comments

Comments
 (0)