Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
fc102859
提交
fc102859
authored
3月 30, 2017
作者:
Noel Grandin
提交者:
GitHub
3月 30, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #451 from maxenglander/enum-support
Enum support
上级
f087d461
02176ff1
隐藏空白字符变更
内嵌
并排
正在显示
20 个修改的文件
包含
684 行增加
和
28 行删除
+684
-28
help.csv
h2/src/docsrc/help/help.csv
+15
-1
changelog.html
h2/src/docsrc/html/changelog.html
+2
-0
_messages_en.prop
h2/src/docsrc/textbase/_messages_en.prop
+4
-0
ErrorCode.java
h2/src/main/org/h2/api/ErrorCode.java
+59
-0
Parser.java
h2/src/main/org/h2/command/Parser.java
+27
-1
CreateTable.java
h2/src/main/org/h2/command/ddl/CreateTable.java
+13
-1
ExpressionColumn.java
h2/src/main/org/h2/expression/ExpressionColumn.java
+4
-0
ValueDataType.java
h2/src/main/org/h2/mvstore/db/ValueDataType.java
+1
-0
_messages_en.prop
h2/src/main/org/h2/res/_messages_en.prop
+4
-0
_messages_es.prop
h2/src/main/org/h2/res/_messages_es.prop
+1
-0
help.csv
h2/src/main/org/h2/res/help.csv
+5
-1
Column.java
h2/src/main/org/h2/table/Column.java
+50
-2
DataType.java
h2/src/main/org/h2/value/DataType.java
+24
-0
Transfer.java
h2/src/main/org/h2/value/Transfer.java
+10
-0
Value.java
h2/src/main/org/h2/value/Value.java
+18
-1
ValueEnum.java
h2/src/main/org/h2/value/ValueEnum.java
+183
-0
ValueEnumBase.java
h2/src/main/org/h2/value/ValueEnumBase.java
+139
-0
TestPreparedStatement.java
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
+32
-0
testScript.sql
h2/src/test/org/h2/test/testScript.sql
+73
-1
dictionary.txt
h2/src/tools/org/h2/build/doc/dictionary.txt
+20
-20
没有找到文件。
h2/src/docsrc/help/help.csv
浏览文件 @
fc102859
...
...
@@ -1939,7 +1939,7 @@ CALL CSVWRITE('test2.csv', 'SELECT * FROM TEST', 'charset=UTF-8 fieldSeparator=|
intType | booleanType | tinyintType | smallintType | bigintType | identityType
| decimalType | doubleType | realType | dateType | timeType | timestampType
| binaryType | otherType | varcharType | varcharIgnorecaseType | charType
| blobType | clobType | uuidType | arrayType
| blobType | clobType | uuidType | arrayType
| enumType
","
A data type definition.
","
...
...
@@ -2527,6 +2527,20 @@ and ""ResultSet.getObject(..)"" or ""ResultSet.getArray(..)"" to retrieve the va
ARRAY
"
"Data Types","ENUM Type","
{ ENUM (string [, ... ]) }
","
A type with enumerated values.
Mapped to ""java.lang.Integer"".
The first provided value is mapped to 0, the
second mapped to 1, and so on.
Duplicate and empty values are not permitted.
","
ENUM('clubs', 'diamonds', 'hearts', 'spades')
"
"Data Types","GEOMETRY Type","
GEOMETRY
","
...
...
h2/src/docsrc/html/changelog.html
浏览文件 @
fc102859
...
...
@@ -25,6 +25,8 @@ Change Log
</li>
<li>
Added support for invisible columns.
</li>
<li>
Added an ENUM data type, with syntax similar to that of MySQL and Oracle.
</li>
</ul>
<h2>
Version 1.4.194 (2017-03-10)
</h2>
...
...
h2/src/docsrc/textbase/_messages_en.prop
浏览文件 @
fc102859
...
...
@@ -9,6 +9,10 @@
22012=Division by zero: {0}
22018=Data conversion error converting {0}
22025=Error in LIKE ESCAPE: {0}
22030=Value not permitted for column {0}: {1}
22031=Value not a member of enumerators {0}: {1}
22032=Empty enums are not allowed
22033=Duplicate enumerators are not allowed for enum types: {0}
23502=NULL not allowed for column {0}
23503=Referential integrity constraint violation: {0}
23505=Unique index or primary key violation: {0}
...
...
h2/src/main/org/h2/api/ErrorCode.java
浏览文件 @
fc102859
...
...
@@ -159,6 +159,65 @@ public class ErrorCode {
*/
public
static
final
int
LIKE_ESCAPE_ERROR_1
=
22025
;
/**
* The error with code <code>22030</code> is thrown when
* an attempt is made to INSERT or UPDATE an ENUM-typed cell,
* but the value is not one of the values enumerated by the
* type.
*
* This error is best thrown in a context when the column name
* and it's enumerated values are known.
*
* Example:
* <pre>
* CREATE TABLE TEST(CASE ENUM('sensitive','insensitive'));
* INSERT INTO TEST VALUES('snake');
* </pre>
*/
public
static
final
int
ENUM_VALUE_NOT_PERMITTED_1
=
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
* attempt is made to add or modify an ENUM-typed column so
* that one or more of its enumerators would be empty.
*
* Example:
* <pre>
* CREATE TABLE TEST(CASE ENUM(' '));
* </pre>
*/
public
static
final
int
ENUM_EMPTY
=
22032
;
/**
* The error with code <code>22033</code> is thrown when an
* attempt is made to add or modify an ENUM-typed column so
* that it would have duplicate values.
*
* Example:
* <pre>
* CREATE TABLE TEST(CASE ENUM('sensitive', 'sensitive'));
* </pre>
*/
public
static
final
int
ENUM_DUPLICATE
=
22033
;
// 23: constraint violation
/**
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
fc102859
...
...
@@ -146,6 +146,7 @@ import org.h2.value.ValueBoolean;
import
org.h2.value.ValueBytes
;
import
org.h2.value.ValueDate
;
import
org.h2.value.ValueDecimal
;
import
org.h2.value.ValueEnum
;
import
org.h2.value.ValueInt
;
import
org.h2.value.ValueLong
;
import
org.h2.value.ValueNull
;
...
...
@@ -4127,6 +4128,7 @@ public class Parser {
}
long
precision
=
-
1
;
int
displaySize
=
-
1
;
String
[]
enumerators
=
null
;
int
scale
=
-
1
;
String
comment
=
null
;
Column
templateColumn
=
null
;
...
...
@@ -4200,6 +4202,28 @@ public class Parser {
}
read
(
")"
);
}
}
else
if
(
dataType
.
enumerated
)
{
if
(
readIf
(
"("
))
{
java
.
util
.
List
<
String
>
enumeratorList
=
new
ArrayList
<
String
>();
original
+=
'('
;
String
enumerator0
=
readString
();
enumeratorList
.
add
(
enumerator0
);
original
+=
"'"
+
enumerator0
+
"'"
;
while
(
readIf
(
","
))
{
original
+=
','
;
String
enumeratorN
=
readString
();
original
+=
"'"
+
enumeratorN
+
"'"
;
enumeratorList
.
add
(
enumeratorN
);
}
read
(
")"
);
original
+=
')'
;
enumerators
=
enumeratorList
.
toArray
(
new
String
[
enumeratorList
.
size
()]);
}
try
{
ValueEnum
.
check
(
enumerators
);
}
catch
(
DbException
e
)
{
throw
e
.
addSQL
(
original
);
}
}
else
if
(
readIf
(
"("
))
{
// Support for MySQL: INT(11), MEDIUMINT(8) and so on.
// Just ignore the precision.
...
...
@@ -4220,8 +4244,10 @@ public class Parser {
throw
DbException
.
get
(
ErrorCode
.
INVALID_VALUE_SCALE_PRECISION
,
Integer
.
toString
(
scale
),
Long
.
toString
(
precision
));
}
Column
column
=
new
Column
(
columnName
,
type
,
precision
,
scale
,
displaySize
);
displaySize
,
enumerators
);
if
(
templateColumn
!=
null
)
{
column
.
setNullable
(
templateColumn
.
isNullable
());
column
.
setDefaultExpression
(
session
,
...
...
h2/src/main/org/h2/command/ddl/CreateTable.java
浏览文件 @
fc102859
...
...
@@ -16,6 +16,7 @@ import org.h2.engine.Database;
import
org.h2.engine.DbObject
;
import
org.h2.engine.Session
;
import
org.h2.expression.Expression
;
import
org.h2.expression.ExpressionColumn
;
import
org.h2.message.DbException
;
import
org.h2.schema.Schema
;
import
org.h2.schema.Sequence
;
...
...
@@ -248,7 +249,18 @@ public class CreateTable extends SchemaCommand {
if
(
scale
>
precision
)
{
precision
=
scale
;
}
Column
col
=
new
Column
(
name
,
type
,
precision
,
scale
,
displaySize
);
String
[]
enumerators
=
null
;
if
(
dt
.
enumerated
)
{
/**
* Only columns of tables may be enumerated.
*/
if
(!(
expr
instanceof
ExpressionColumn
))
{
throw
DbException
.
get
(
ErrorCode
.
GENERAL_ERROR_1
,
"Unable to resolve enumerators of expression"
);
}
enumerators
=
((
ExpressionColumn
)
expr
).
getColumn
().
getEnumerators
();
}
Column
col
=
new
Column
(
name
,
type
,
precision
,
scale
,
displaySize
,
enumerators
);
addColumn
(
col
);
}
}
...
...
h2/src/main/org/h2/expression/ExpressionColumn.java
浏览文件 @
fc102859
...
...
@@ -22,6 +22,7 @@ import org.h2.table.Table;
import
org.h2.table.TableFilter
;
import
org.h2.value.Value
;
import
org.h2.value.ValueBoolean
;
import
org.h2.value.ValueEnum
;
/**
* A expression that represents a column of a table or view.
...
...
@@ -187,6 +188,9 @@ public class ExpressionColumn extends Expression {
columnResolver
.
getValue
(
column
);
throw
DbException
.
get
(
ErrorCode
.
MUST_GROUP_BY_COLUMN_1
,
getSQL
());
}
if
(
column
.
getEnumerators
()
!=
null
)
{
return
ValueEnum
.
get
(
column
.
getEnumerators
(),
value
);
}
return
value
;
}
...
...
h2/src/main/org/h2/mvstore/db/ValueDataType.java
浏览文件 @
fc102859
...
...
@@ -201,6 +201,7 @@ public class ValueDataType implements DataType {
case
Value
.
SHORT
:
buff
.
put
((
byte
)
type
).
putShort
(
v
.
getShort
());
break
;
case
Value
.
ENUM
:
case
Value
.
INT
:
{
int
x
=
v
.
getInt
();
if
(
x
<
0
)
{
...
...
h2/src/main/org/h2/res/_messages_en.prop
浏览文件 @
fc102859
...
...
@@ -9,6 +9,10 @@
22012=Division by zero: {0}
22018=Data conversion error converting {0}
22025=Error in LIKE ESCAPE: {0}
22030=Value not permitted for column {0}: {1}
22031=Value not a member of enumerators {0}: {1}
22032=Empty enums are not allowed
22033=Duplicate enumerators are not allowed for enum types: {0}
23502=NULL not allowed for column {0}
23503=Referential integrity constraint violation: {0}
23505=Unique index or primary key violation: {0}
...
...
h2/src/main/org/h2/res/_messages_es.prop
浏览文件 @
fc102859
...
...
@@ -9,6 +9,7 @@
22012=División por cero: {0}
22018=Conversión de datos fallida, convirtiendo {0}
22025=Error en LIKE ESCAPE: {0}
22030=Valor no permitido para la columna {0}: {1}
23502=La columna {0} no permite valores nulos (NULL)
23503=Violación de una restricción de Integridad Referencial: {0}
23505=Violación de indice de Unicidad ó Clave primaria: {0}
...
...
h2/src/main/org/h2/res/help.csv
浏览文件 @
fc102859
...
...
@@ -606,7 +606,7 @@ Optional parameters for CSVREAD and CSVWRITE."
intType | booleanType | tinyintType | smallintType | bigintType | identityType
| decimalType | doubleType | realType | dateType | timeType | timestampType
| binaryType | otherType | varcharType | varcharIgnorecaseType | charType
| blobType | clobType | uuidType | arrayType
| blobType | clobType | uuidType | arrayType
| enumType
","
A data type definition."
"Other Grammar","Date","
...
...
@@ -834,6 +834,10 @@ Universally unique identifier."
ARRAY
","
An array of values."
"Data Types","ENUM Type","
{ ENUM (string [, ... ]) }
","
A type with enumerated values."
"Data Types","GEOMETRY Type","
GEOMETRY
","
...
...
h2/src/main/org/h2/table/Column.java
浏览文件 @
fc102859
...
...
@@ -6,6 +6,7 @@
package
org
.
h2
.
table
;
import
java.sql.ResultSetMetaData
;
import
java.util.Arrays
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.Parser
;
import
org.h2.engine.Constants
;
...
...
@@ -26,6 +27,7 @@ import org.h2.util.StringUtils;
import
org.h2.value.DataType
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDate
;
import
org.h2.value.ValueEnum
;
import
org.h2.value.ValueInt
;
import
org.h2.value.ValueLong
;
import
org.h2.value.ValueNull
;
...
...
@@ -66,6 +68,7 @@ public class Column {
private
final
int
type
;
private
long
precision
;
private
int
scale
;
private
String
[]
enumerators
;
private
int
displaySize
;
private
Table
table
;
private
String
name
;
...
...
@@ -89,11 +92,20 @@ public class Column {
private
boolean
visible
=
true
;
public
Column
(
String
name
,
int
type
)
{
this
(
name
,
type
,
-
1
,
-
1
,
-
1
);
this
(
name
,
type
,
-
1
,
-
1
,
-
1
,
null
);
}
public
Column
(
String
name
,
int
type
,
String
[]
enumerators
)
{
this
(
name
,
type
,
-
1
,
-
1
,
-
1
,
enumerators
);
}
public
Column
(
String
name
,
int
type
,
long
precision
,
int
scale
,
int
displaySize
)
{
this
(
name
,
type
,
precision
,
scale
,
displaySize
,
null
);
}
public
Column
(
String
name
,
int
type
,
long
precision
,
int
scale
,
int
displaySize
,
String
[]
enumerators
)
{
this
.
name
=
name
;
this
.
type
=
type
;
if
(
precision
==
-
1
&&
scale
==
-
1
&&
displaySize
==
-
1
&&
type
!=
Value
.
UNKNOWN
)
{
...
...
@@ -105,6 +117,7 @@ public class Column {
this
.
precision
=
precision
;
this
.
scale
=
scale
;
this
.
displaySize
=
displaySize
;
this
.
enumerators
=
enumerators
;
}
@Override
...
...
@@ -133,8 +146,12 @@ public class Column {
return
table
.
getId
()
^
name
.
hashCode
();
}
public
boolean
isEnumerated
()
{
return
type
==
Value
.
ENUM
;
}
public
Column
getClone
()
{
Column
newColumn
=
new
Column
(
name
,
type
,
precision
,
scale
,
displaySize
);
Column
newColumn
=
new
Column
(
name
,
type
,
precision
,
scale
,
displaySize
,
enumerators
);
newColumn
.
copy
(
this
);
return
newColumn
;
}
...
...
@@ -258,6 +275,14 @@ public class Column {
nullable
=
b
;
}
public
String
[]
getEnumerators
()
{
return
enumerators
;
}
public
void
setEnumerators
(
String
[]
enumerators
)
{
this
.
enumerators
=
enumerators
;
}
public
boolean
getVisible
()
{
return
visible
;
}
...
...
@@ -345,6 +370,18 @@ public class Column {
getCreateSQL
(),
s
+
" ("
+
value
.
getPrecision
()
+
")"
);
}
}
if
(
isEnumerated
())
{
if
(!
ValueEnum
.
isValid
(
enumerators
,
value
))
{
String
s
=
value
.
getTraceSQL
();
if
(
s
.
length
()
>
127
)
{
s
=
s
.
substring
(
0
,
128
)
+
"..."
;
}
throw
DbException
.
get
(
ErrorCode
.
ENUM_VALUE_NOT_PERMITTED_1
,
getCreateSQL
(),
s
);
}
value
=
ValueEnum
.
get
(
enumerators
,
value
);
}
updateSequenceIfRequired
(
session
,
value
);
return
value
;
}
...
...
@@ -434,6 +471,15 @@ public class Column {
case
Value
.
DECIMAL
:
buff
.
append
(
'('
).
append
(
precision
).
append
(
", "
).
append
(
scale
).
append
(
')'
);
break
;
case
Value
.
ENUM
:
buff
.
append
(
'('
);
for
(
int
i
=
0
;
i
<
enumerators
.
length
;
i
++)
{
buff
.
append
(
'\''
).
append
(
enumerators
[
i
]).
append
(
'\''
);
if
(
i
<
enumerators
.
length
-
1
)
{
buff
.
append
(
','
);
}
}
buff
.
append
(
')'
);
case
Value
.
BYTES
:
case
Value
.
STRING
:
case
Value
.
STRING_IGNORECASE
:
...
...
@@ -748,6 +794,8 @@ public class Column {
displaySize
=
source
.
displaySize
;
name
=
source
.
name
;
precision
=
source
.
precision
;
enumerators
=
source
.
enumerators
==
null
?
null
:
Arrays
.
copyOf
(
source
.
enumerators
,
source
.
enumerators
.
length
);
scale
=
source
.
scale
;
// table is not set
// columnId is not set
...
...
h2/src/main/org/h2/value/DataType.java
浏览文件 @
fc102859
...
...
@@ -140,6 +140,11 @@ public class DataType {
*/
public
boolean
caseSensitive
;
/**
* If enumerated values are supported.
*/
public
boolean
enumerated
;
/**
* If the precision parameter is supported.
*/
...
...
@@ -385,6 +390,11 @@ public class DataType {
new
String
[]{
"RESULT_SET"
},
400
);
add
(
Value
.
ENUM
,
Types
.
OTHER
,
"Enum"
,
createEnum
(),
new
String
[]{
"ENUM"
},
48
);
for
(
Integer
i
:
TYPES_BY_VALUE_TYPE
.
keySet
())
{
Value
.
getOrder
(
i
);
}
...
...
@@ -406,6 +416,7 @@ public class DataType {
dt
.
params
=
dataType
.
params
;
dt
.
prefix
=
dataType
.
prefix
;
dt
.
suffix
=
dataType
.
suffix
;
dt
.
enumerated
=
dataType
.
enumerated
;
dt
.
supportsPrecision
=
dataType
.
supportsPrecision
;
dt
.
supportsScale
=
dataType
.
supportsScale
;
dt
.
defaultPrecision
=
dataType
.
defaultPrecision
;
...
...
@@ -459,6 +470,13 @@ public class DataType {
return
dataType
;
}
private
static
DataType
createEnum
()
{
DataType
dataType
=
createString
(
false
);
dataType
.
enumerated
=
true
;
dataType
.
supportsPrecision
=
false
;
dataType
.
supportsScale
=
false
;
return
dataType
;
}
private
static
DataType
createString
(
boolean
caseSensitive
)
{
DataType
dataType
=
new
DataType
();
dataType
.
prefix
=
"'"
;
...
...
@@ -667,6 +685,12 @@ public class DataType {
v
=
ValueArray
.
get
(
values
);
break
;
}
case
Value
.
ENUM
:
{
int
value
=
rs
.
getInt
(
columnIndex
);
v
=
rs
.
wasNull
()
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueInt
.
get
(
value
);
break
;
}
case
Value
.
RESULT_SET
:
{
ResultSet
x
=
(
ResultSet
)
rs
.
getObject
(
columnIndex
);
if
(
x
==
null
)
{
...
...
h2/src/main/org/h2/value/Transfer.java
浏览文件 @
fc102859
...
...
@@ -494,6 +494,11 @@ public class Transfer {
}
break
;
}
case
Value
.
ENUM
:
{
writeInt
(
v
.
getInt
());
writeString
(
v
.
getString
());
break
;
}
case
Value
.
RESULT_SET
:
{
try
{
ResultSet
rs
=
((
ValueResultSet
)
v
).
getResultSet
();
...
...
@@ -594,6 +599,11 @@ public class Transfer {
return
ValueDouble
.
get
(
readDouble
());
case
Value
.
FLOAT
:
return
ValueFloat
.
get
(
readFloat
());
case
Value
.
ENUM
:
{
final
int
ordinal
=
readInt
();
final
String
label
=
readString
();
return
ValueEnumBase
.
get
(
label
,
ordinal
);
}
case
Value
.
INT
:
return
ValueInt
.
get
(
readInt
());
case
Value
.
LONG
:
...
...
h2/src/main/org/h2/value/Value.java
浏览文件 @
fc102859
...
...
@@ -168,10 +168,15 @@ public abstract class Value {
*/
public
static
final
int
TIMESTAMP_TZ
=
24
;
/**
* The value type for ENUM values.
*/
public
static
final
int
ENUM
=
25
;
/**
* The number of value types.
*/
public
static
final
int
TYPE_COUNT
=
TIMESTAMP_TZ
;
public
static
final
int
TYPE_COUNT
=
ENUM
;
private
static
SoftReference
<
Value
[]>
softCache
=
new
SoftReference
<
Value
[]>(
null
);
...
...
@@ -323,6 +328,8 @@ public abstract class Value {
return
50_000
;
case
RESULT_SET:
return
51_000
;
case
ENUM:
return
52_000
;
default
:
if
(
JdbcUtils
.
customDataTypesHandler
!=
null
)
{
return
JdbcUtils
.
customDataTypesHandler
.
getDataTypeOrder
(
type
);
...
...
@@ -618,6 +625,8 @@ public abstract class Value {
return
ValueInt
.
get
(
getBoolean
().
booleanValue
()
?
1
:
0
);
case
BYTE:
return
ValueInt
.
get
(
getByte
());
case
ENUM:
return
ValueInt
.
get
(
getInt
());
case
SHORT:
return
ValueInt
.
get
(
getShort
());
case
LONG:
...
...
@@ -849,6 +858,13 @@ public abstract class Value {
}
break
;
}
case
ENUM:
{
switch
(
getType
())
{
case
INT:
case
STRING:
return
this
;
}
}
case
BLOB:
{
switch
(
getType
())
{
case
BYTES:
...
...
@@ -940,6 +956,7 @@ public abstract class Value {
case
JAVA_OBJECT:
return
ValueJavaObject
.
getNoCopy
(
null
,
StringUtils
.
convertHexToBytes
(
s
.
trim
()),
getDataHandler
());
case
ENUM:
case
STRING:
return
ValueString
.
get
(
s
);
case
STRING_IGNORECASE:
...
...
h2/src/main/org/h2/value/ValueEnum.java
0 → 100644
浏览文件 @
fc102859
package
org
.
h2
.
value
;
import
java.util.Locale
;
import
org.h2.api.ErrorCode
;
import
org.h2.message.DbException
;
import
org.h2.util.MathUtils
;
import
org.h2.value.DataType
;
public
class
ValueEnum
extends
ValueEnumBase
{
private
static
enum
Validation
{
DUPLICATE
,
EMPTY
,
INVALID
,
VALID
}
private
final
String
[]
enumerators
;
private
ValueEnum
(
final
String
[]
enumerators
,
final
int
ordinal
)
{
super
(
enumerators
[
ordinal
],
ordinal
);
this
.
enumerators
=
enumerators
;
}
/**
* Check for any violations, such as empty
* values, duplicate values.
*
* @param enumerators the enumerators
*/
public
static
final
void
check
(
final
String
[]
enumerators
)
{
switch
(
validate
(
enumerators
))
{
case
VALID:
return
;
case
EMPTY:
throw
DbException
.
get
(
ErrorCode
.
ENUM_EMPTY
);
case
DUPLICATE:
throw
DbException
.
get
(
ErrorCode
.
ENUM_DUPLICATE
,
toString
(
enumerators
));
default
:
throw
DbException
.
get
(
ErrorCode
.
INVALID_VALUE_2
,
toString
(
enumerators
));
}
}
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
.
ENUM_VALUE_NOT_PERMITTED_2
,
toString
(
enumerators
),
value
.
toString
());
}
}
@Override
protected
int
compareSecure
(
final
Value
v
,
final
CompareMode
mode
)
{
final
ValueEnum
ev
=
ValueEnum
.
get
(
enumerators
,
v
);
return
MathUtils
.
compareInt
(
getInt
(),
ev
.
getInt
());
}
/**
* Create an ENUM value from the provided enumerators
* and value.
*
* @param enumerators the enumerators
* @param value a value
* @return the ENUM value
*/
public
static
ValueEnum
get
(
final
String
[]
enumerators
,
final
Value
value
)
{
check
(
enumerators
,
value
);
if
(
DataType
.
isStringType
(
value
.
getType
()))
{
final
String
cleanLabel
=
sanitize
(
value
.
getString
());
for
(
int
i
=
0
;
i
<
enumerators
.
length
;
i
++)
{
if
(
cleanLabel
.
equals
(
sanitize
(
enumerators
[
i
])))
return
new
ValueEnum
(
enumerators
,
i
);
}
throw
DbException
.
get
(
ErrorCode
.
GENERAL_ERROR_1
,
"Unexpected error"
);
}
else
{
return
new
ValueEnum
(
enumerators
,
value
.
getInt
());
}
}
public
String
[]
getEnumerators
()
{
return
enumerators
;
}
/**
* Evaluates whether a valid ENUM can be constructed
* from the provided enumerators and value.
*
* @param enumerators the enumerators
* @param value the value
* @return whether a valid ENUM can be constructed from the provided values
*/
public
static
boolean
isValid
(
final
String
enumerators
[],
final
Value
value
)
{
return
validate
(
enumerators
,
value
).
equals
(
Validation
.
VALID
);
}
private
static
String
sanitize
(
final
String
label
)
{
return
label
==
null
?
null
:
label
.
trim
().
toUpperCase
(
Locale
.
ENGLISH
);
}
private
static
String
[]
sanitize
(
final
String
[]
enumerators
)
{
if
(
enumerators
==
null
||
enumerators
.
length
==
0
)
return
null
;
final
String
[]
clean
=
new
String
[
enumerators
.
length
];
for
(
int
i
=
0
;
i
<
enumerators
.
length
;
i
++)
{
clean
[
i
]
=
sanitize
(
enumerators
[
i
]);
}
return
clean
;
}
private
static
String
toString
(
final
String
[]
enumerators
)
{
String
result
=
"("
;
for
(
int
i
=
0
;
i
<
enumerators
.
length
;
i
++)
{
result
+=
"'"
+
enumerators
[
i
]
+
"'"
;
if
(
i
<
enumerators
.
length
-
1
)
{
result
+=
", "
;
}
}
result
+=
")"
;
return
result
;
}
private
static
Validation
validate
(
final
String
[]
enumerators
)
{
final
String
[]
cleaned
=
sanitize
(
enumerators
);
if
(
cleaned
==
null
||
cleaned
.
length
==
0
)
{
return
Validation
.
EMPTY
;
}
for
(
int
i
=
0
;
i
<
cleaned
.
length
;
i
++)
{
if
(
cleaned
[
i
]
==
null
||
cleaned
[
i
].
equals
(
""
))
{
return
Validation
.
EMPTY
;
}
if
(
i
<
cleaned
.
length
-
1
)
{
for
(
int
j
=
i
+
1
;
j
<
cleaned
.
length
;
j
++)
{
if
(
cleaned
[
i
].
equals
(
cleaned
[
j
]))
{
return
Validation
.
DUPLICATE
;
}
}
}
}
return
Validation
.
VALID
;
}
private
static
Validation
validate
(
final
String
[]
enumerators
,
final
Value
value
)
{
final
Validation
validation
=
validate
(
enumerators
);
if
(!
validation
.
equals
(
Validation
.
VALID
))
{
return
validation
;
}
if
(
DataType
.
isStringType
(
value
.
getType
()))
{
final
String
cleanLabel
=
sanitize
(
value
.
getString
());
for
(
int
i
=
0
;
i
<
enumerators
.
length
;
i
++)
{
if
(
cleanLabel
.
equals
(
sanitize
(
enumerators
[
i
])))
{
return
Validation
.
VALID
;
}
}
return
Validation
.
INVALID
;
}
else
{
final
int
ordinal
=
value
.
getInt
();
if
(
ordinal
<
0
||
ordinal
>=
enumerators
.
length
)
{
return
Validation
.
INVALID
;
}
return
Validation
.
VALID
;
}
}
}
h2/src/main/org/h2/value/ValueEnumBase.java
0 → 100644
浏览文件 @
fc102859
package
org
.
h2
.
value
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.util.Locale
;
import
org.h2.message.DbException
;
import
org.h2.util.MathUtils
;
/**
* Base implementation of the ENUM data type.
*
* Currently, this class is used primarily for
* client-server communication.
*/
public
class
ValueEnumBase
extends
Value
{
private
static
final
int
PRECISION
=
10
;
private
static
final
int
DISPLAY_SIZE
=
11
;
private
final
String
label
;
private
final
int
ordinal
;
protected
ValueEnumBase
(
final
String
label
,
final
int
ordinal
)
{
this
.
label
=
label
;
this
.
ordinal
=
ordinal
;
}
@Override
public
Value
add
(
final
Value
v
)
{
final
Value
iv
=
v
.
convertTo
(
Value
.
INT
);
return
convertTo
(
Value
.
INT
).
add
(
iv
);
}
@Override
protected
int
compareSecure
(
final
Value
v
,
final
CompareMode
mode
)
{
return
MathUtils
.
compareInt
(
getInt
(),
v
.
getInt
());
}
@Override
public
Value
divide
(
final
Value
v
)
{
final
Value
iv
=
v
.
convertTo
(
Value
.
INT
);
return
convertTo
(
Value
.
INT
).
divide
(
iv
);
}
@Override
public
boolean
equals
(
final
Object
other
)
{
return
other
instanceof
ValueEnumBase
&&
getInt
()
==
((
ValueEnumBase
)
other
).
getInt
();
}
/**
* Get or create an enum value with the given label and ordinal.
*
* @param label the label
* @param ordinal the ordinal
* @return the value
*/
public
static
ValueEnumBase
get
(
final
String
label
,
final
int
ordinal
)
{
return
new
ValueEnumBase
(
label
,
ordinal
);
}
@Override
public
int
getDisplaySize
()
{
return
DISPLAY_SIZE
;
}
@Override
public
int
getInt
()
{
return
ordinal
;
}
@Override
public
long
getLong
()
{
return
ordinal
;
}
@Override
public
Object
getObject
()
{
return
ordinal
;
}
@Override
public
long
getPrecision
()
{
return
PRECISION
;
}
@Override
public
int
getSignum
()
{
return
Integer
.
signum
(
ordinal
);
}
@Override
public
String
getSQL
()
{
return
getString
();
}
@Override
public
String
getString
()
{
return
label
;
}
@Override
public
int
getType
()
{
return
Value
.
ENUM
;
}
@Override
public
int
hashCode
()
{
int
results
=
31
;
results
+=
getString
().
hashCode
();
results
+=
getInt
();
return
results
;
}
@Override
public
Value
modulus
(
final
Value
v
)
{
final
Value
iv
=
v
.
convertTo
(
Value
.
INT
);
return
convertTo
(
Value
.
INT
).
modulus
(
iv
);
}
@Override
public
Value
multiply
(
final
Value
v
)
{
final
Value
iv
=
v
.
convertTo
(
Value
.
INT
);
return
convertTo
(
Value
.
INT
).
multiply
(
iv
);
}
@Override
public
void
set
(
final
PreparedStatement
prep
,
final
int
parameterIndex
)
throws
SQLException
{
prep
.
setInt
(
parameterIndex
,
ordinal
);
}
@Override
public
Value
subtract
(
final
Value
v
)
{
final
Value
iv
=
v
.
convertTo
(
Value
.
INT
);
return
convertTo
(
Value
.
INT
).
subtract
(
iv
);
}
}
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
浏览文件 @
fc102859
...
...
@@ -57,6 +57,7 @@ public class TestPreparedStatement extends TestBase {
testToString
(
conn
);
testExecuteUpdateCall
(
conn
);
testPrepareExecute
(
conn
);
testEnum
(
conn
);
testUUID
(
conn
);
testUUIDAsJavaObject
(
conn
);
testScopedGeneratedKey
(
conn
);
...
...
@@ -443,6 +444,37 @@ public class TestPreparedStatement extends TestBase {
assertFalse
(
rs
.
next
());
}
private
void
testEnum
(
Connection
conn
)
throws
SQLException
{
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE TABLE test_enum(size ENUM('small', 'medium', 'large'))"
);
String
[]
badSizes
=
new
String
[]{
"green"
,
"smol"
,
"0"
};
for
(
int
i
=
0
;
i
<
badSizes
.
length
;
i
++)
{
PreparedStatement
prep
=
conn
.
prepareStatement
(
"INSERT INTO test_enum VALUES(?)"
);
prep
.
setObject
(
1
,
badSizes
[
i
]);
assertThrows
(
ErrorCode
.
ENUM_VALUE_NOT_PERMITTED_1
,
prep
).
execute
();
}
String
[]
goodSizes
=
new
String
[]{
"small"
,
"medium"
,
"large"
};
for
(
int
i
=
0
;
i
<
goodSizes
.
length
;
i
++)
{
PreparedStatement
prep
=
conn
.
prepareStatement
(
"INSERT INTO test_enum VALUES(?)"
);
prep
.
setObject
(
1
,
goodSizes
[
i
]);
prep
.
execute
();
ResultSet
rs
=
stat
.
executeQuery
(
"SELECT * FROM test_enum"
);
for
(
int
j
=
0
;
j
<=
i
;
j
++)
{
rs
.
next
();
}
assertEquals
(
goodSizes
[
i
],
rs
.
getString
(
1
));
assertEquals
(
i
,
rs
.
getInt
(
1
));
Object
o
=
rs
.
getObject
(
1
);
assertEquals
(
Integer
.
class
,
o
.
getClass
());
}
stat
.
execute
(
"DROP TABLE test_enum"
);
}
private
void
testUUID
(
Connection
conn
)
throws
SQLException
{
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"create table test_uuid(id uuid primary key)"
);
...
...
h2/src/test/org/h2/test/testScript.sql
浏览文件 @
fc102859
...
...
@@ -10588,4 +10588,76 @@ create table z.z (id int);
>
ok
drop
schema
z
;
>
ok
\ No newline at end of file
>
ok
----------------
--- ENUM support
----------------
--- ENUM basic operations
create
table
card
(
rank
int
,
suit
enum
(
'hearts'
,
'clubs'
,
'spades'
));
>
ok
insert
into
card
(
rank
,
suit
)
values
(
0
,
'clubs'
),
(
3
,
'hearts'
);
>
update
count
:
2
alter
table
card
alter
column
suit
enum
(
'hearts'
,
'clubs'
,
'spades'
,
'diamonds'
);
>
ok
select
*
from
card
;
>
RANK
SUIT
>
---- ------
>
0
clubs
>
3
hearts
select
*
from
card
order
by
suit
;
>
RANK
SUIT
>
---- ------
>
3
hearts
>
0
clubs
insert
into
card
(
rank
,
suit
)
values
(
8
,
'diamonds'
),
(
10
,
'clubs'
),
(
7
,
'hearts'
);
>
update
count
:
3
select
suit
,
count
(
rank
)
from
card
group
by
suit
order
by
suit
,
count
(
rank
);
>
SUIT
COUNT
(
RANK
)
>
-------- -----------
>
hearts
2
>
clubs
2
>
diamonds
1
select
rank
from
card
where
suit
=
'diamonds'
;
>
RANK
>
----
>
8
--- ENUM integer-based operations
select
rank
from
card
where
suit
=
1
;
>
RANK
>
----
>
0
>
10
insert
into
card
(
rank
,
suit
)
values
(
5
,
2
);
>
update
count
:
1
select
*
from
card
where
rank
=
5
;
>
RANK
SUIT
>
---- ------
>
5
spades
--- ENUM edge cases
insert
into
card
(
rank
,
suit
)
values
(
6
,
' '
);
>
exception
alter
table
card
alter
column
suit
enum
(
'hearts'
,
'clubs'
,
'spades'
,
'diamonds'
,
'clubs'
);
>
exception
alter
table
card
alter
column
suit
enum
(
'hearts'
,
'clubs'
,
'spades'
,
'diamonds'
,
''
);
>
exception
drop
table
card
;
>
ok
h2/src/tools/org/h2/build/doc/dictionary.txt
浏览文件 @
fc102859
...
...
@@ -76,7 +76,7 @@ calculation calculations calendar calendars call callable callback callbacks
called caller calling calls cally caload came camel can cancel canceled canceling
cancellation cancelled cancels candidates cannot canonical cap capabilities
capability capacity capitalization capitalize capitalized capone caps capture
captured car cardinal cardinality care careful carriage carrier cars cartesian
captured car card
card
inal cardinality care careful carriage carrier cars cartesian
cascade cascading case cases casesensitive casewhen cash casing casqueiro cast
casting castore cat catalina catalog catalogs cataloguing catch catcher catches
catching category catlog caucho caught cause caused causes causing cavestro
...
...
@@ -181,8 +181,8 @@ detailed details detect detected detecting detection detector detects determine
determining deterministic detrimental deusen deutsch dev develop developed
developer developers developing development devenish deviation device devices
dfile dgenerate dgroup dhe dhis diabetes diagnostic diagnostics diagram diagrams
dialect dialog diam
s dick dictionary did didn died dieguez diehard dies diff
differ difference differences different differential differentiate differently
dialect dialog diam
onds diams dick dictionary did didn died dieguez diehard dies
diff
diff
er difference differences different differential differentiate differently
differs dig digest digit digital digits diligence dim dimension dimensional
dimensions dimitrijs dinamica dining dip dips dir direct direction directly
directories directory directs dirname dirs dirty disable disabled
...
...
@@ -218,14 +218,14 @@ encrypting encryption encrypts end ended enderbury endif ending endings endless
endlessly endorse ends enforce enforceability enforceable enforced engine engines
english enhance enhanced enhancement enhancer enlarge enough enqueued ensp ensure
ensures ensuring enter entered entering enterprise entire entities entity entries
entry enum enumerate enumerat
ion env envelope environment environments enwiki eof
e
ol epl epoch epoll epsilon equal equality equally equals equipment equitable
equ
iv equivalent equivalents era erable eremainder eric erik err error errorlevel
er
rors erwan ery esc escape escaped escapes escaping escargots ese espa essential
es
sentials established estimate estimated estimates estimating estimation
est
oppel eta etc eth etl euml euro europe europeu euros eva eval evaluatable
evaluat
e evaluated evaluates evaluating evaluation evdokimov even evenly event
events eventually ever every everybody everyone everything everywhere evict
entry enum enumerate enumerat
ed enumerator enumerators enumeration env envelope
e
nvironment environments enwiki eof eol epl epoch epoll epsilon equal equality equally
equ
als equipment equitable equiv equivalent equivalents era erable eremainder eric
er
ik err error errorlevel errors erwan ery esc escape escaped escapes escaping
es
cargots ese espa essential essentials established estimate estimated estimates
est
imating estimation estoppel eta etc eth etl euml euro europe europeu euros eva eval
evaluat
able evaluate evaluated evaluates evaluating evaluation evdokimov even evenly
event
event
s eventually ever every everybody everyone everything everywhere evict
evicted eviction evolving exact exactly example examples exceed exceeded exceeds
excel except exception exceptions exchange exclude excluded excludes excluding
exclusion exclusive exclusively exe exec executable executables execute executed
...
...
@@ -277,7 +277,7 @@ google googlegroups got goto goubard governed governing government gpg grabbing
graceful graf grails grained grains grajcar grammar grammars grandin grandma
grant grantable granted grantedrole grantee granteetype granting grantor grants
granularity graph graphic graphical graphics grass gray great greater greatest
greatly gredler greece greedy gregorian grep grew grid gridwidth gridx gridy
greatly gredler greece greedy gre
en gre
gorian grep grew grid gridwidth gridx gridy
groove groovy gross group grouped grouping groups groupware grover grow growing
grows growth guarantee guaranteed guard guardian guess guesses guest gui guid
guide guidelines guides gumbo gustav gutierrez gzip hack had haidinyak half hallo
...
...
@@ -485,9 +485,9 @@ predict predicted prediction prefer preferable preferdoslikelineends preferences
preferred prefix prefixes prefs premain premature prep prepare prepared prepares
preparing prepended prepending pres presence present presentation preserve
preserved preserving press pressed pretty prev prevent prevented prevention
prevents previous previously pri price prices primar
y prime primitive primitives
pri
ncipal print printable printed printf printing println prints prio prior
prioritize priority private privilege privileges pro prob probability probable
prevents previous previously pri price prices primar
ily primary prime primitive
pri
mitives principal print printable printed printf printing println prints prio
prior
prior
itize priority private privilege privileges pro prob probability probable
probably problem problematic problems proc procedural procedure procedures
proceed process processed processes processing processor processors procurement
prod produce produced produces product production products prof profile profiler
...
...
@@ -558,7 +558,7 @@ routines row rowcount rowid rowlock rownum rows rowscn rowsize roy royalty rpad
rsaquo rsquo rss rtree rtrim ruby ruebezahl rule rules run rund rundll runnable
runner runners running runs runscript runtime rwd rws sabine safari safe safely
safes safety said sainsbury salary sale sales saload salt salz sam same
sameorigin samp sample samples sanity sans sastore sat satisfy saturday sauce
sameorigin samp sample samples sanit
ize sanit
y sans sastore sat satisfy saturday sauce
sauerkraut sava save saved savepoint savepoints saves saving savings say saying
says sbquo scala scalability scalable scalar scale scaled scales scan scanned
scanner scanners scanning scans scapegoat scc schedule scheduler schem schema
...
...
@@ -591,7 +591,7 @@ sites situation situations six sixty size sized sizeof sizes sizing skeletons sk
skiing skill skip skipped skipping skips sky slash slashdot slashes slave sleep
sleeping sleeps slept slice sliced slight slightly slist slot slots slovensky
slow slowed slower slowest slowing slowly slows small smalldatetime smaller
smallest smallint smart smith sm
tp smtps smuggled
snapshot snapshots snipped
smallest smallint smart smith sm
ol smtp smtps smuggled snake
snapshot snapshots snipped
snippet snippets soap social socket sockets soerensen soffice soft software sold
sole solely solid solo solution solutions solve solved solves solving some
somebody somehow someone something sometime sometimes somewhat somewhere song
...
...
@@ -621,8 +621,8 @@ subscribe subselect subsequent subsequently subset substance substitute
substituted substitution substr substring substrings substructure subsystem
subtract subtracted subtracting subtraction subversion succeed succeeded succeeds
success successful successfully succession such suddenly sudo sue sufficient
sufficiently suffix sugar suggest suggested suggestion suggestions suit
able suit
e
suites sullivan sum summand summary summer summertime sums sun sunday sup supe
sufficiently suffix sugar suggest suggested suggestion suggestions suit
suitabl
e
suite
suite
s sullivan sum summand summary summer summertime sums sun sunday sup supe
super superclass superfluous superinterfaces superior superseded supertable
superuser supplemental supplied supplier supply support supported supporter
supporters supporting supports supposed suppress sure surname surrogate
...
...
@@ -666,7 +666,7 @@ trick tricky tried tries trig trigger triggered triggers trigonometric trim
trimmed trims trip trivial trouble true trunc truncate truncated truncates
truncating truncation trunk trust trusted trx try trying tsi tsmsys tsv tucc
tucker tuesday tune tunes tuning turkel turkish turn turned turns tutorial tweak
tweaking tweet twelve twice twitter two txt tymczak type typeof types typesafe
tweaking tweet twelve twice twitter two txt tymczak type type
d type
of types typesafe
typical typically typing typlen typname typo typos typtypmod tzd tzh tzm tzr
uacute uarr ubuntu ucase ucb ucirc ucs udt udts uffff ugly ugrave uid uint ujint
ujlong ulimit uml umlaut umr unable unaligned unary unavailability unbound
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论