Skip to content

Commit

Permalink
ResultSet.getInt/Long/Float/Double now return 0 for NULL values, getB…
Browse files Browse the repository at this point in the history
…oolean returns false for NULL values. This patch solves issue #81
  • Loading branch information
inserpio committed Sep 15, 2016
1 parent b9d8545 commit d2b4ccd
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 20 deletions.
Expand Up @@ -19,8 +19,23 @@
*/
package org.neo4j.jdbc.bolt;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.neo4j.driver.internal.types.InternalTypeSystem;
import org.neo4j.driver.internal.value.*;
import org.neo4j.driver.internal.value.BooleanValue;
import org.neo4j.driver.internal.value.FloatValue;
import org.neo4j.driver.internal.value.IntegerValue;
import org.neo4j.driver.internal.value.ListValue;
import org.neo4j.driver.internal.value.NodeValue;
import org.neo4j.driver.internal.value.PathValue;
import org.neo4j.driver.internal.value.RelationshipValue;
import org.neo4j.driver.internal.value.StringValue;
import org.neo4j.driver.v1.Record;
import org.neo4j.driver.v1.StatementResult;
import org.neo4j.driver.v1.Value;
Expand All @@ -30,12 +45,14 @@
import org.neo4j.driver.v1.types.Relationship;
import org.neo4j.driver.v1.types.Type;
import org.neo4j.driver.v1.util.Pair;
import org.neo4j.jdbc.*;
import org.neo4j.jdbc.Array;
import org.neo4j.jdbc.InstanceFactory;
import org.neo4j.jdbc.Loggable;
import org.neo4j.jdbc.ResultSet;
import org.neo4j.jdbc.ResultSetMetaData;
import org.neo4j.jdbc.Statement;
import org.neo4j.jdbc.impl.ListArray;

import java.sql.SQLException;
import java.util.*;

/**
* @author AgileLARUS
* @since 3.0.0
Expand Down Expand Up @@ -236,6 +253,7 @@ private String getStringFromValue(Value value) {
}
}

@SuppressWarnings("rawtypes")
private String convertToJSONProperty(String key, Object value) {
String result = key == null ? "" : "\"" + key + "\":";

Expand Down Expand Up @@ -326,7 +344,8 @@ private String convertPathToString(Path path) {

@Override public boolean getBoolean(String columnLabel) throws SQLException {
checkClosed();
return this.fetchValueFromLabel(columnLabel).asBoolean();
Value value = this.fetchValueFromLabel(columnLabel);
return value.isNull() ? false : value.asBoolean();
}

private Value fetchPropertyValue(String key, String property) throws SQLException {
Expand Down Expand Up @@ -397,12 +416,14 @@ private Value fetchValueFromIndex(int index) throws SQLException {

@Override public int getInt(String columnLabel) throws SQLException {
checkClosed();
return this.fetchValueFromLabel(columnLabel).asInt();
Value value = this.fetchValueFromLabel(columnLabel);
return value.isNull() ? 0 : value.asInt();
}

@Override public long getLong(String columnLabel) throws SQLException {
checkClosed();
return this.fetchValueFromLabel(columnLabel).asLong();
Value value = this.fetchValueFromLabel(columnLabel);
return value.isNull() ? 0 : value.asLong();
}

@Override public int findColumn(String columnLabel) throws SQLException {
Expand Down Expand Up @@ -430,42 +451,50 @@ private Value fetchValueFromIndex(int index) throws SQLException {

@Override public boolean getBoolean(int columnIndex) throws SQLException {
checkClosed();
return this.fetchValueFromIndex(columnIndex).asBoolean();
Value value = this.fetchValueFromIndex(columnIndex);
return value.isNull() ? false : value.asBoolean();
}

@Override public int getInt(int columnIndex) throws SQLException {
checkClosed();
return this.fetchValueFromIndex(columnIndex).asInt();
Value value = this.fetchValueFromIndex(columnIndex);
return value.isNull() ? 0 : value.asInt();
}

@Override public long getLong(int columnIndex) throws SQLException {
checkClosed();
return this.fetchValueFromIndex(columnIndex).asLong();
Value value = this.fetchValueFromIndex(columnIndex);
return value.isNull() ? 0 : value.asLong();
}

@Override public float getFloat(String columnLabel) throws SQLException {
checkClosed();
return this.fetchValueFromLabel(columnLabel).asFloat();
Value value = this.fetchValueFromLabel(columnLabel);
return value.isNull() ? 0 : value.asFloat();
}

@Override public float getFloat(int columnIndex) throws SQLException {
checkClosed();
return this.fetchValueFromIndex(columnIndex).asFloat();
Value value = this.fetchValueFromIndex(columnIndex);
return value.isNull() ? 0 : value.asFloat();
}

@Override public short getShort(String columnLabel) throws SQLException {
checkClosed();
return (short) this.fetchValueFromLabel(columnLabel).asInt();
Value value = this.fetchValueFromLabel(columnLabel);
return value.isNull() ? 0 : (short) value.asInt();
}

@Override public short getShort(int columnIndex) throws SQLException {
checkClosed();
return (short) this.fetchValueFromIndex(columnIndex).asInt();
Value value = this.fetchValueFromIndex(columnIndex);
return value.isNull() ? 0 : (short) value.asInt();
}

@Override public double getDouble(int columnIndex) throws SQLException {
checkClosed();
return this.fetchValueFromIndex(columnIndex).asDouble();
Value value = this.fetchValueFromIndex(columnIndex);
return value.isNull() ? 0 : value.asDouble();
}

@Override public Array getArray(int columnIndex) throws SQLException {
Expand All @@ -474,6 +503,7 @@ private Value fetchValueFromIndex(int index) throws SQLException {
return new ListArray(list, Array.getObjectType(list.get(0)));
}

@SuppressWarnings("rawtypes")
@Override public Array getArray(String columnLabel) throws SQLException {
checkClosed();
List list = this.fetchValueFromLabel(columnLabel).asList();
Expand All @@ -482,7 +512,8 @@ private Value fetchValueFromIndex(int index) throws SQLException {

@Override public double getDouble(String columnLabel) throws SQLException {
checkClosed();
return this.fetchValueFromLabel(columnLabel).asDouble();
Value value = this.fetchValueFromLabel(columnLabel);
return value.isNull() ? 0 : value.asDouble();
}

@Override public ResultSetMetaData getMetaData() throws SQLException {
Expand Down
Expand Up @@ -360,6 +360,16 @@ public class BoltResultSetGettersTest {
assertEquals(1, resultSet.getInt(4));
}

@Test public void getIntShouldReturnZeroForNull() throws SQLException {
StatementResult statementResult = ResultSetData
.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_ONE_NULL_ELEMENT, ResultSetData.RECORD_LIST_ONE_NULL_ELEMENT);
ResultSet resultSet = new BoltResultSet(null, statementResult);

resultSet.next();
assertEquals(0, resultSet.getInt("columnA"));
assertEquals(0, resultSet.getInt(2));
}

/*------------------------------*/
/* getFloat */
/*------------------------------*/
Expand Down Expand Up @@ -445,6 +455,16 @@ public class BoltResultSetGettersTest {
resultSet.getFloat(3);
}

@Test public void getFloatShouldReturnZeroForNull() throws SQLException {
StatementResult statementResult = ResultSetData
.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_ONE_NULL_ELEMENT, ResultSetData.RECORD_LIST_ONE_NULL_ELEMENT);
ResultSet resultSet = new BoltResultSet(null, statementResult);

resultSet.next();
assertEquals(0F, resultSet.getFloat("columnA"), 0);
assertEquals(0F, resultSet.getFloat(2), 0);
}

/*------------------------------*/
/* getShort */
/*------------------------------*/
Expand Down Expand Up @@ -530,6 +550,16 @@ public class BoltResultSetGettersTest {
resultSet.getShort(3);
}

@Test public void getShortShouldReturnZeroForNull() throws SQLException {
StatementResult statementResult = ResultSetData
.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_ONE_NULL_ELEMENT, ResultSetData.RECORD_LIST_ONE_NULL_ELEMENT);
ResultSet resultSet = new BoltResultSet(null, statementResult);

resultSet.next();
assertEquals(0, resultSet.getShort("columnA"));
assertEquals(0, resultSet.getShort(2));
}

/*------------------------------*/
/* getDouble */
/*------------------------------*/
Expand Down Expand Up @@ -614,6 +644,16 @@ public class BoltResultSetGettersTest {
resultSet.getDouble(5);
}

@Test public void getDoubleShouldReturnZeroForNull() throws SQLException {
StatementResult statementResult = ResultSetData
.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_ONE_NULL_ELEMENT, ResultSetData.RECORD_LIST_ONE_NULL_ELEMENT);
ResultSet resultSet = new BoltResultSet(null, statementResult);

resultSet.next();
assertEquals(0D, resultSet.getDouble("columnA"), 0);
assertEquals(0D, resultSet.getDouble(2), 0);
}

/*------------------------------*/
/* getObject */
/*------------------------------*/
Expand All @@ -626,6 +666,7 @@ public class BoltResultSetGettersTest {
resultSet.next();
assertEquals("value1", resultSet.getObject("columnString").toString());
assertEquals(1L, resultSet.getObject("columnInt"));
assertNull(resultSet.getObject("columnNull"));

resultSet.next();
assertEquals(2L, resultSet.getObject("columnShort"));
Expand Down Expand Up @@ -919,6 +960,16 @@ public class BoltResultSetGettersTest {
resultSet.getBoolean(6);
}

@Test public void getBooleanShouldReturnFalseForNull() throws SQLException {
StatementResult statementResult = ResultSetData
.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_ONE_NULL_ELEMENT, ResultSetData.RECORD_LIST_ONE_NULL_ELEMENT);
ResultSet resultSet = new BoltResultSet(null, statementResult);

resultSet.next();
assertEquals(false, resultSet.getBoolean("columnA"));
assertEquals(false, resultSet.getBoolean(2));
}

/*------------------------------*/
/* getLong */
/*------------------------------*/
Expand Down Expand Up @@ -1002,6 +1053,16 @@ public class BoltResultSetGettersTest {
resultSet.getLong(7);
}

@Test public void getLongShouldReturnZeroForNull() throws SQLException {
StatementResult statementResult = ResultSetData
.buildResultCursor(ResultSetData.KEYS_RECORD_LIST_ONE_NULL_ELEMENT, ResultSetData.RECORD_LIST_ONE_NULL_ELEMENT);
ResultSet resultSet = new BoltResultSet(null, statementResult);

resultSet.next();
assertEquals(0, resultSet.getLong("columnA"));
assertEquals(0, resultSet.getLong(2));
}

/*------------------------------*/
/* getHoldability */
/*------------------------------*/
Expand Down
Expand Up @@ -45,6 +45,7 @@
public class ResultSetData {
public static List<Object[]> RECORD_LIST_EMPTY = Collections.emptyList();
public static List<Object[]> RECORD_LIST_ONE_ELEMENT;
public static List<Object[]> RECORD_LIST_ONE_NULL_ELEMENT;
public static List<Object[]> RECORD_LIST_MORE_ELEMENTS;
public static List<Object[]> RECORD_LIST_MORE_ELEMENTS_DIFF;
public static List<Object[]> RECORD_LIST_MORE_ELEMENTS_MIXED;
Expand All @@ -55,10 +56,11 @@ public class ResultSetData {

public static String[] KEYS_RECORD_LIST_EMPTY = new String[] {};
public static String[] KEYS_RECORD_LIST_ONE_ELEMENT = new String[] { "columnA", "columnB" };
public static String[] KEYS_RECORD_LIST_ONE_NULL_ELEMENT = KEYS_RECORD_LIST_ONE_ELEMENT;
public static String[] KEYS_RECORD_LIST_MORE_ELEMENTS = KEYS_RECORD_LIST_ONE_ELEMENT;
public static String[] KEYS_RECORD_LIST_MORE_ELEMENTS_DIFF = new String[] { "columnA", "columnB", "columnC" };
public static String[] KEYS_RECORD_LIST_MORE_ELEMENTS_MIXED = new String[] { "columnInt", "columnString", "columnFloat", "columnShort", "columnDouble",
"columnBoolean", "columnLong" };
"columnBoolean", "columnLong", "columnNull" };
public static String[] KEYS_RECORD_LIST_MORE_ELEMENTS_NODES = new String[] { "node" };
public static String[] KEYS_RECORD_LIST_MORE_ELEMENTS_PATHS = new String[] { "path" };
public static String[] KEYS_RECORD_LIST_MORE_ELEMENTS_RELATIONS = new String[] { "relation" };
Expand All @@ -74,15 +76,18 @@ public class ResultSetData {
RECORD_LIST_ONE_ELEMENT = new LinkedList<>();
RECORD_LIST_ONE_ELEMENT.add(new Object[] { "valueA1", "valueB1" });

RECORD_LIST_ONE_NULL_ELEMENT = new LinkedList<>();
RECORD_LIST_ONE_NULL_ELEMENT.add(new Object[] { null, null });

RECORD_LIST_MORE_ELEMENTS = new LinkedList<>();
RECORD_LIST_MORE_ELEMENTS.add(new Object[] { "valueA1", "valueB1" });
RECORD_LIST_MORE_ELEMENTS.add(new Object[] { "valueA2", "valueB2" });
RECORD_LIST_MORE_ELEMENTS.add(new Object[] { "valueA3", "valueB3" });

RECORD_LIST_MORE_ELEMENTS_MIXED = new LinkedList<>();

RECORD_LIST_MORE_ELEMENTS_MIXED.add(new Object[] { 1, "value1", 0.1f, (short) 1, 02.29D, true, 2L });
RECORD_LIST_MORE_ELEMENTS_MIXED.add(new Object[] { 2, "value2", 0.2f, (short) 2, 20.16D, false, 6L });
RECORD_LIST_MORE_ELEMENTS_MIXED.add(new Object[] { 1, "value1", 0.1f, (short) 1, 02.29D, true, 2L, null });
RECORD_LIST_MORE_ELEMENTS_MIXED.add(new Object[] { 2, "value2", 0.2f, (short) 2, 20.16D, false, 6L, null });

RECORD_LIST_MORE_ELEMENTS_NODES = new LinkedList<>();

Expand Down

1 comment on commit d2b4ccd

@fbiville
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my 2 cents: that deserves a PR against the Java driver to encapsulate this behavior.
AsXxx if Xxx is a primitive type should be default-value-aware, that does not seem like something the JDBC driver should concern itself with.

Please sign in to comment.