зеркало из https://github.com/github/vitess-gh.git
Merge pull request #1572 from youtube/caseInsensitiveMap
Case Insensitive Map for getting Column Index
This commit is contained in:
Коммит
6b7efe52ef
|
@ -20,6 +20,11 @@
|
||||||
<artifactId>jsr305</artifactId>
|
<artifactId>jsr305</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>3.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-collections4</artifactId>
|
||||||
|
<version>4.1</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<pluginRepositories>
|
<pluginRepositories>
|
||||||
|
|
|
@ -4,10 +4,11 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
|
|
||||||
import com.youtube.vitess.proto.Query.Field;
|
import com.youtube.vitess.proto.Query.Field;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.map.CaseInsensitiveMap;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -16,6 +17,9 @@ import javax.annotation.Nullable;
|
||||||
/**
|
/**
|
||||||
* A wrapper for {@code List<Field>} that also facilitates lookup by field name.
|
* A wrapper for {@code List<Field>} that also facilitates lookup by field name.
|
||||||
*
|
*
|
||||||
|
* <p>Lookups by field name are case-insensitive, as in {@link java.sql.ResultSet}.
|
||||||
|
* If multiple fields have the same name, the earliest one will be returned.
|
||||||
|
*
|
||||||
* <p>The field name maps to an index, rather than a Field, because that same
|
* <p>The field name maps to an index, rather than a Field, because that same
|
||||||
* index is also used to find the value in a separate list.
|
* index is also used to find the value in a separate list.
|
||||||
*/
|
*/
|
||||||
|
@ -26,25 +30,43 @@ public class FieldMap {
|
||||||
public FieldMap(Iterable<Field> fields) {
|
public FieldMap(Iterable<Field> fields) {
|
||||||
this.fields = ImmutableList.copyOf(checkNotNull(fields));
|
this.fields = ImmutableList.copyOf(checkNotNull(fields));
|
||||||
|
|
||||||
ImmutableMap.Builder<String, Integer> builder = new ImmutableMap.Builder<>();
|
indexMap = new CaseInsensitiveMap<String, Integer>();
|
||||||
// columnIndex is 1-based.
|
// columnIndex is 1-based.
|
||||||
int columnIndex = 1;
|
int columnIndex = 1;
|
||||||
for (Field field : this.fields) {
|
for (Field field : this.fields) {
|
||||||
builder.put(field.getName(), columnIndex++);
|
String columnLabel = field.getName();
|
||||||
|
// If multiple columns have the same name,
|
||||||
|
// prefer the earlier one as JDBC ResultSet does.
|
||||||
|
if (!indexMap.containsKey(columnLabel)) {
|
||||||
|
indexMap.put(columnLabel, columnIndex);
|
||||||
|
}
|
||||||
|
++columnIndex;
|
||||||
}
|
}
|
||||||
indexMap = builder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Field> getList() {
|
public List<Field> getList() {
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Field} for a 1-based column index.
|
||||||
|
*
|
||||||
|
* @param columnIndex 1-based column number (0 is invalid)
|
||||||
|
*/
|
||||||
public Field get(int columnIndex) {
|
public Field get(int columnIndex) {
|
||||||
// columnIndex is 1-based.
|
// columnIndex is 1-based.
|
||||||
checkArgument(columnIndex >= 1, "columnIndex out of range: %s", columnIndex);
|
checkArgument(columnIndex >= 1, "columnIndex out of range: %s", columnIndex);
|
||||||
return fields.get(columnIndex - 1);
|
return fields.get(columnIndex - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the 1-based index for a column label.
|
||||||
|
*
|
||||||
|
* <p>If multiple columns have the same label,
|
||||||
|
* the earlier one is returned.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public Integer getIndex(String columnLabel) {
|
public Integer getIndex(String columnLabel) {
|
||||||
return indexMap.get(columnLabel);
|
return indexMap.get(columnLabel);
|
||||||
|
|
|
@ -33,10 +33,12 @@ import javax.annotation.concurrent.NotThreadSafe;
|
||||||
* the list of {@link Field}s from the corresponding
|
* the list of {@link Field}s from the corresponding
|
||||||
* {@link com.youtube.vitess.proto.Query.QueryResult}.
|
* {@link com.youtube.vitess.proto.Query.QueryResult}.
|
||||||
*
|
*
|
||||||
* <p>Note that {@code columnIndex} values start at 1 for the first column,
|
* <p>Methods on {@code Row} are intended to be compatible with those on
|
||||||
* since the methods on {@code Row} are intended to be compatible with those
|
* {@link java.sql.ResultSet} where possible.
|
||||||
* on {@link java.sql.ResultSet} (which uses 1-based {@code columnIndex})
|
* This means {@code columnIndex} values start at 1 for the first column,
|
||||||
* where possible.
|
* and {@code columnLabel} values are case-insensitive. If multiple columns
|
||||||
|
* have the same case-insensitive {@code columnLabel}, the earliest one will
|
||||||
|
* be returned.
|
||||||
*/
|
*/
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
public class Row {
|
public class Row {
|
||||||
|
@ -115,6 +117,8 @@ public class Row {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns 1-based column number.
|
* Returns 1-based column number.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public int findColumn(String columnLabel) throws SQLException {
|
public int findColumn(String columnLabel) throws SQLException {
|
||||||
Integer columnIndex = fieldMap.getIndex(columnLabel);
|
Integer columnIndex = fieldMap.getIndex(columnLabel);
|
||||||
|
@ -124,6 +128,9 @@ public class Row {
|
||||||
return columnIndex;
|
return columnIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
|
*/
|
||||||
public Object getObject(String columnLabel) throws SQLException {
|
public Object getObject(String columnLabel) throws SQLException {
|
||||||
return getObject(findColumn(columnLabel));
|
return getObject(findColumn(columnLabel));
|
||||||
}
|
}
|
||||||
|
@ -161,6 +168,8 @@ public class Row {
|
||||||
*
|
*
|
||||||
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
||||||
* or {@link #getObject(String,Class)}.
|
* or {@link #getObject(String,Class)}.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public int getInt(String columnLabel) throws SQLException {
|
public int getInt(String columnLabel) throws SQLException {
|
||||||
return getInt(findColumn(columnLabel));
|
return getInt(findColumn(columnLabel));
|
||||||
|
@ -179,6 +188,9 @@ public class Row {
|
||||||
return value == null ? 0 : value;
|
return value == null ? 0 : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
|
*/
|
||||||
public UnsignedLong getULong(String columnLabel) throws SQLException {
|
public UnsignedLong getULong(String columnLabel) throws SQLException {
|
||||||
return getULong(findColumn(columnLabel));
|
return getULong(findColumn(columnLabel));
|
||||||
}
|
}
|
||||||
|
@ -190,6 +202,9 @@ public class Row {
|
||||||
return getObject(columnIndex, UnsignedLong.class);
|
return getObject(columnIndex, UnsignedLong.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
|
*/
|
||||||
public String getString(String columnLabel) throws SQLException {
|
public String getString(String columnLabel) throws SQLException {
|
||||||
return getString(findColumn(columnLabel));
|
return getString(findColumn(columnLabel));
|
||||||
}
|
}
|
||||||
|
@ -206,6 +221,8 @@ public class Row {
|
||||||
*
|
*
|
||||||
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
||||||
* or {@link #getObject(String,Class)}.
|
* or {@link #getObject(String,Class)}.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public long getLong(String columnLabel) throws SQLException {
|
public long getLong(String columnLabel) throws SQLException {
|
||||||
return getLong(findColumn(columnLabel));
|
return getLong(findColumn(columnLabel));
|
||||||
|
@ -229,6 +246,8 @@ public class Row {
|
||||||
*
|
*
|
||||||
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
||||||
* or {@link #getObject(String,Class)}.
|
* or {@link #getObject(String,Class)}.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public double getDouble(String columnLabel) throws SQLException {
|
public double getDouble(String columnLabel) throws SQLException {
|
||||||
return getDouble(findColumn(columnLabel));
|
return getDouble(findColumn(columnLabel));
|
||||||
|
@ -252,6 +271,8 @@ public class Row {
|
||||||
*
|
*
|
||||||
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
||||||
* or {@link #getObject(String,Class)}.
|
* or {@link #getObject(String,Class)}.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public float getFloat(String columnLabel) throws SQLException {
|
public float getFloat(String columnLabel) throws SQLException {
|
||||||
return getFloat(findColumn(columnLabel));
|
return getFloat(findColumn(columnLabel));
|
||||||
|
@ -272,6 +293,8 @@ public class Row {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the column value as a {@link Date} with the default time zone.
|
* Returns the column value as a {@link Date} with the default time zone.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public Date getDate(String columnLabel) throws SQLException {
|
public Date getDate(String columnLabel) throws SQLException {
|
||||||
return getDate(findColumn(columnLabel), Calendar.getInstance());
|
return getDate(findColumn(columnLabel), Calendar.getInstance());
|
||||||
|
@ -279,6 +302,8 @@ public class Row {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the column value as a {@link Date} with the given {@link Calendar}.
|
* Returns the column value as a {@link Date} with the given {@link Calendar}.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public Date getDate(String columnLabel, Calendar cal) throws SQLException {
|
public Date getDate(String columnLabel, Calendar cal) throws SQLException {
|
||||||
return getDate(findColumn(columnLabel), cal);
|
return getDate(findColumn(columnLabel), cal);
|
||||||
|
@ -317,6 +342,8 @@ public class Row {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the column value as {@link Time} with the default time zone.
|
* Returns the column value as {@link Time} with the default time zone.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public Time getTime(String columnLabel) throws SQLException {
|
public Time getTime(String columnLabel) throws SQLException {
|
||||||
return getTime(findColumn(columnLabel), Calendar.getInstance());
|
return getTime(findColumn(columnLabel), Calendar.getInstance());
|
||||||
|
@ -324,6 +351,8 @@ public class Row {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the column value as {@link Time} with the given {@link Calendar}.
|
* Returns the column value as {@link Time} with the given {@link Calendar}.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public Time getTime(String columnLabel, Calendar cal) throws SQLException {
|
public Time getTime(String columnLabel, Calendar cal) throws SQLException {
|
||||||
return getTime(findColumn(columnLabel), cal);
|
return getTime(findColumn(columnLabel), cal);
|
||||||
|
@ -362,6 +391,8 @@ public class Row {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the column value as {@link Timestamp} with the default time zone.
|
* Returns the column value as {@link Timestamp} with the default time zone.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public Timestamp getTimestamp(String columnLabel) throws SQLException {
|
public Timestamp getTimestamp(String columnLabel) throws SQLException {
|
||||||
return getTimestamp(findColumn(columnLabel), Calendar.getInstance());
|
return getTimestamp(findColumn(columnLabel), Calendar.getInstance());
|
||||||
|
@ -369,6 +400,8 @@ public class Row {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the column value as {@link Timestamp} with the given {@link Calendar}.
|
* Returns the column value as {@link Timestamp} with the given {@link Calendar}.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {
|
public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {
|
||||||
return getTimestamp(findColumn(columnLabel), cal);
|
return getTimestamp(findColumn(columnLabel), cal);
|
||||||
|
@ -410,6 +443,9 @@ public class Row {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
|
*/
|
||||||
public byte[] getBytes(String columnLabel) throws SQLException {
|
public byte[] getBytes(String columnLabel) throws SQLException {
|
||||||
return getBytes(findColumn(columnLabel));
|
return getBytes(findColumn(columnLabel));
|
||||||
}
|
}
|
||||||
|
@ -421,6 +457,9 @@ public class Row {
|
||||||
return getObject(columnIndex, byte[].class);
|
return getObject(columnIndex, byte[].class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
|
*/
|
||||||
public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
|
public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
|
||||||
return getBigDecimal(findColumn(columnLabel));
|
return getBigDecimal(findColumn(columnLabel));
|
||||||
}
|
}
|
||||||
|
@ -437,6 +476,8 @@ public class Row {
|
||||||
*
|
*
|
||||||
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
* <p>To distinguish between 0 and SQL NULL, use either {@link #wasNull()}
|
||||||
* or {@link #getObject(String,Class)}.
|
* or {@link #getObject(String,Class)}.
|
||||||
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
*/
|
*/
|
||||||
public short getShort(String columnLabel) throws SQLException {
|
public short getShort(String columnLabel) throws SQLException {
|
||||||
return getShort(findColumn(columnLabel));
|
return getShort(findColumn(columnLabel));
|
||||||
|
@ -494,6 +535,7 @@ public class Row {
|
||||||
* }
|
* }
|
||||||
* </pre></blockquote>
|
* </pre></blockquote>
|
||||||
*
|
*
|
||||||
|
* @param columnLabel case-insensitive column label
|
||||||
* @throws SQLDataException if the type doesn't match the actual value.
|
* @throws SQLDataException if the type doesn't match the actual value.
|
||||||
*/
|
*/
|
||||||
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
|
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
|
||||||
|
|
|
@ -32,12 +32,13 @@ public class CursorTest {
|
||||||
new SimpleCursor(
|
new SimpleCursor(
|
||||||
QueryResult.newBuilder()
|
QueryResult.newBuilder()
|
||||||
.addFields(Field.newBuilder().setName("col1").build())
|
.addFields(Field.newBuilder().setName("col1").build())
|
||||||
.addFields(Field.newBuilder().setName("col2").build())
|
.addFields(Field.newBuilder().setName("COL2").build()) // case-insensitive
|
||||||
.addFields(Field.newBuilder().setName("col3").build())
|
.addFields(Field.newBuilder().setName("col1").build()) // duplicate
|
||||||
|
.addFields(Field.newBuilder().setName("col4").build()) // skip duplicate
|
||||||
.build())) {
|
.build())) {
|
||||||
Assert.assertEquals(1, cursor.findColumn("col1"));
|
Assert.assertEquals(1, cursor.findColumn("col1")); // should return first col1
|
||||||
Assert.assertEquals(2, cursor.findColumn("col2"));
|
Assert.assertEquals(2, cursor.findColumn("Col2")); // should be case-insensitive
|
||||||
Assert.assertEquals(3, cursor.findColumn("col3"));
|
Assert.assertEquals(4, cursor.findColumn("col4")); // index should skip over duplicate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче