Repository: clickhouse/clickhouse-java
Issue: File data insert using CSVWithNames is failing since v0.3.2-patch10

We are using ClickHouse JDBC driver to import CSV files that include a header line with column names. Here is the JRuby code that we use https://github.com/rsim/mondrian-olap/blob/master/spec/rake_tasks.rb#L377-L380
```ruby
conn.jdbc_connection.createStatement.write.
  query("INSERT INTO #{table_name}(#{columns_string})").
  format(Java::com.clickhouse.client.ClickHouseFormat::CSVWithNames).
  data(file_path).send
```

It was working until the version v0.3.2-patch9 but since the version v0.3.2-patch10 it is failing with:
```
Java::JavaUtilConcurrent::CompletionException: com.clickhouse.client.ClickHouseException: Code: 27. DB::ParsingException: Cannot parse input: expected ',' before: 'id,the_date,the_day,the_month,the_year,day_of_month,week_of_year,month_of_year,quarter\\n1,2010-01-01 02:00:00,Friday,January,2010,1,0,1,Q1\\n2,2010-01-02 02:00:00,':
Row 1:
Column 0,   name: id,            type: Int32,    ERROR: text "id,the_dat" is not like Int32

: While executing ParallelParsingBlockInputFormat: (at row 1)
. (CANNOT_PARSE_INPUT_ASSERTION_FAILED) (version 22.1.4.1)
, server ClickHouseNode [uri=http://localhost:8123/mondrian_test]com.clickhouse.client.ClickHouseClientBuilder$Agent.handle(com/clickhouse/client/ClickHouseClientBuilder.java:181)
com.clickhouse.client.ClickHouseClientBuilder$Agent.send(com/clickhouse/client/ClickHouseClientBuilder.java:204)
com.clickhouse.client.ClickHouseClientBuilder$Agent.execute(com/clickhouse/client/ClickHouseClientBuilder.java:234)
com.clickhouse.client.ClickHouseRequest$Mutation.execute(com/clickhouse/client/ClickHouseRequest.java:241)
com.clickhouse.client.ClickHouseRequest$Mutation.send(com/clickhouse/client/ClickHouseRequest.java:292)
java.lang.reflect.Method.invoke(java/lang/reflect/Method.java:498)
```

It seems that now the CSV format (without the header line) is used instead of CSVWithNames and it complains about the first file line with column headers.

I was browsing the changes between patch9 and patch10 but couldn't identify so far which change could be causing this.

Changed files:
clickhouse-cli-client/src/main/java/com/clickhouse/client/cli/ClickHouseCommandLine.java
clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseRequest.java
clickhouse-client/src/test/java/com/clickhouse/client/ClientIntegrationTest.java

diff --git a/clickhouse-cli-client/src/main/java/com/clickhouse/client/cli/ClickHouseCommandLine.java b/clickhouse-cli-client/src/main/java/com/clickhouse/client/cli/ClickHouseCommandLine.java
index 5565b2aa..c4835963 100644
--- a/clickhouse-cli-client/src/main/java/com/clickhouse/client/cli/ClickHouseCommandLine.java
+++ b/clickhouse-cli-client/src/main/java/com/clickhouse/client/cli/ClickHouseCommandLine.java
@@ -124,7 +124,9 @@ public class ClickHouseCommandLine implements AutoCloseable {
                 process = null;
             }
 
-            cache.put(command, value);
+            if (value) { // no negative cache
+                cache.put(command, value);
+            }
         }
 
         return Boolean.TRUE.equals(value);
diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseRequest.java b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseRequest.java
index 4a3caf04..62428bff 100644
--- a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseRequest.java
+++ b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseRequest.java
@@ -196,7 +196,7 @@ public class ClickHouseRequest<SelfT extends ClickHouseRequest<SelfT>> implement
 
             final ClickHouseRequest<?> self = this;
             final ClickHouseFile wrappedFile = ClickHouseFile.of(file, compression, 0, null);
-            if (wrappedFile.hasFormat()) {
+            if (wrappedFile.hasFormat() && getFormat().defaultInputFormat() != wrappedFile.getFormat()) {
                 format(wrappedFile.getFormat());
             }
             this.input = changeProperty(PROP_DATA, this.input, ClickHouseDeferredValue
diff --git a/clickhouse-client/src/test/java/com/clickhouse/client/ClientIntegrationTest.java b/clickhouse-client/src/test/java/com/clickhouse/client/ClientIntegrationTest.java
index 0e2f42b8..c4a0f8f3 100644
--- a/clickhouse-client/src/test/java/com/clickhouse/client/ClientIntegrationTest.java
+++ b/clickhouse-client/src/test/java/com/clickhouse/client/ClientIntegrationTest.java
@@ -1403,7 +1403,7 @@ public abstract class ClientIntegrationTest extends BaseIntegrationTest {
     }
 
     @Test(groups = { "integration" })
-    public void testInsertWithCustomFormat() throws ClickHouseException {
+    public void testInsertWithCustomFormat1() throws ClickHouseException, IOException {
         ClickHouseNode server = getServer();
         sendAndWait(server, "drop table if exists test_custom_input_format",
                 "create table test_custom_input_format(i Int8, f String)engine=Memory");
@@ -1415,18 +1415,30 @@ public abstract class ClientIntegrationTest extends BaseIntegrationTest {
             }
             try (ClickHouseResponse response = request.write().format(ClickHouseFormat.CSVWithNames)
                     .table("test_custom_input_format")
-                    .data(o -> o.writeBytes("i,f\\n2,CSVWithNames".getBytes())).executeAndWait()) {
+                    .data(o -> o.writeBytes("i,f\\n2,CSVWithNames\\n3,CSVWithNames".getBytes(StandardCharsets.US_ASCII)))
+                    .executeAndWait()) {
+                // ignore
+            }
+
+            Path temp = Files.createTempFile("data", ".csv");
+            Assert.assertEquals(Files.size(temp), 0L);
+            Files.write(temp, "i,f\\n4,CSVWithNames\\n5,CSVWithNames\\n".getBytes(StandardCharsets.US_ASCII));
+            Assert.assertTrue(Files.size(temp) > 0L);
+            try (ClickHouseResponse response = request.write().format(ClickHouseFormat.CSVWithNames)
+                    .table("test_custom_input_format")
+                    .data(temp.toFile().getAbsolutePath()).executeAndWait()) {
                 // ignore
             }
+
             try (ClickHouseResponse response = request.query("select * from test_custom_input_format order by i")
                     .executeAndWait()) {
                 int count = 0;
                 for (ClickHouseRecord r : response.records()) {
                     Assert.assertEquals(r.getValue(0).asInteger(), count + 1);
-                    Assert.assertEquals(r.getValue(1).asString(), count == 0 ? "RowBinary" : "CSVWithNames");
+                    Assert.assertEquals(r.getValue(1).asString(), count < 1 ? "RowBinary" : "CSVWithNames");
                     count++;
                 }
-                Assert.assertEquals(count, 2);
+                Assert.assertEquals(count, 5);
             }
         }
     }
@@ -1481,9 +1493,10 @@ public abstract class ClientIntegrationTest extends BaseIntegrationTest {
         try (ClickHouseClient client = getClient()) {
             ClickHouseRequest<?> request = client.connect(server).format(ClickHouseFormat.RowBinary)
                     .session(sessionId);
-            request.query("drop temporary table if exists my_temp_table").executeAndWait();
-            request.query("create temporary table my_temp_table(a Int8)").executeAndWait();
-            request.query("insert into my_temp_table values(2)").executeAndWait();
+            execute(request, "drop temporary table if exists my_temp_table");
+            execute(request, "create temporary table my_temp_table(a Int8)");
+            execute(request, "insert into my_temp_table values(2)");
+
             try (ClickHouseResponse resp = request.write().table("my_temp_table")
                     .data(new ByteArrayInputStream(new byte[] { 3 })).executeAndWait()) {
                 // ignore