提交 eb396945 authored 作者: Max Englander's avatar Max Englander

enum-support: handle enum comparisons with ints and strings

上级 d0fe846b
...@@ -4200,13 +4200,13 @@ public class Parser { ...@@ -4200,13 +4200,13 @@ public class Parser {
if (readIf("(")) { if (readIf("(")) {
original += '('; original += '(';
String enumerator0 = readString(); String enumerator0 = readString();
enumerators.add(enumerator0); enumerators.add(enumerator0.toLowerCase().trim());
original += "'" + enumerator0 + "'"; original += "'" + enumerator0 + "'";
while(readIf(",")) { while(readIf(",")) {
original += ','; original += ',';
String enumeratorN = readString(); String enumeratorN = readString();
original += "'" + enumeratorN + "'"; original += "'" + enumeratorN + "'";
enumerators.add(enumeratorN); enumerators.add(enumeratorN.toLowerCase().trim());
} }
read(")"); read(")");
original += ')'; original += ')';
...@@ -4232,7 +4232,7 @@ public class Parser { ...@@ -4232,7 +4232,7 @@ public class Parser {
Integer.toString(scale), Long.toString(precision)); Integer.toString(scale), Long.toString(precision));
} }
Column column = new Column(columnName, type, precision, scale, Column column = new Column(columnName, type, precision, scale,
displaySize, enumerators); displaySize, enumerators.toArray(new String[enumerators.size()]));
if (templateColumn != null) { if (templateColumn != null) {
column.setNullable(templateColumn.isNullable()); column.setNullable(templateColumn.isNullable());
column.setDefaultExpression(session, column.setDefaultExpression(session,
......
...@@ -189,9 +189,7 @@ public class ExpressionColumn extends Expression { ...@@ -189,9 +189,7 @@ public class ExpressionColumn extends Expression {
throw DbException.get(ErrorCode.MUST_GROUP_BY_COLUMN_1, getSQL()); throw DbException.get(ErrorCode.MUST_GROUP_BY_COLUMN_1, getSQL());
} }
if (column.getEnumerators() != null) { if (column.getEnumerators() != null) {
final int ordinal = value.getInt(); return ValueEnum.get(column.getEnumerators(), value);
return new ValueEnum(column.getEnumerators()
.toArray(new String[column.getEnumerators().size()]), ordinal);
} }
return value; return value;
} }
......
...@@ -199,6 +199,7 @@ public class ValueDataType implements DataType { ...@@ -199,6 +199,7 @@ public class ValueDataType implements DataType {
case Value.SHORT: case Value.SHORT:
buff.put((byte) type).putShort(v.getShort()); buff.put((byte) type).putShort(v.getShort());
break; break;
case Value.ENUM:
case Value.INT: { case Value.INT: {
int x = v.getInt(); int x = v.getInt();
if (x < 0) { if (x < 0) {
......
...@@ -7,7 +7,6 @@ package org.h2.table; ...@@ -7,7 +7,6 @@ package org.h2.table;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.Parser; import org.h2.command.Parser;
import org.h2.engine.Constants; import org.h2.engine.Constants;
...@@ -28,6 +27,7 @@ import org.h2.util.StringUtils; ...@@ -28,6 +27,7 @@ import org.h2.util.StringUtils;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueDate; import org.h2.value.ValueDate;
import org.h2.value.ValueEnum;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
import org.h2.value.ValueLong; import org.h2.value.ValueLong;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
...@@ -68,7 +68,7 @@ public class Column { ...@@ -68,7 +68,7 @@ public class Column {
private final int type; private final int type;
private long precision; private long precision;
private int scale; private int scale;
private List<String> enumerators; private String[] enumerators;
private int displaySize; private int displaySize;
private Table table; private Table table;
private String name; private String name;
...@@ -94,7 +94,7 @@ public class Column { ...@@ -94,7 +94,7 @@ public class Column {
this(name, type, -1, -1, -1, null); this(name, type, -1, -1, -1, null);
} }
public Column(String name, int type, List<String> enumerators) { public Column(String name, int type, String[] enumerators) {
this(name, type, -1, -1, -1, enumerators); this(name, type, -1, -1, -1, enumerators);
} }
...@@ -104,7 +104,7 @@ public class Column { ...@@ -104,7 +104,7 @@ public class Column {
} }
public Column(String name, int type, long precision, int scale, public Column(String name, int type, long precision, int scale,
int displaySize, List<String> enumerators) { int displaySize, String[] enumerators) {
this.name = name; this.name = name;
this.type = type; this.type = type;
if (precision == -1 && scale == -1 && displaySize == -1 && type != Value.UNKNOWN) { if (precision == -1 && scale == -1 && displaySize == -1 && type != Value.UNKNOWN) {
...@@ -145,6 +145,10 @@ public class Column { ...@@ -145,6 +145,10 @@ public class Column {
return table.getId() ^ name.hashCode(); return table.getId() ^ name.hashCode();
} }
public boolean isEnumerated() {
return enumerators != null && enumerators.length > 0;
}
public Column getClone() { public Column getClone() {
Column newColumn = new Column(name, type, precision, scale, displaySize, enumerators); Column newColumn = new Column(name, type, precision, scale, displaySize, enumerators);
newColumn.copy(this); newColumn.copy(this);
...@@ -270,11 +274,11 @@ public class Column { ...@@ -270,11 +274,11 @@ public class Column {
nullable = b; nullable = b;
} }
public List<String> getEnumerators() { public String[] getEnumerators() {
return enumerators; return enumerators;
} }
public void setEnumerators(List<String> enumerators) { public void setEnumerators(String[] enumerators) {
this.enumerators = enumerators; this.enumerators = enumerators;
} }
...@@ -357,24 +361,17 @@ public class Column { ...@@ -357,24 +361,17 @@ public class Column {
getCreateSQL(), s + " (" + value.getPrecision() + ")"); getCreateSQL(), s + " (" + value.getPrecision() + ")");
} }
} }
if (!enumerators.isEmpty()) { if (isEnumerated()) {
int index; if (!ValueEnum.isValid(enumerators, value)) {
if (DataType.isStringType(value.getType())) {
index = enumerators.indexOf(value.getString());
} else {
index = value.getInt() < enumerators.size() ? value.getInt() : -1;
}
if (index == -1) {
String s = value.getTraceSQL(); String s = value.getTraceSQL();
if (s.length() > 127) { if (s.length() > 127) {
s = s.substring(0, 128) + "..."; s = s.substring(0, 128) + "...";
} }
throw DbException.get(ErrorCode.VALUE_NOT_PERMITTED, throw DbException.get(ErrorCode.VALUE_NOT_PERMITTED,
getCreateSQL(), s + " (" + value.getString() + ")"); getCreateSQL(), s + " (" + value.getString() + ")");
} else {
value = ValueInt.get(index);
} }
value = ValueEnum.get(enumerators, value);
} }
updateSequenceIfRequired(session, value); updateSequenceIfRequired(session, value);
return value; return value;
...@@ -467,10 +464,9 @@ public class Column { ...@@ -467,10 +464,9 @@ public class Column {
break; break;
case Value.ENUM: case Value.ENUM:
buff.append('('); buff.append('(');
Iterator<String> it = enumerators.iterator(); for (int i = 0; i < enumerators.length; i++) {
while(it.hasNext()) { buff.append('\'').append(enumerators[i]).append('\'');
buff.append('\'').append(it.next()).append('\''); if(i < enumerators.length - 1) {
if(it.hasNext()) {
buff.append(','); buff.append(',');
} }
} }
......
...@@ -852,11 +852,13 @@ public abstract class Value { ...@@ -852,11 +852,13 @@ public abstract class Value {
} }
break; break;
} }
case ENUM: case ENUM: {
switch (getType()) { switch (getType()) {
case INT: case INT:
case STRING:
return this; return this;
} }
}
case BLOB: { case BLOB: {
switch (getType()) { switch (getType()) {
case BYTES: case BYTES:
...@@ -984,7 +986,7 @@ public abstract class Value { ...@@ -984,7 +986,7 @@ public abstract class Value {
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw DbException.get( throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, e, getString()); ErrorCode.DATA_CONVERSION_ERROR_1, e, getString() + " type=" + getType());
} }
} }
......
...@@ -3,36 +3,91 @@ package org.h2.value; ...@@ -3,36 +3,91 @@ package org.h2.value;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.api.ErrorCode;
import org.h2.message.DbException;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.value.DataType;
public class ValueEnum extends Value { public class ValueEnum extends Value {
public static final int PRECISION = 10; public static final int PRECISION = 10;
public static final int DISPLAY_SIZE = 11; public static final int DISPLAY_SIZE = 11;
private final String[] labels; private static enum Validation {
DUPLICATE,
EMPTY,
INVALID,
VALID
}
private final String[] enumerators;
private final String label; private final String label;
private final int ordinal; private final int ordinal;
public ValueEnum(final String[] labels, final int ordinal) { private ValueEnum(final String[] enumerators, final int ordinal) {
this.label = labels[ordinal]; this.label = enumerators[ordinal];
this.labels = labels; this.enumerators = enumerators;
this.ordinal = ordinal; this.ordinal = ordinal;
} }
@Override private static final void check(final String[] enumerators) {
public Value add(final Value v) { switch (validate(enumerators)) {
throw new UnsupportedOperationException("Not yet implemented"); case VALID:
return;
case EMPTY:
throw DbException.get(ErrorCode.INVALID_VALUE_2,
"Empty enum is not allowed");
case DUPLICATE:
throw DbException.get(ErrorCode.INVALID_VALUE_2,
"Enum with duplicate enumerator is not allowed");
default:
throw DbException.get(ErrorCode.INVALID_VALUE_2,
"Invalid enumerator list for enum");
}
} }
@Override private static final void check(final String[] enumerators, final String label) {
protected int compareSecure(final Value o, final CompareMode mode) { check(enumerators);
final ValueEnum v = (ValueEnum) o;
return MathUtils.compareInt(ordinal(), v.ordinal()); switch (validate(enumerators, label)) {
case VALID:
return;
case EMPTY:
throw DbException.get(ErrorCode.VALUE_NOT_PERMITTED,
"Enumerator label may not be empty");
default:
throw DbException.get(ErrorCode.VALUE_NOT_PERMITTED,
"Enumerator label is invalid");
}
}
private static final void check(final String[] enumerators, final int ordinal) {
check(enumerators);
switch (validate(enumerators, ordinal)) {
case VALID:
return;
default:
throw DbException.get(ErrorCode.VALUE_NOT_PERMITTED,
"Provided enumerator label does not match any member of enum");
}
}
private static final void check(final String[] enumerators, final Value value) {
check(enumerators);
switch (validate(enumerators, value)) {
case VALID:
return;
default:
throw DbException.get(ErrorCode.VALUE_NOT_PERMITTED,
"Provided value is does not match any enumerators");
}
} }
@Override @Override
public Value divide(final Value v) { protected int compareSecure(final Value o, final CompareMode mode) {
throw new UnsupportedOperationException("Not yet implemented"); final ValueEnum v = ValueEnum.get(enumerators, o);
return MathUtils.compareInt(ordinal(), v.ordinal());
} }
@Override @Override
...@@ -41,6 +96,32 @@ public class ValueEnum extends Value { ...@@ -41,6 +96,32 @@ public class ValueEnum extends Value {
ordinal() == ((ValueEnum) other).ordinal(); ordinal() == ((ValueEnum) other).ordinal();
} }
public static ValueEnum get(final String[] enumerators, final String label) {
check(enumerators, label);
for (int i = 0; i < enumerators.length; i++) {
if (label.equals(enumerators[i]))
return new ValueEnum(enumerators, i);
}
throw DbException.get(ErrorCode.GENERAL_ERROR_1, "Unexpected error");
}
public static ValueEnum get(final String[] enumerators, final int ordinal) {
check(enumerators, ordinal);
return new ValueEnum(enumerators, ordinal);
}
public static ValueEnum get(final String[] enumerators, final Value value) {
check(enumerators, value);
if (DataType.isStringType(value.getType())) {
return get(enumerators, value.getString());
} else {
return get(enumerators, value.getInt());
}
}
@Override @Override
public int getDisplaySize() { public int getDisplaySize() {
return DISPLAY_SIZE; return DISPLAY_SIZE;
...@@ -83,27 +164,24 @@ public class ValueEnum extends Value { ...@@ -83,27 +164,24 @@ public class ValueEnum extends Value {
@Override @Override
public int hashCode() { public int hashCode() {
return ordinal; return enumerators.hashCode() + ordinal;
} }
@Override public static boolean isValid(final String enumerators[], final String label) {
public int getType() { return validate(enumerators, label).equals(Validation.VALID);
return Value.INT;
} }
@Override public static boolean isValid(final String enumerators[], final int ordinal) {
public Value modulus(final Value v) { return validate(enumerators, ordinal).equals(Validation.VALID);
throw new UnsupportedOperationException("Not yet implemented");
} }
@Override public static boolean isValid(final String enumerators[], final Value value) {
public Value multiply(final Value v) { return validate(enumerators, value).equals(Validation.VALID);
throw new UnsupportedOperationException("Not yet implemented");
} }
@Override @Override
public Value negate() { public int getType() {
throw new UnsupportedOperationException("Not yet implemented"); return Value.ENUM;
} }
protected int ordinal() { protected int ordinal() {
...@@ -116,8 +194,55 @@ public class ValueEnum extends Value { ...@@ -116,8 +194,55 @@ public class ValueEnum extends Value {
prep.setInt(parameterIndex, ordinal); prep.setInt(parameterIndex, ordinal);
} }
@Override private static Validation validate(final String[] enumerators, final String label) {
public Value subtract(final Value v) { check(enumerators);
throw new UnsupportedOperationException("Not yet implemented");
if (label == null || label.trim().length() == 0) {
return Validation.EMPTY;
}
for (int i = 0; i < enumerators.length; i++) {
if (label.equals(enumerators[i])) {
return Validation.VALID;
}
}
return Validation.INVALID;
}
private static Validation validate(final String[] enumerators) {
for (int i = 0; i < enumerators.length; i++) {
if (enumerators[i] == null || enumerators[i].equals("")) {
return Validation.EMPTY;
}
if (i < enumerators.length - 1) {
for (int j = i + 1; j < enumerators.length; j++) {
if (enumerators[i].equals(enumerators[j])) {
return Validation.DUPLICATE;
}
}
}
}
return Validation.VALID;
}
private static Validation validate(final String[] enumerators, final int ordinal) {
check(enumerators);
if (ordinal < 0 || ordinal >= enumerators.length) {
return Validation.INVALID;
}
return Validation.VALID;
}
private static Validation validate(final String[] enumerators, final Value value) {
if (DataType.isStringType(value.getType())) {
return validate(enumerators, value.getString());
} else {
return validate(enumerators, value.getInt());
}
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论