提交 2a3118fd authored 作者: Noel Grandin's avatar Noel Grandin

Issue #569: ClassCastException when filtering on ENUM value in WHERE clause

required passing the Column down to Value#convertTo
Note that the test code in testscript.sql was pulled from maxenglander's
PR #572
上级 476dba18
...@@ -21,6 +21,8 @@ Change Log ...@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>Issue #569: ClassCastException when filtering on ENUM value in WHERE clause
</li>
<li>Issue #535: Allow explicit paths on Windows without drive letter <li>Issue #535: Allow explicit paths on Windows without drive letter
</li> </li>
<li>Issue #549: Removed UNION ALL requirements for CTE <li>Issue #549: Removed UNION ALL requirements for CTE
......
...@@ -165,34 +165,13 @@ public class ErrorCode { ...@@ -165,34 +165,13 @@ public class ErrorCode {
* but the value is not one of the values enumerated by the * but the value is not one of the values enumerated by the
* type. * type.
* *
* This error is best thrown in a context when the column name
* and it's enumerated values are known.
*
* Example: * Example:
* <pre> * <pre>
* CREATE TABLE TEST(CASE ENUM('sensitive','insensitive')); * CREATE TABLE TEST(CASE ENUM('sensitive','insensitive'));
* INSERT INTO TEST VALUES('snake'); * INSERT INTO TEST VALUES('snake');
* </pre> * </pre>
*/ */
public static final int ENUM_VALUE_NOT_PERMITTED_1 = 22030; public static final int ENUM_VALUE_NOT_PERMITTED = 22030;
/**
* The error with code <code>22031</code> is typically thrown
* when a math operation is attempted on an ENUM-typed cell,
* but the value resulting from the operation is not one of
* values enumerated by the type.
*
* This error is best thrown in a context when the column name
* is not known, but the enumerated values of the type are known.
*
* Example:
* <pre>
* CREATE TABLE TEST(CASE ENUM('sensitive','insensitive'));
* INSERT INTO TEST VALUES('sensitive');
* UPDATE TEST SET CASE = CASE + 100;
* </pre>
*/
public static final int ENUM_VALUE_NOT_PERMITTED_2 = 22031;
/** /**
* The error with code <code>22032</code> is thrown when an * The error with code <code>22032</code> is thrown when an
......
...@@ -203,7 +203,8 @@ public class Comparison extends Condition { ...@@ -203,7 +203,8 @@ public class Comparison extends Condition {
// once. // once.
if (constType != resType) { if (constType != resType) {
right = ValueExpression.get(r.convertTo(resType, right = ValueExpression.get(r.convertTo(resType,
MathUtils.convertLongToInt(left.getPrecision()), session.getDatabase().getMode())); MathUtils.convertLongToInt(left.getPrecision()),
session.getDatabase().getMode(), ((ExpressionColumn) left).getColumn()));
} }
} else if (right instanceof Parameter) { } else if (right instanceof Parameter) {
((Parameter) right).setColumn( ((Parameter) right).setColumn(
......
...@@ -189,7 +189,7 @@ public class ExpressionColumn extends Expression { ...@@ -189,7 +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) {
return ValueEnum.get(column.getEnumerators(), value); return ValueEnum.get(column.getEnumerators(), value.getInt());
} }
return value; return value;
} }
......
...@@ -177,13 +177,13 @@ public class Column { ...@@ -177,13 +177,13 @@ public class Column {
*/ */
public Value convert(Value v, Mode mode) { public Value convert(Value v, Mode mode) {
try { try {
return v.convertTo(type, MathUtils.convertLongToInt(precision), mode); return v.convertTo(type, MathUtils.convertLongToInt(precision), mode, this);
} catch (DbException e) { } catch (DbException e) {
if (e.getErrorCode() == ErrorCode.DATA_CONVERSION_ERROR_1) { if (e.getErrorCode() == ErrorCode.DATA_CONVERSION_ERROR_1) {
String target = (table == null ? "" : table.getName() + ": ") + String target = (table == null ? "" : table.getName() + ": ") +
getCreateSQL(); getCreateSQL();
throw DbException.get( throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, ErrorCode.DATA_CONVERSION_ERROR_1, e,
v.getSQL() + " (" + target + ")"); v.getSQL() + " (" + target + ")");
} }
throw e; throw e;
...@@ -389,11 +389,11 @@ public class Column { ...@@ -389,11 +389,11 @@ public class Column {
if (s.length() > 127) { if (s.length() > 127) {
s = s.substring(0, 128) + "..."; s = s.substring(0, 128) + "...";
} }
throw DbException.get(ErrorCode.ENUM_VALUE_NOT_PERMITTED_1, throw DbException.get(ErrorCode.ENUM_VALUE_NOT_PERMITTED,
getCreateSQL(), s); getCreateSQL(), s);
} }
value = ValueEnum.get(enumerators, value); value = ValueEnum.get(enumerators, value.getInt());
} }
updateSequenceIfRequired(session, value); updateSequenceIfRequired(session, value);
return value; return value;
......
...@@ -24,6 +24,7 @@ import org.h2.engine.Mode; ...@@ -24,6 +24,7 @@ import org.h2.engine.Mode;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.table.Column;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
...@@ -551,12 +552,26 @@ public abstract class Value { ...@@ -551,12 +552,26 @@ public abstract class Value {
* Compare a value to the specified type. * Compare a value to the specified type.
* *
* @param targetType the type of the returned value * @param targetType the type of the returned value
* @param the precision of the column to convert this value to. * @param precision the precision of the column to convert this value to.
* The special constant <code>-1</code> is used to indicate that * The special constant <code>-1</code> is used to indicate that
* the precision plays no role when converting the value * the precision plays no role when converting the value
* @return the converted value * @return the converted value
*/ */
public Value convertTo(int targetType, int precision, Mode mode) { public final Value convertTo(int targetType, int precision, Mode mode) {
return convertTo(targetType, precision, mode, null);
}
/**
* Compare a value to the specified type.
*
* @param targetType the type of the returned value
* @param precision the precision of the column to convert this value to.
* The special constant <code>-1</code> is used to indicate that
* the precision plays no role when converting the value
* @param column the column that contains the ENUM datatype enumerators, for dealing with ENUM conversions
* @return the converted value
*/
public Value convertTo(int targetType, int precision, Mode mode, Column column) {
// converting NULL is done in ValueNull // converting NULL is done in ValueNull
// converting BLOB to CLOB and vice versa is done in ValueLob // converting BLOB to CLOB and vice versa is done in ValueLob
if (getType() == targetType) { if (getType() == targetType) {
...@@ -582,6 +597,7 @@ public abstract class Value { ...@@ -582,6 +597,7 @@ public abstract class Value {
case BYTES: case BYTES:
case JAVA_OBJECT: case JAVA_OBJECT:
case UUID: case UUID:
case ENUM:
throw DbException.get( throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString()); ErrorCode.DATA_CONVERSION_ERROR_1, getString());
} }
...@@ -593,6 +609,7 @@ public abstract class Value { ...@@ -593,6 +609,7 @@ public abstract class Value {
return ValueByte.get(getBoolean().booleanValue() ? (byte) 1 : (byte) 0); return ValueByte.get(getBoolean().booleanValue() ? (byte) 1 : (byte) 0);
case SHORT: case SHORT:
return ValueByte.get(convertToByte(getShort())); return ValueByte.get(convertToByte(getShort()));
case ENUM:
case INT: case INT:
return ValueByte.get(convertToByte(getInt())); return ValueByte.get(convertToByte(getInt()));
case LONG: case LONG:
...@@ -617,6 +634,7 @@ public abstract class Value { ...@@ -617,6 +634,7 @@ public abstract class Value {
return ValueShort.get(getBoolean().booleanValue() ? (short) 1 : (short) 0); return ValueShort.get(getBoolean().booleanValue() ? (short) 1 : (short) 0);
case BYTE: case BYTE:
return ValueShort.get(getByte()); return ValueShort.get(getByte());
case ENUM:
case INT: case INT:
return ValueShort.get(convertToShort(getInt())); return ValueShort.get(convertToShort(getInt()));
case LONG: case LONG:
...@@ -669,6 +687,7 @@ public abstract class Value { ...@@ -669,6 +687,7 @@ public abstract class Value {
return ValueLong.get(getByte()); return ValueLong.get(getByte());
case SHORT: case SHORT:
return ValueLong.get(getShort()); return ValueLong.get(getShort());
case ENUM:
case INT: case INT:
return ValueLong.get(getInt()); return ValueLong.get(getInt());
case DECIMAL: case DECIMAL:
...@@ -700,6 +719,7 @@ public abstract class Value { ...@@ -700,6 +719,7 @@ public abstract class Value {
return ValueDecimal.get(BigDecimal.valueOf(getByte())); return ValueDecimal.get(BigDecimal.valueOf(getByte()));
case SHORT: case SHORT:
return ValueDecimal.get(BigDecimal.valueOf(getShort())); return ValueDecimal.get(BigDecimal.valueOf(getShort()));
case ENUM:
case INT: case INT:
return ValueDecimal.get(BigDecimal.valueOf(getInt())); return ValueDecimal.get(BigDecimal.valueOf(getInt()));
case LONG: case LONG:
...@@ -743,6 +763,7 @@ public abstract class Value { ...@@ -743,6 +763,7 @@ public abstract class Value {
return ValueDouble.get(getBigDecimal().doubleValue()); return ValueDouble.get(getBigDecimal().doubleValue());
case FLOAT: case FLOAT:
return ValueDouble.get(getFloat()); return ValueDouble.get(getFloat());
case ENUM:
case TIMESTAMP_TZ: case TIMESTAMP_TZ:
throw DbException.get( throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString()); ErrorCode.DATA_CONVERSION_ERROR_1, getString());
...@@ -765,6 +786,7 @@ public abstract class Value { ...@@ -765,6 +786,7 @@ public abstract class Value {
return ValueFloat.get(getBigDecimal().floatValue()); return ValueFloat.get(getBigDecimal().floatValue());
case DOUBLE: case DOUBLE:
return ValueFloat.get((float) getDouble()); return ValueFloat.get((float) getDouble());
case ENUM:
case TIMESTAMP_TZ: case TIMESTAMP_TZ:
throw DbException.get( throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString()); ErrorCode.DATA_CONVERSION_ERROR_1, getString());
...@@ -784,6 +806,9 @@ public abstract class Value { ...@@ -784,6 +806,9 @@ public abstract class Value {
case TIMESTAMP_TZ: case TIMESTAMP_TZ:
return ValueDate.fromDateValue( return ValueDate.fromDateValue(
((ValueTimestampTimeZone) this).getDateValue()); ((ValueTimestampTimeZone) this).getDateValue());
case ENUM:
throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString());
} }
break; break;
} }
...@@ -799,6 +824,9 @@ public abstract class Value { ...@@ -799,6 +824,9 @@ public abstract class Value {
case TIMESTAMP_TZ: case TIMESTAMP_TZ:
return ValueTime.fromNanos( return ValueTime.fromNanos(
((ValueTimestampTimeZone) this).getTimeNanos()); ((ValueTimestampTimeZone) this).getTimeNanos());
case ENUM:
throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString());
} }
break; break;
} }
...@@ -814,6 +842,9 @@ public abstract class Value { ...@@ -814,6 +842,9 @@ public abstract class Value {
return ValueTimestamp.fromDateValueAndNanos( return ValueTimestamp.fromDateValueAndNanos(
((ValueTimestampTimeZone) this).getDateValue(), ((ValueTimestampTimeZone) this).getDateValue(),
((ValueTimestampTimeZone) this).getTimeNanos()); ((ValueTimestampTimeZone) this).getTimeNanos());
case ENUM:
throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString());
} }
break; break;
} }
...@@ -856,6 +887,7 @@ public abstract class Value { ...@@ -856,6 +887,7 @@ public abstract class Value {
(byte) x (byte) x
}); });
} }
case ENUM:
case TIMESTAMP_TZ: case TIMESTAMP_TZ:
throw DbException.get( throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString()); ErrorCode.DATA_CONVERSION_ERROR_1, getString());
...@@ -868,6 +900,7 @@ public abstract class Value { ...@@ -868,6 +900,7 @@ public abstract class Value {
case BLOB: case BLOB:
return ValueJavaObject.getNoCopy( return ValueJavaObject.getNoCopy(
null, getBytesNoCopy(), getDataHandler()); null, getBytesNoCopy(), getDataHandler());
case ENUM:
case TIMESTAMP_TZ: case TIMESTAMP_TZ:
throw DbException.get( throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString()); ErrorCode.DATA_CONVERSION_ERROR_1, getString());
...@@ -876,9 +909,19 @@ public abstract class Value { ...@@ -876,9 +909,19 @@ public abstract class Value {
} }
case ENUM: { case ENUM: {
switch (getType()) { switch (getType()) {
case BYTE:
case SHORT:
case INT: case INT:
case LONG:
case DECIMAL:
return ValueEnum.get(column.getEnumerators(), getInt());
case STRING: case STRING:
return this; case STRING_IGNORECASE:
case STRING_FIXED:
return ValueEnum.get(column.getEnumerators(), getString());
default:
throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString());
} }
} }
case BLOB: { case BLOB: {
...@@ -972,7 +1015,6 @@ public abstract class Value { ...@@ -972,7 +1015,6 @@ public abstract class Value {
case JAVA_OBJECT: case JAVA_OBJECT:
return ValueJavaObject.getNoCopy(null, return ValueJavaObject.getNoCopy(null,
StringUtils.convertHexToBytes(s.trim()), getDataHandler()); StringUtils.convertHexToBytes(s.trim()), getDataHandler());
case ENUM:
case STRING: case STRING:
return ValueString.get(s); return ValueString.get(s);
case STRING_IGNORECASE: case STRING_IGNORECASE:
......
...@@ -49,19 +49,15 @@ public class ValueEnum extends ValueEnumBase { ...@@ -49,19 +49,15 @@ public class ValueEnum extends ValueEnumBase {
private static final void check(final String[] enumerators, final Value value) { private static final void check(final String[] enumerators, final Value value) {
check(enumerators); check(enumerators);
switch (validate(enumerators, value)) { if (validate(enumerators, value) != Validation.VALID) {
case VALID: throw DbException.get(ErrorCode.ENUM_VALUE_NOT_PERMITTED,
return; toString(enumerators), value.toString());
default:
throw DbException.get(ErrorCode.ENUM_VALUE_NOT_PERMITTED_2,
toString(enumerators), value.toString());
} }
} }
@Override @Override
protected int compareSecure(final Value v, final CompareMode mode) { protected int compareSecure(final Value v, final CompareMode mode) {
final ValueEnum ev = ValueEnum.get(enumerators, v); return MathUtils.compareInt(getInt(), v.getInt());
return MathUtils.compareInt(getInt(), ev.getInt());
} }
/** /**
...@@ -72,21 +68,22 @@ public class ValueEnum extends ValueEnumBase { ...@@ -72,21 +68,22 @@ public class ValueEnum extends ValueEnumBase {
* @param value a value * @param value a value
* @return the ENUM value * @return the ENUM value
*/ */
public static ValueEnum get(final String[] enumerators, final Value value) { public static ValueEnum get(final String[] enumerators, int value) {
check(enumerators, value); check(enumerators, ValueInt.get(value));
return new ValueEnum(enumerators, value);
}
if (DataType.isStringType(value.getType())) { public static ValueEnum get(final String[] enumerators, String value) {
final String cleanLabel = sanitize(value.getString()); check(enumerators, ValueString.get(value));
for (int i = 0; i < enumerators.length; i++) { final String cleanLabel = sanitize(value);
if (cleanLabel.equals(sanitize(enumerators[i])))
return new ValueEnum(enumerators, i);
}
throw DbException.get(ErrorCode.GENERAL_ERROR_1, "Unexpected error"); for (int i = 0; i < enumerators.length; i++) {
} else { if (cleanLabel.equals(sanitize(enumerators[i])))
return new ValueEnum(enumerators, value.getInt()); return new ValueEnum(enumerators, i);
} }
throw DbException.get(ErrorCode.GENERAL_ERROR_1, "Unexpected error");
} }
public String[] getEnumerators() { public String[] getEnumerators() {
......
...@@ -8,17 +8,16 @@ package org.h2.value; ...@@ -8,17 +8,16 @@ package org.h2.value;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.CoordinateSequenceFilter;
import com.vividsolutions.jts.geom.PrecisionModel;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.table.Column;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.CoordinateSequenceFilter;
import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKBReader; import com.vividsolutions.jts.io.WKBReader;
import com.vividsolutions.jts.io.WKBWriter; import com.vividsolutions.jts.io.WKBWriter;
...@@ -274,11 +273,11 @@ public class ValueGeometry extends Value { ...@@ -274,11 +273,11 @@ public class ValueGeometry extends Value {
} }
@Override @Override
public Value convertTo(int targetType, int precision, Mode mode) { public Value convertTo(int targetType, int precision, Mode mode, Column column) {
if (targetType == Value.JAVA_OBJECT) { if (targetType == Value.JAVA_OBJECT) {
return this; return this;
} }
return super.convertTo(targetType, precision, mode); return super.convertTo(targetType, precision, mode, column);
} }
/** /**
......
...@@ -23,6 +23,7 @@ import org.h2.store.FileStore; ...@@ -23,6 +23,7 @@ import org.h2.store.FileStore;
import org.h2.store.FileStoreInputStream; import org.h2.store.FileStoreInputStream;
import org.h2.store.FileStoreOutputStream; import org.h2.store.FileStoreOutputStream;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.table.Column;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -444,7 +445,7 @@ public class ValueLob extends Value { ...@@ -444,7 +445,7 @@ public class ValueLob extends Value {
* @return the converted value * @return the converted value
*/ */
@Override @Override
public Value convertTo(int t, int precision, Mode mode) { public Value convertTo(int t, int precision, Mode mode, Column column) {
if (t == type) { if (t == type) {
return this; return this;
} else if (t == Value.CLOB) { } else if (t == Value.CLOB) {
...@@ -454,7 +455,7 @@ public class ValueLob extends Value { ...@@ -454,7 +455,7 @@ public class ValueLob extends Value {
ValueLob copy = ValueLob.createBlob(getInputStream(), -1, handler); ValueLob copy = ValueLob.createBlob(getInputStream(), -1, handler);
return copy; return copy;
} }
return super.convertTo(t, precision, mode); return super.convertTo(t, precision, mode, column);
} }
@Override @Override
......
...@@ -25,6 +25,7 @@ import org.h2.store.FileStoreOutputStream; ...@@ -25,6 +25,7 @@ import org.h2.store.FileStoreOutputStream;
import org.h2.store.LobStorageFrontend; import org.h2.store.LobStorageFrontend;
import org.h2.store.LobStorageInterface; import org.h2.store.LobStorageInterface;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.table.Column;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -185,7 +186,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, ...@@ -185,7 +186,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
* @return the converted value * @return the converted value
*/ */
@Override @Override
public Value convertTo(int t, int precision, Mode mode) { public Value convertTo(int t, int precision, Mode mode, Column column) {
if (t == type) { if (t == type) {
return this; return this;
} else if (t == Value.CLOB) { } else if (t == Value.CLOB) {
...@@ -205,7 +206,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, ...@@ -205,7 +206,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return ValueLobDb.createSmallLob(t, small); return ValueLobDb.createSmallLob(t, small);
} }
} }
return super.convertTo(t, precision, mode); return super.convertTo(t, precision, mode, column);
} }
@Override @Override
......
...@@ -13,9 +13,9 @@ import java.sql.PreparedStatement; ...@@ -13,9 +13,9 @@ import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.table.Column;
/** /**
* Implementation of NULL. NULL is not a regular data type. * Implementation of NULL. NULL is not a regular data type.
...@@ -133,7 +133,7 @@ public class ValueNull extends Value { ...@@ -133,7 +133,7 @@ public class ValueNull extends Value {
} }
@Override @Override
public Value convertTo(int type, int precision, Mode mode) { public Value convertTo(int type, int precision, Mode mode, Column column) {
return this; return this;
} }
......
...@@ -454,7 +454,7 @@ public class TestPreparedStatement extends TestBase { ...@@ -454,7 +454,7 @@ public class TestPreparedStatement extends TestBase {
PreparedStatement prep = conn.prepareStatement( PreparedStatement prep = conn.prepareStatement(
"INSERT INTO test_enum VALUES(?)"); "INSERT INTO test_enum VALUES(?)");
prep.setObject(1, badSizes[i]); prep.setObject(1, badSizes[i]);
assertThrows(ErrorCode.ENUM_VALUE_NOT_PERMITTED_1, prep).execute(); assertThrows(ErrorCode.ENUM_VALUE_NOT_PERMITTED, prep).execute();
} }
String[] goodSizes = new String[]{"small", "medium", "large"}; String[] goodSizes = new String[]{"small", "medium", "large"};
......
...@@ -10683,4 +10683,59 @@ drop table card; ...@@ -10683,4 +10683,59 @@ drop table card;
> ok > ok
drop type CARD_SUIT; drop type CARD_SUIT;
> ok > ok
\ No newline at end of file
--- ENUM in primary key with another column
create type CARD_SUIT as enum('hearts', 'clubs', 'spades', 'diamonds');
> ok
create table card (rank int, suit CARD_SUIT, primary key(rank, suit));
> ok
insert into card (rank, suit) values (0, 'clubs'), (3, 'hearts'), (1, 'clubs');
> update count: 3
insert into card (rank, suit) values (0, 'clubs');
> exception
select rank from card where suit = 'clubs';
> RANK
> ----
> 0
> 1
drop table card;
> ok
drop type CARD_SUIT;
> ok
--- ENUM with index
create type CARD_SUIT as enum('hearts', 'clubs', 'spades', 'diamonds');
> ok
create table card (rank int, suit CARD_SUIT, primary key(rank, suit));
> ok
insert into card (rank, suit) values (0, 'clubs'), (3, 'hearts'), (1, 'clubs');
> update count: 3
create index idx_card_suite on card(`suit`);
select rank from card where suit = 'clubs';
> RANK
> ----
> 0
> 1
select rank from card where suit in ('clubs');
> RANK
> ----
> 0
> 1
drop table card;
> ok
drop type CARD_SUIT;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论