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