diff --git a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java index 23b05c983..7426ed43e 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java @@ -569,12 +569,15 @@ public Object[] getObjectArray(String colName) { @Override public boolean hasValue(int colIndex) { + if (colIndex < 1 || colIndex > currentRecord.length) { + return false; + } return currentRecord[colIndex - 1] != null; } @Override public boolean hasValue(String colName) { - return hasValue(schema.nameToColumnIndex(colName)); + return hasValue(schema.findColumnIndex(colName)); } @Override diff --git a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java index 07e65de39..94a89efae 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java @@ -2,6 +2,7 @@ import com.clickhouse.client.api.ClientException; import com.clickhouse.client.api.internal.DataTypeConverter; +import com.clickhouse.client.api.metadata.NoSuchColumnException; import com.clickhouse.client.api.metadata.TableSchema; import com.clickhouse.client.api.query.GenericRecord; import com.clickhouse.client.api.query.NullValueException; @@ -11,6 +12,7 @@ import com.clickhouse.data.value.ClickHouseGeoPointValue; import com.clickhouse.data.value.ClickHouseGeoPolygonValue; import com.clickhouse.data.value.ClickHouseGeoRingValue; +import com.google.common.collect.ImmutableList; import java.math.BigDecimal; import java.math.BigInteger; @@ -310,7 +312,8 @@ public String[] getStringArray(String colName) { @Override public boolean hasValue(int colIndex) { - return hasValue(schema.columnIndexToName(colIndex)); + String columnName = schema.findColumnName(colIndex); + return columnName != null && hasValue(columnName); } @Override diff --git a/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java b/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java index 023571dbd..fa9b86319 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java @@ -86,11 +86,10 @@ public ClickHouseColumn getColumnByIndex(int colIndex) { * @return - column name */ public String indexToName(int index) { - try { - return columns.get(index).getColumnName(); - } catch (IndexOutOfBoundsException e) { + if (index < 0 || index >= columns.size()) { throw new NoSuchColumnException("Result has no column with index = " + index); } + return columns.get(index).getColumnName(); } /** @@ -129,6 +128,25 @@ public int nameToIndex(String name) { return index; } + /** + * Looks up for column 1-based index for a column name. + * @param columnName - name of column to search + * @return column 1-based index of column or -1 if not found + */ + public int findColumnIndex(String columnName) { + Integer index = colIndex.get(columnName); + return index == null ? -1 : index + 1; + } + + public String findColumnName(int colIndex) { + int lookupIndex = colIndex - 1; + if (lookupIndex < 0 || lookupIndex >= columns.size()) { + return null; + } + + return columns.get(lookupIndex).getColumnName(); + } + @Override public String toString() { return "TableSchema{" + diff --git a/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java b/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java index a942f5fca..ad36c6c4d 100644 --- a/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java +++ b/client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java @@ -694,6 +694,41 @@ public void testQueryRecordsReadsAllValues() throws Exception { } } + @Test(groups = {"integration"}) + public void testSimpleResultSetReadWithBinaryReader() throws Exception { + QuerySettings settings = new QuerySettings().setFormat(ClickHouseFormat.RowBinaryWithNamesAndTypes); + + try (QueryResponse response = client.query("SELECT 1 a, null::Nullable(Int32) b", settings).get(3, TimeUnit.SECONDS)) { + ClickHouseBinaryFormatReader reader = client.newBinaryFormatReader(response); + + Assert.assertTrue(reader.hasNext()); + reader.next(); + Assert.assertEquals(reader.getInteger(1), 1); + + Assert.assertTrue(reader.hasValue(1)); + Assert.assertFalse(reader.hasValue(2)); + Assert.assertFalse(reader.hasValue(3)); + + Assert.assertTrue(reader.hasValue("a")); + Assert.assertFalse(reader.hasValue("b")); + Assert.assertFalse(reader.hasValue("c")); + } + + List records = client.queryAll("SELECT 1 a, null::Nullable(Int32) b", settings); + + GenericRecord record = records.get(0); + + Assert.assertEquals(record.getInteger(1), 1); + + Assert.assertTrue(record.hasValue(1)); + Assert.assertFalse(record.hasValue(2)); + Assert.assertFalse(record.hasValue(3)); + + Assert.assertTrue(record.hasValue("a")); + Assert.assertFalse(record.hasValue("b")); + Assert.assertFalse(record.hasValue("c")); + } + private final static List NULL_DATASET_COLUMNS = Arrays.asList( "id UInt32", "col1 UInt32 NULL",