Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
473d3d9c
提交
473d3d9c
authored
1月 17, 2019
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Use TypeInfo in Expression implementations
上级
3f2932f9
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
44 个修改的文件
包含
542 行增加
和
227 行删除
+542
-227
Parser.java
h2/src/main/org/h2/command/Parser.java
+4
-4
CreateTable.java
h2/src/main/org/h2/command/ddl/CreateTable.java
+1
-1
Call.java
h2/src/main/org/h2/command/dml/Call.java
+1
-1
SelectUnion.java
h2/src/main/org/h2/command/dml/SelectUnion.java
+2
-2
Alias.java
h2/src/main/org/h2/expression/Alias.java
+7
-1
BinaryOperation.java
h2/src/main/org/h2/expression/BinaryOperation.java
+25
-6
Expression.java
h2/src/main/org/h2/expression/Expression.java
+12
-3
ExpressionColumn.java
h2/src/main/org/h2/expression/ExpressionColumn.java
+7
-1
ExpressionList.java
h2/src/main/org/h2/expression/ExpressionList.java
+8
-2
IntervalOperation.java
h2/src/main/org/h2/expression/IntervalOperation.java
+14
-2
Parameter.java
h2/src/main/org/h2/expression/Parameter.java
+13
-1
ParameterInterface.java
h2/src/main/org/h2/expression/ParameterInterface.java
+1
-1
ParameterRemote.java
h2/src/main/org/h2/expression/ParameterRemote.java
+2
-2
Rownum.java
h2/src/main/org/h2/expression/Rownum.java
+7
-1
SequenceValue.java
h2/src/main/org/h2/expression/SequenceValue.java
+7
-1
Subquery.java
h2/src/main/org/h2/expression/Subquery.java
+7
-1
UnaryOperation.java
h2/src/main/org/h2/expression/UnaryOperation.java
+15
-9
ValueExpression.java
h2/src/main/org/h2/expression/ValueExpression.java
+8
-2
Variable.java
h2/src/main/org/h2/expression/Variable.java
+7
-1
Wildcard.java
h2/src/main/org/h2/expression/Wildcard.java
+7
-1
Aggregate.java
h2/src/main/org/h2/expression/aggregate/Aggregate.java
+39
-21
JavaAggregate.java
h2/src/main/org/h2/expression/aggregate/JavaAggregate.java
+10
-2
WindowFunction.java
h2/src/main/org/h2/expression/analysis/WindowFunction.java
+27
-3
CompareLike.java
h2/src/main/org/h2/expression/condition/CompareLike.java
+1
-1
Comparison.java
h2/src/main/org/h2/expression/condition/Comparison.java
+4
-4
Condition.java
h2/src/main/org/h2/expression/condition/Condition.java
+7
-1
ConditionIn.java
h2/src/main/org/h2/expression/condition/ConditionIn.java
+1
-1
ConditionInConstantSet.java
...n/org/h2/expression/condition/ConditionInConstantSet.java
+1
-1
Function.java
h2/src/main/org/h2/expression/function/Function.java
+112
-116
FunctionCall.java
h2/src/main/org/h2/expression/function/FunctionCall.java
+1
-1
JavaFunction.java
h2/src/main/org/h2/expression/function/JavaFunction.java
+9
-3
JdbcParameterMetaData.java
h2/src/main/org/h2/jdbc/JdbcParameterMetaData.java
+3
-3
FunctionsMySQL.java
h2/src/main/org/h2/mode/FunctionsMySQL.java
+2
-5
LazyResult.java
h2/src/main/org/h2/result/LazyResult.java
+1
-1
LocalResultImpl.java
h2/src/main/org/h2/result/LocalResultImpl.java
+1
-1
ResultTempTable.java
h2/src/main/org/h2/result/ResultTempTable.java
+1
-1
FunctionTable.java
h2/src/main/org/h2/table/FunctionTable.java
+1
-1
MetaTable.java
h2/src/main/org/h2/table/MetaTable.java
+1
-1
TableView.java
h2/src/main/org/h2/table/TableView.java
+2
-2
DataType.java
h2/src/main/org/h2/value/DataType.java
+1
-0
TypeInfo.java
h2/src/main/org/h2/value/TypeInfo.java
+160
-3
ValueArray.java
h2/src/main/org/h2/value/ValueArray.java
+0
-5
ValueRow.java
h2/src/main/org/h2/value/ValueRow.java
+0
-5
TestDate.java
h2/src/test/org/h2/test/unit/TestDate.java
+2
-2
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
473d3d9c
...
...
@@ -2440,7 +2440,7 @@ public class Parser {
SelectOrderBy
order
=
new
SelectOrderBy
();
Expression
expr
=
readExpression
();
if
(
canBeNumber
&&
expr
instanceof
ValueExpression
&&
expr
.
getType
()
==
Value
.
INT
)
{
expr
.
get
Value
Type
()
==
Value
.
INT
)
{
order
.
columnIndexExpr
=
expr
;
}
else
if
(
expr
instanceof
Parameter
)
{
recompileAlways
=
true
;
...
...
@@ -3837,12 +3837,12 @@ public class Parser {
read
();
if
(
currentTokenType
==
VALUE
)
{
r
=
ValueExpression
.
get
(
currentValue
.
negate
());
if
(
r
.
getType
()
==
Value
.
LONG
&&
if
(
r
.
get
Value
Type
()
==
Value
.
LONG
&&
r
.
getValue
(
session
).
getLong
()
==
Integer
.
MIN_VALUE
)
{
// convert Integer.MIN_VALUE to type 'int'
// (Integer.MAX_VALUE+1 is of type 'long')
r
=
ValueExpression
.
get
(
ValueInt
.
get
(
Integer
.
MIN_VALUE
));
}
else
if
(
r
.
getType
()
==
Value
.
DECIMAL
&&
}
else
if
(
r
.
get
Value
Type
()
==
Value
.
DECIMAL
&&
r
.
getValue
(
session
).
getBigDecimal
()
.
compareTo
(
Value
.
MIN_LONG_DECIMAL
)
==
0
)
{
// convert Long.MIN_VALUE to type 'long'
...
...
@@ -5841,7 +5841,7 @@ public class Parser {
do
{
Expression
expr
=
readExpression
();
expr
=
expr
.
optimize
(
session
);
int
type
=
expr
.
getType
();
int
type
=
expr
.
get
Value
Type
();
long
prec
;
int
scale
,
displaySize
;
Column
column
;
...
...
h2/src/main/org/h2/command/ddl/CreateTable.java
浏览文件 @
473d3d9c
...
...
@@ -180,7 +180,7 @@ public class CreateTable extends CommandWithColumns {
ColumnNamer
columnNamer
=
new
ColumnNamer
(
session
);
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
Expression
expr
=
expressions
.
get
(
i
);
int
type
=
expr
.
getType
();
int
type
=
expr
.
get
Value
Type
();
String
name
=
columnNamer
.
getColumnName
(
expr
,
i
,
expr
.
getAlias
());
long
precision
=
expr
.
getPrecision
();
int
displaySize
=
expr
.
getDisplaySize
();
...
...
h2/src/main/org/h2/command/dml/Call.java
浏览文件 @
473d3d9c
...
...
@@ -76,7 +76,7 @@ public class Call extends Prepared {
public
void
prepare
()
{
expression
=
expression
.
optimize
(
session
);
expressions
=
new
Expression
[]
{
expression
};
isResultSet
=
expression
.
getType
()
==
Value
.
RESULT_SET
;
isResultSet
=
expression
.
get
Value
Type
()
==
Value
.
RESULT_SET
;
if
(
isResultSet
)
{
prepareAlways
=
true
;
}
...
...
h2/src/main/org/h2/command/dml/SelectUnion.java
浏览文件 @
473d3d9c
...
...
@@ -121,7 +121,7 @@ public class SelectUnion extends Query {
Mode
mode
=
session
.
getDatabase
().
getMode
();
for
(
int
i
=
0
;
i
<
columnCount
;
i
++)
{
Expression
e
=
expressions
.
get
(
i
);
newValues
[
i
]
=
values
[
i
].
convertTo
(
e
.
getType
(),
mode
);
newValues
[
i
]
=
values
[
i
].
convertTo
(
e
.
get
Value
Type
(),
mode
);
}
return
newValues
;
}
...
...
@@ -328,7 +328,7 @@ public class SelectUnion extends Query {
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
Expression
l
=
le
.
get
(
i
);
Expression
r
=
re
.
get
(
i
);
int
type
=
Value
.
getHigherOrder
(
l
.
get
Type
(),
r
.
get
Type
());
int
type
=
Value
.
getHigherOrder
(
l
.
get
ValueType
(),
r
.
getValue
Type
());
long
prec
=
Math
.
max
(
l
.
getPrecision
(),
r
.
getPrecision
());
int
scale
=
Math
.
max
(
l
.
getScale
(),
r
.
getScale
());
int
displaySize
=
Math
.
max
(
l
.
getDisplaySize
(),
r
.
getDisplaySize
());
...
...
h2/src/main/org/h2/expression/Alias.java
浏览文件 @
473d3d9c
...
...
@@ -9,6 +9,7 @@ import org.h2.command.Parser;
import
org.h2.engine.Session
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
/**
...
...
@@ -37,10 +38,15 @@ public class Alias extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
expr
.
getType
();
}
@Override
public
int
getValueType
()
{
return
expr
.
getValueType
();
}
@Override
public
void
mapColumns
(
ColumnResolver
resolver
,
int
level
,
int
state
)
{
expr
.
mapColumns
(
resolver
,
level
,
state
);
...
...
h2/src/main/org/h2/expression/BinaryOperation.java
浏览文件 @
473d3d9c
...
...
@@ -14,6 +14,7 @@ import org.h2.table.ColumnResolver;
import
org.h2.table.TableFilter
;
import
org.h2.util.MathUtils
;
import
org.h2.value.DataType
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueInt
;
import
org.h2.value.ValueNull
;
...
...
@@ -59,6 +60,7 @@ public class BinaryOperation extends Expression {
private
OpType
opType
;
private
Expression
left
,
right
;
private
TypeInfo
type
;
private
int
dataType
;
private
boolean
convertRight
=
true
;
...
...
@@ -164,6 +166,7 @@ public class BinaryOperation extends Expression {
right
=
right
.
optimize
(
session
);
switch
(
opType
)
{
case
CONCAT:
type
=
TypeInfo
.
TYPE_STRING_DEFAULT
;
dataType
=
Value
.
STRING
;
break
;
case
PLUS:
...
...
@@ -171,17 +174,19 @@ public class BinaryOperation extends Expression {
case
MULTIPLY:
case
DIVIDE:
case
MODULUS:
int
l
=
left
.
getType
();
int
r
=
right
.
getType
();
int
l
=
left
.
get
Value
Type
();
int
r
=
right
.
get
Value
Type
();
if
((
l
==
Value
.
NULL
&&
r
==
Value
.
NULL
)
||
(
l
==
Value
.
UNKNOWN
&&
r
==
Value
.
UNKNOWN
))
{
// (? + ?) - use decimal by default (the most safe data type) or
// string when text concatenation with + is enabled
if
(
opType
==
OpType
.
PLUS
&&
session
.
getDatabase
().
getMode
().
allowPlusForStringConcat
)
{
type
=
TypeInfo
.
TYPE_STRING_DEFAULT
;
dataType
=
Value
.
STRING
;
opType
=
OpType
.
CONCAT
;
}
else
{
type
=
TypeInfo
.
TYPE_DECIMAL_DEFAULT
;
dataType
=
Value
.
DECIMAL
;
}
}
else
if
(
DataType
.
isIntervalType
(
l
)
||
DataType
.
isIntervalType
(
r
))
{
...
...
@@ -191,10 +196,13 @@ public class BinaryOperation extends Expression {
}
else
{
dataType
=
Value
.
getHigherOrder
(
l
,
r
);
if
(
dataType
==
Value
.
ENUM
)
{
type
=
TypeInfo
.
TYPE_INT
;
dataType
=
Value
.
INT
;
}
else
if
(
DataType
.
isStringType
(
dataType
)
&&
session
.
getDatabase
().
getMode
().
allowPlusForStringConcat
)
{
opType
=
OpType
.
CONCAT
;
}
else
{
type
=
TypeInfo
.
getTypeInfo
(
dataType
);
if
(
DataType
.
isStringType
(
dataType
)
&&
session
.
getDatabase
().
getMode
().
allowPlusForStringConcat
)
{
opType
=
OpType
.
CONCAT
;
}
}
}
break
;
...
...
@@ -311,8 +319,10 @@ public class BinaryOperation extends Expression {
case
Value
.
TIME
:
if
(
r
==
Value
.
TIME
||
r
==
Value
.
TIMESTAMP_TZ
)
{
dataType
=
r
;
type
=
TypeInfo
.
getTypeInfo
(
r
);
return
this
;
}
else
{
// DATE, TIMESTAMP
type
=
TypeInfo
.
TYPE_TIMESTAMP
;
dataType
=
Value
.
TIMESTAMP
;
return
this
;
}
...
...
@@ -351,6 +361,7 @@ public class BinaryOperation extends Expression {
return
f
.
optimize
(
session
);
}
case
Value
.
TIME
:
type
=
TypeInfo
.
TYPE_TIMESTAMP
;
dataType
=
Value
.
TIMESTAMP
;
return
this
;
case
Value
.
DATE
:
...
...
@@ -368,11 +379,13 @@ public class BinaryOperation extends Expression {
break
;
case
MULTIPLY:
if
(
l
==
Value
.
TIME
)
{
type
=
TypeInfo
.
TYPE_TIME
;
dataType
=
Value
.
TIME
;
convertRight
=
false
;
return
this
;
}
else
if
(
r
==
Value
.
TIME
)
{
swap
();
type
=
TypeInfo
.
TYPE_TIME
;
dataType
=
Value
.
TIME
;
convertRight
=
false
;
return
this
;
...
...
@@ -380,6 +393,7 @@ public class BinaryOperation extends Expression {
break
;
case
DIVIDE:
if
(
l
==
Value
.
TIME
)
{
type
=
TypeInfo
.
TYPE_TIME
;
dataType
=
Value
.
TIME
;
convertRight
=
false
;
return
this
;
...
...
@@ -408,7 +422,12 @@ public class BinaryOperation extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
type
;
}
@Override
public
int
getValueType
()
{
return
dataType
;
}
...
...
h2/src/main/org/h2/expression/Expression.java
浏览文件 @
473d3d9c
...
...
@@ -13,6 +13,7 @@ import org.h2.result.ResultInterface;
import
org.h2.table.Column
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueArray
;
...
...
@@ -84,12 +85,20 @@ public abstract class Expression {
public
abstract
Value
getValue
(
Session
session
);
/**
* Return the data type. The data type may not be known before the
* Return
s
the data type. The data type may not be known before the
* optimization phase.
*
* @return the type
* @return the
data
type
*/
public
abstract
int
getType
();
public
abstract
TypeInfo
getType
();
/**
* Return the value type. The value type may not be known before the
* optimization phase.
*
* @return the value type
*/
public
abstract
int
getValueType
();
/**
* Map the columns of the resolver to expression columns.
...
...
h2/src/main/org/h2/expression/ExpressionColumn.java
浏览文件 @
473d3d9c
...
...
@@ -22,6 +22,7 @@ import org.h2.table.ColumnResolver;
import
org.h2.table.Table
;
import
org.h2.table.TableFilter
;
import
org.h2.value.ExtTypeInfo
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueBoolean
;
import
org.h2.value.ValueNull
;
...
...
@@ -225,7 +226,12 @@ public class ExpressionColumn extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
column
==
null
?
TypeInfo
.
TYPE_UNKNOWN
:
column
.
getType
();
}
@Override
public
int
getValueType
()
{
return
column
==
null
?
Value
.
UNKNOWN
:
column
.
getType
().
getValueType
();
}
...
...
h2/src/main/org/h2/expression/ExpressionList.java
浏览文件 @
473d3d9c
...
...
@@ -9,6 +9,7 @@ import org.h2.engine.Session;
import
org.h2.table.Column
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueArray
;
import
org.h2.value.ValueRow
;
...
...
@@ -37,7 +38,12 @@ public class ExpressionList extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
isArray
?
TypeInfo
.
TYPE_ARRAY
:
TypeInfo
.
TYPE_ROW
;
}
@Override
public
int
getValueType
()
{
return
isArray
?
Value
.
ARRAY
:
Value
.
ROW
;
}
...
...
@@ -125,7 +131,7 @@ public class ExpressionList extends Expression {
for
(
int
i
=
0
;
i
<
list
.
length
;
i
++)
{
Expression
e
=
list
[
i
];
Column
col
=
new
Column
(
"C"
+
(
i
+
1
),
e
.
getType
(),
e
.
getPrecision
(),
e
.
getScale
(),
e
.
get
Value
Type
(),
e
.
getPrecision
(),
e
.
getScale
(),
e
.
getDisplaySize
());
expr
[
i
]
=
new
ExpressionColumn
(
session
.
getDatabase
(),
col
);
}
...
...
h2/src/main/org/h2/expression/IntervalOperation.java
浏览文件 @
473d3d9c
...
...
@@ -26,6 +26,7 @@ import org.h2.table.ColumnResolver;
import
org.h2.table.TableFilter
;
import
org.h2.util.IntervalUtils
;
import
org.h2.value.DataType
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDate
;
import
org.h2.value.ValueInterval
;
...
...
@@ -77,6 +78,7 @@ public class IntervalOperation extends Expression {
private
final
IntervalOpType
opType
;
private
Expression
left
,
right
;
private
TypeInfo
type
;
private
int
dataType
;
private
static
BigInteger
nanosFromValue
(
Value
v
)
{
...
...
@@ -89,24 +91,29 @@ public class IntervalOperation extends Expression {
this
.
opType
=
opType
;
this
.
left
=
left
;
this
.
right
=
right
;
int
l
=
left
.
get
Type
(),
r
=
right
.
get
Type
();
int
l
=
left
.
get
ValueType
(),
r
=
right
.
getValue
Type
();
switch
(
opType
)
{
case
INTERVAL_PLUS_INTERVAL:
case
INTERVAL_MINUS_INTERVAL:
dataType
=
Value
.
getHigherOrder
(
l
,
r
);
type
=
TypeInfo
.
getTypeInfo
(
dataType
);
break
;
case
DATETIME_PLUS_INTERVAL:
case
DATETIME_MINUS_INTERVAL:
case
INTERVAL_MULTIPLY_NUMERIC:
case
INTERVAL_DIVIDE_NUMERIC:
type
=
left
.
getType
();
dataType
=
l
;
break
;
case
DATETIME_MINUS_DATETIME:
if
(
l
==
Value
.
TIME
&&
r
==
Value
.
TIME
)
{
type
=
TypeInfo
.
TYPE_INTERVAL_HOUR_TO_SECOND
;
dataType
=
Value
.
INTERVAL_HOUR_TO_SECOND
;
}
else
if
(
l
==
Value
.
DATE
&&
r
==
Value
.
DATE
)
{
type
=
TypeInfo
.
TYPE_INTERVAL_DAY
;
dataType
=
Value
.
INTERVAL_DAY
;
}
else
{
type
=
TypeInfo
.
TYPE_INTERVAL_DAY_TO_SECOND
;
dataType
=
Value
.
INTERVAL_DAY_TO_SECOND
;
}
}
...
...
@@ -277,7 +284,12 @@ public class IntervalOperation extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
type
;
}
@Override
public
int
getValueType
()
{
return
dataType
;
}
...
...
h2/src/main/org/h2/expression/Parameter.java
浏览文件 @
473d3d9c
...
...
@@ -12,6 +12,7 @@ import org.h2.message.DbException;
import
org.h2.table.Column
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueBoolean
;
import
org.h2.value.ValueNull
;
...
...
@@ -61,7 +62,18 @@ public class Parameter extends Expression implements ParameterInterface {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
if
(
value
!=
null
)
{
return
value
.
getType
();
}
if
(
column
!=
null
)
{
return
column
.
getType
();
}
return
TypeInfo
.
TYPE_UNKNOWN
;
}
@Override
public
int
getValueType
()
{
if
(
value
!=
null
)
{
return
value
.
getValueType
();
}
...
...
h2/src/main/org/h2/expression/ParameterInterface.java
浏览文件 @
473d3d9c
...
...
@@ -48,7 +48,7 @@ public interface ParameterInterface {
*
* @return the data type
*/
int
getType
();
int
get
Value
Type
();
/**
* Get the expected precision of this parameter.
...
...
h2/src/main/org/h2/expression/ParameterRemote.java
浏览文件 @
473d3d9c
...
...
@@ -55,7 +55,7 @@ public class ParameterRemote implements ParameterInterface {
}
@Override
public
int
getType
()
{
public
int
get
Value
Type
()
{
return
value
==
null
?
dataType
:
value
.
getValueType
();
}
...
...
@@ -94,7 +94,7 @@ public class ParameterRemote implements ParameterInterface {
*/
public
static
void
writeMetaData
(
Transfer
transfer
,
ParameterInterface
p
)
throws
IOException
{
transfer
.
writeInt
(
p
.
getType
());
transfer
.
writeInt
(
p
.
get
Value
Type
());
transfer
.
writeLong
(
p
.
getPrecision
());
transfer
.
writeInt
(
p
.
getScale
());
transfer
.
writeInt
(
p
.
getNullable
());
...
...
h2/src/main/org/h2/expression/Rownum.java
浏览文件 @
473d3d9c
...
...
@@ -10,6 +10,7 @@ import org.h2.engine.Session;
import
org.h2.message.DbException
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueLong
;
...
...
@@ -33,7 +34,12 @@ public class Rownum extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
TypeInfo
.
TYPE_LONG
;
}
@Override
public
int
getValueType
()
{
return
Value
.
LONG
;
}
...
...
h2/src/main/org/h2/expression/SequenceValue.java
浏览文件 @
473d3d9c
...
...
@@ -10,6 +10,7 @@ import org.h2.message.DbException;
import
org.h2.schema.Sequence
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueLong
;
...
...
@@ -32,7 +33,12 @@ public class SequenceValue extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
TypeInfo
.
TYPE_LONG
;
}
@Override
public
int
getValueType
()
{
return
Value
.
LONG
;
}
...
...
h2/src/main/org/h2/expression/Subquery.java
浏览文件 @
473d3d9c
...
...
@@ -13,6 +13,7 @@ import org.h2.message.DbException;
import
org.h2.result.ResultInterface
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueNull
;
import
org.h2.value.ValueRow
;
...
...
@@ -53,10 +54,15 @@ public class Subquery extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
getExpression
().
getType
();
}
@Override
public
int
getValueType
()
{
return
getExpression
().
getValueType
();
}
@Override
public
void
mapColumns
(
ColumnResolver
resolver
,
int
level
,
int
state
)
{
query
.
mapColumns
(
resolver
,
level
+
1
);
...
...
h2/src/main/org/h2/expression/UnaryOperation.java
浏览文件 @
473d3d9c
...
...
@@ -8,6 +8,7 @@ package org.h2.expression;
import
org.h2.engine.Session
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueNull
;
...
...
@@ -17,7 +18,7 @@ import org.h2.value.ValueNull;
public
class
UnaryOperation
extends
Expression
{
private
Expression
arg
;
private
int
dataT
ype
;
private
TypeInfo
t
ype
;
public
UnaryOperation
(
Expression
arg
)
{
this
.
arg
=
arg
;
...
...
@@ -33,7 +34,7 @@ public class UnaryOperation extends Expression {
@Override
public
Value
getValue
(
Session
session
)
{
Value
a
=
arg
.
getValue
(
session
).
convertTo
(
dataType
,
session
.
getDatabase
().
getMode
());
Value
a
=
arg
.
getValue
(
session
).
convertTo
(
type
.
getValueType
()
,
session
.
getDatabase
().
getMode
());
return
a
==
ValueNull
.
INSTANCE
?
a
:
a
.
negate
();
}
...
...
@@ -45,11 +46,11 @@ public class UnaryOperation extends Expression {
@Override
public
Expression
optimize
(
Session
session
)
{
arg
=
arg
.
optimize
(
session
);
dataT
ype
=
arg
.
getType
();
if
(
dataType
==
Value
.
UNKNOWN
)
{
dataType
=
Value
.
DECIMAL
;
}
else
if
(
dataType
==
Value
.
ENUM
)
{
dataType
=
Value
.
INT
;
t
ype
=
arg
.
getType
();
if
(
type
.
getValueType
()
==
Value
.
UNKNOWN
)
{
type
=
TypeInfo
.
TYPE_DECIMAL_DEFAULT
;
}
else
if
(
type
.
getValueType
()
==
Value
.
ENUM
)
{
type
=
TypeInfo
.
TYPE_
INT
;
}
if
(
arg
.
isConstant
())
{
return
ValueExpression
.
get
(
getValue
(
session
));
...
...
@@ -63,8 +64,13 @@ public class UnaryOperation extends Expression {
}
@Override
public
int
getType
()
{
return
dataType
;
public
TypeInfo
getType
()
{
return
type
;
}
@Override
public
int
getValueType
()
{
return
type
.
getValueType
();
}
@Override
...
...
h2/src/main/org/h2/expression/ValueExpression.java
浏览文件 @
473d3d9c
...
...
@@ -11,6 +11,7 @@ import org.h2.index.IndexCondition;
import
org.h2.message.DbException
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueArray
;
import
org.h2.value.ValueBoolean
;
...
...
@@ -75,7 +76,12 @@ public class ValueExpression extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
value
.
getType
();
}
@Override
public
int
getValueType
()
{
return
value
.
getValueType
();
}
...
...
@@ -177,7 +183,7 @@ public class ValueExpression extends Expression {
@Override
public
Expression
[]
getExpressionColumns
(
Session
session
)
{
if
(
getType
()
==
Value
.
ARRAY
)
{
if
(
get
Value
Type
()
==
Value
.
ARRAY
)
{
return
getExpressionColumns
(
session
,
(
ValueArray
)
getValue
(
session
));
}
return
super
.
getExpressionColumns
(
session
);
...
...
h2/src/main/org/h2/expression/Variable.java
浏览文件 @
473d3d9c
...
...
@@ -10,6 +10,7 @@ import org.h2.engine.Session;
import
org.h2.message.DbException
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
/**
...
...
@@ -52,7 +53,12 @@ public class Variable extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
lastValue
.
getType
();
}
@Override
public
int
getValueType
()
{
return
lastValue
.
getValueType
();
}
...
...
h2/src/main/org/h2/expression/Wildcard.java
浏览文件 @
473d3d9c
...
...
@@ -15,6 +15,7 @@ import org.h2.table.Column;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.util.StringUtils
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
/**
...
...
@@ -67,7 +68,12 @@ public class Wildcard extends Expression {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
throw
DbException
.
throwInternalError
(
toString
());
}
@Override
public
int
getValueType
()
{
throw
DbException
.
throwInternalError
(
toString
());
}
...
...
h2/src/main/org/h2/expression/aggregate/Aggregate.java
浏览文件 @
473d3d9c
...
...
@@ -35,6 +35,7 @@ import org.h2.util.StatementBuilder;
import
org.h2.util.ValueHashMap
;
import
org.h2.value.CompareMode
;
import
org.h2.value.DataType
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueArray
;
import
org.h2.value.ValueBoolean
;
...
...
@@ -158,12 +159,13 @@ public class Aggregate extends AbstractAggregate {
private
static
final
HashMap
<
String
,
AggregateType
>
AGGREGATES
=
new
HashMap
<>(
64
);
private
final
AggregateType
t
ype
;
private
final
AggregateType
aggregateT
ype
;
private
Expression
on
;
private
Expression
groupConcatSeparator
;
private
ArrayList
<
SelectOrderBy
>
orderByList
;
private
SortOrder
orderBySort
;
private
TypeInfo
type
;
private
int
dataType
,
scale
;
private
long
precision
;
private
int
displaySize
;
...
...
@@ -171,7 +173,7 @@ public class Aggregate extends AbstractAggregate {
/**
* Create a new aggregate object.
*
* @param
t
ype
* @param
aggregateT
ype
* the aggregate type
* @param on
* the aggregated expression
...
...
@@ -180,12 +182,12 @@ public class Aggregate extends AbstractAggregate {
* @param distinct
* if distinct is used
*/
public
Aggregate
(
AggregateType
t
ype
,
Expression
on
,
Select
select
,
boolean
distinct
)
{
public
Aggregate
(
AggregateType
aggregateT
ype
,
Expression
on
,
Select
select
,
boolean
distinct
)
{
super
(
select
,
distinct
);
if
(
distinct
&&
t
ype
==
AggregateType
.
COUNT_ALL
)
{
if
(
distinct
&&
aggregateT
ype
==
AggregateType
.
COUNT_ALL
)
{
throw
DbException
.
throwInternalError
();
}
this
.
type
=
t
ype
;
this
.
aggregateType
=
aggregateT
ype
;
this
.
on
=
on
;
}
...
...
@@ -272,7 +274,7 @@ public class Aggregate extends AbstractAggregate {
* @return the type of this aggregate
*/
public
AggregateType
getAggregateType
()
{
return
t
ype
;
return
aggregateT
ype
;
}
private
void
sortWithOrderBy
(
Value
[]
array
)
{
...
...
@@ -297,11 +299,11 @@ public class Aggregate extends AbstractAggregate {
}
private
void
updateData
(
Session
session
,
AggregateData
data
,
Value
v
,
Value
[]
remembered
)
{
if
(
t
ype
==
AggregateType
.
GROUP_CONCAT
)
{
if
(
aggregateT
ype
==
AggregateType
.
GROUP_CONCAT
)
{
if
(
v
!=
ValueNull
.
INSTANCE
)
{
v
=
updateCollecting
(
session
,
v
.
convertTo
(
Value
.
STRING
),
remembered
);
}
}
else
if
(
t
ype
==
AggregateType
.
ARRAY_AGG
)
{
}
else
if
(
aggregateT
ype
==
AggregateType
.
ARRAY_AGG
)
{
if
(
v
!=
ValueNull
.
INSTANCE
)
{
v
=
updateCollecting
(
session
,
v
,
remembered
);
}
...
...
@@ -379,7 +381,7 @@ public class Aggregate extends AbstractAggregate {
@Override
protected
Object
createAggregateData
()
{
return
AggregateData
.
create
(
t
ype
,
distinct
);
return
AggregateData
.
create
(
aggregateT
ype
,
distinct
);
}
@Override
...
...
@@ -388,14 +390,14 @@ public class Aggregate extends AbstractAggregate {
}
private
Value
getValueQuick
(
Session
session
)
{
switch
(
t
ype
)
{
switch
(
aggregateT
ype
)
{
case
COUNT:
case
COUNT_ALL:
Table
table
=
select
.
getTopTableFilter
().
getTable
();
return
ValueLong
.
get
(
table
.
getRowCount
(
session
));
case
MIN:
case
MAX:
{
boolean
first
=
t
ype
==
AggregateType
.
MIN
;
boolean
first
=
aggregateT
ype
==
AggregateType
.
MIN
;
Index
index
=
getMinMaxColumnIndex
();
int
sortType
=
index
.
getIndexColumns
()[
0
].
sortType
;
if
((
sortType
&
SortOrder
.
DESCENDING
)
!=
0
)
{
...
...
@@ -416,7 +418,7 @@ public class Aggregate extends AbstractAggregate {
case
ENVELOPE:
return
((
MVSpatialIndex
)
AggregateDataEnvelope
.
getGeometryColumnIndex
(
on
)).
getBounds
(
session
);
default
:
throw
DbException
.
throwInternalError
(
"type="
+
t
ype
);
throw
DbException
.
throwInternalError
(
"type="
+
aggregateT
ype
);
}
}
...
...
@@ -426,7 +428,7 @@ public class Aggregate extends AbstractAggregate {
if
(
data
==
null
)
{
data
=
(
AggregateData
)
createAggregateData
();
}
switch
(
t
ype
)
{
switch
(
aggregateT
ype
)
{
case
COUNT:
if
(
distinct
)
{
return
ValueLong
.
get
(((
AggregateDataCollecting
)
data
).
getCount
());
...
...
@@ -443,7 +445,7 @@ public class Aggregate extends AbstractAggregate {
if
(
c
.
getCount
()
==
0
)
{
return
ValueNull
.
INSTANCE
;
}
AggregateDataDefault
d
=
new
AggregateDataDefault
(
t
ype
);
AggregateDataDefault
d
=
new
AggregateDataDefault
(
aggregateT
ype
);
Database
db
=
session
.
getDatabase
();
for
(
Value
v
:
c
)
{
d
.
add
(
db
,
dataType
,
v
);
...
...
@@ -579,7 +581,12 @@ public class Aggregate extends AbstractAggregate {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
type
;
}
@Override
public
int
getValueType
()
{
return
dataType
;
}
...
...
@@ -604,7 +611,8 @@ public class Aggregate extends AbstractAggregate {
super
.
optimize
(
session
);
if
(
on
!=
null
)
{
on
=
on
.
optimize
(
session
);
dataType
=
on
.
getType
();
type
=
on
.
getType
();
dataType
=
on
.
getValueType
();
scale
=
on
.
getScale
();
precision
=
on
.
getPrecision
();
displaySize
=
on
.
getDisplaySize
();
...
...
@@ -618,26 +626,30 @@ public class Aggregate extends AbstractAggregate {
if
(
groupConcatSeparator
!=
null
)
{
groupConcatSeparator
=
groupConcatSeparator
.
optimize
(
session
);
}
switch
(
t
ype
)
{
switch
(
aggregateT
ype
)
{
case
GROUP_CONCAT:
type
=
TypeInfo
.
TYPE_STRING_DEFAULT
;
dataType
=
Value
.
STRING
;
scale
=
0
;
precision
=
displaySize
=
Integer
.
MAX_VALUE
;
break
;
case
COUNT_ALL:
case
COUNT:
type
=
TypeInfo
.
TYPE_LONG
;
dataType
=
Value
.
LONG
;
scale
=
0
;
precision
=
ValueLong
.
PRECISION
;
displaySize
=
ValueLong
.
DISPLAY_SIZE
;
break
;
case
SELECTIVITY:
type
=
TypeInfo
.
TYPE_INT
;
dataType
=
Value
.
INT
;
scale
=
0
;
precision
=
ValueInt
.
PRECISION
;
displaySize
=
ValueInt
.
DISPLAY_SIZE
;
break
;
case
HISTOGRAM:
type
=
TypeInfo
.
TYPE_ARRAY
;
dataType
=
Value
.
ARRAY
;
scale
=
0
;
precision
=
displaySize
=
Integer
.
MAX_VALUE
;
...
...
@@ -645,11 +657,13 @@ public class Aggregate extends AbstractAggregate {
case
SUM:
if
(
dataType
==
Value
.
BOOLEAN
)
{
// example: sum(id > 3) (count the rows)
type
=
TypeInfo
.
TYPE_LONG
;
dataType
=
Value
.
LONG
;
}
else
if
(!
DataType
.
supportsAdd
(
dataType
))
{
throw
DbException
.
get
(
ErrorCode
.
SUM_OR_AVG_ON_WRONG_DATATYPE_1
,
getSQL
());
}
else
{
dataType
=
DataType
.
getAddProofType
(
dataType
);
type
=
TypeInfo
.
getTypeInfo
(
dataType
);
}
break
;
case
AVG:
...
...
@@ -666,6 +680,7 @@ public class Aggregate extends AbstractAggregate {
case
STDDEV_SAMP:
case
VAR_POP:
case
VAR_SAMP:
type
=
TypeInfo
.
TYPE_DOUBLE
;
dataType
=
Value
.
DOUBLE
;
precision
=
ValueDouble
.
PRECISION
;
displaySize
=
ValueDouble
.
DISPLAY_SIZE
;
...
...
@@ -673,6 +688,7 @@ public class Aggregate extends AbstractAggregate {
break
;
case
EVERY:
case
ANY:
type
=
TypeInfo
.
TYPE_BOOLEAN
;
dataType
=
Value
.
BOOLEAN
;
precision
=
ValueBoolean
.
PRECISION
;
displaySize
=
ValueBoolean
.
DISPLAY_SIZE
;
...
...
@@ -685,17 +701,19 @@ public class Aggregate extends AbstractAggregate {
}
break
;
case
ARRAY_AGG:
type
=
TypeInfo
.
TYPE_ARRAY
;
dataType
=
Value
.
ARRAY
;
scale
=
0
;
precision
=
displaySize
=
Integer
.
MAX_VALUE
;
break
;
case
ENVELOPE:
type
=
TypeInfo
.
TYPE_GEOMETRY
;
dataType
=
Value
.
GEOMETRY
;
scale
=
0
;
precision
=
displaySize
=
Integer
.
MAX_VALUE
;
break
;
default
:
DbException
.
throwInternalError
(
"type="
+
t
ype
);
DbException
.
throwInternalError
(
"type="
+
aggregateT
ype
);
}
return
this
;
}
...
...
@@ -760,7 +778,7 @@ public class Aggregate extends AbstractAggregate {
@Override
public
StringBuilder
getSQL
(
StringBuilder
builder
)
{
String
text
;
switch
(
t
ype
)
{
switch
(
aggregateT
ype
)
{
case
GROUP_CONCAT:
return
getSQLGroupConcat
(
builder
);
case
COUNT_ALL:
...
...
@@ -822,7 +840,7 @@ public class Aggregate extends AbstractAggregate {
text
=
"ENVELOPE"
;
break
;
default
:
throw
DbException
.
throwInternalError
(
"type="
+
t
ype
);
throw
DbException
.
throwInternalError
(
"type="
+
aggregateT
ype
);
}
builder
.
append
(
text
);
if
(
distinct
)
{
...
...
@@ -862,7 +880,7 @@ public class Aggregate extends AbstractAggregate {
return
false
;
}
if
(
visitor
.
getType
()
==
ExpressionVisitor
.
OPTIMIZABLE_AGGREGATE
)
{
switch
(
t
ype
)
{
switch
(
aggregateT
ype
)
{
case
COUNT:
if
(!
distinct
&&
on
.
getNullable
()
==
Column
.
NOT_NULLABLE
)
{
return
visitor
.
getTable
().
canGetRowCount
();
...
...
h2/src/main/org/h2/expression/aggregate/JavaAggregate.java
浏览文件 @
473d3d9c
...
...
@@ -18,6 +18,7 @@ import org.h2.message.DbException;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.DataType
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueArray
;
import
org.h2.value.ValueBoolean
;
...
...
@@ -31,6 +32,7 @@ public class JavaAggregate extends AbstractAggregate {
private
final
UserAggregate
userAggregate
;
private
final
Expression
[]
args
;
private
int
[]
argTypes
;
private
TypeInfo
type
;
private
int
dataType
;
private
Connection
userConnection
;
...
...
@@ -76,7 +78,12 @@ public class JavaAggregate extends AbstractAggregate {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
type
;
}
@Override
public
int
getValueType
()
{
return
dataType
;
}
...
...
@@ -122,12 +129,13 @@ public class JavaAggregate extends AbstractAggregate {
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
Expression
expr
=
args
[
i
];
args
[
i
]
=
expr
.
optimize
(
session
);
int
type
=
expr
.
getType
();
int
type
=
expr
.
get
Value
Type
();
argTypes
[
i
]
=
type
;
}
try
{
Aggregate
aggregate
=
getInstance
();
dataType
=
aggregate
.
getInternalType
(
argTypes
);
type
=
TypeInfo
.
getTypeInfo
(
dataType
);
}
catch
(
SQLException
e
)
{
throw
DbException
.
convert
(
e
);
}
...
...
h2/src/main/org/h2/expression/analysis/WindowFunction.java
浏览文件 @
473d3d9c
...
...
@@ -16,6 +16,7 @@ import org.h2.expression.Expression;
import
org.h2.message.DbException
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDouble
;
import
org.h2.value.ValueLong
;
...
...
@@ -286,7 +287,7 @@ public class WindowFunction extends DataAnalysisOperation {
int
rowIdColumn
)
{
int
size
=
ordered
.
size
();
int
numExpressions
=
getNumExpressions
();
int
dataType
=
args
[
0
].
getType
();
int
dataType
=
args
[
0
].
get
Value
Type
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
Value
[]
row
=
ordered
.
get
(
i
);
int
rowId
=
row
[
rowIdColumn
].
getInt
();
...
...
@@ -475,7 +476,30 @@ public class WindowFunction extends DataAnalysisOperation {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
switch
(
type
)
{
case
ROW_NUMBER:
case
RANK:
case
DENSE_RANK:
case
NTILE:
return
TypeInfo
.
TYPE_LONG
;
case
PERCENT_RANK:
case
CUME_DIST:
case
RATIO_TO_REPORT:
return
TypeInfo
.
TYPE_DOUBLE
;
case
LEAD:
case
LAG:
case
FIRST_VALUE:
case
LAST_VALUE:
case
NTH_VALUE:
return
args
[
0
].
getType
();
default
:
throw
DbException
.
throwInternalError
(
"type="
+
type
);
}
}
@Override
public
int
getValueType
()
{
switch
(
type
)
{
case
ROW_NUMBER:
case
RANK:
...
...
@@ -491,7 +515,7 @@ public class WindowFunction extends DataAnalysisOperation {
case
FIRST_VALUE:
case
LAST_VALUE:
case
NTH_VALUE:
return
args
[
0
].
getType
();
return
args
[
0
].
get
Value
Type
();
default
:
throw
DbException
.
throwInternalError
(
"type="
+
type
);
}
...
...
h2/src/main/org/h2/expression/condition/CompareLike.java
浏览文件 @
473d3d9c
...
...
@@ -100,7 +100,7 @@ public class CompareLike extends Condition {
public
Expression
optimize
(
Session
session
)
{
left
=
left
.
optimize
(
session
);
right
=
right
.
optimize
(
session
);
if
(
left
.
getType
()
==
Value
.
STRING_IGNORECASE
)
{
if
(
left
.
get
Value
Type
()
==
Value
.
STRING_IGNORECASE
)
{
ignoreCase
=
true
;
}
if
(
left
.
isValueSet
())
{
...
...
h2/src/main/org/h2/expression/condition/Comparison.java
浏览文件 @
473d3d9c
...
...
@@ -206,7 +206,7 @@ public class Comparison extends Condition {
if
(
right
!=
null
)
{
right
=
right
.
optimize
(
session
);
// TODO check row values too
if
(
right
.
get
Type
()
==
Value
.
ARRAY
&&
left
.
get
Type
()
!=
Value
.
ARRAY
)
{
if
(
right
.
get
ValueType
()
==
Value
.
ARRAY
&&
left
.
getValue
Type
()
!=
Value
.
ARRAY
)
{
throw
DbException
.
get
(
ErrorCode
.
COMPARING_ARRAY_TO_SCALAR
);
}
if
(
right
instanceof
ExpressionColumn
)
{
...
...
@@ -225,7 +225,7 @@ public class Comparison extends Condition {
return
ValueExpression
.
getNull
();
}
}
int
colType
=
left
.
getType
();
int
colType
=
left
.
get
Value
Type
();
int
constType
=
r
.
getValueType
();
int
resType
=
Value
.
getHigherOrder
(
colType
,
constType
);
// If not, the column values will need to be promoted
...
...
@@ -516,12 +516,12 @@ public class Comparison extends Condition {
}
if
(
addIndex
)
{
if
(
l
!=
null
)
{
if
(
l
.
get
Type
()
==
right
.
getType
()
||
right
.
get
Type
()
!=
Value
.
STRING_IGNORECASE
)
{
if
(
l
.
get
ValueType
()
==
right
.
getValueType
()
||
right
.
getValue
Type
()
!=
Value
.
STRING_IGNORECASE
)
{
filter
.
addIndexCondition
(
IndexCondition
.
get
(
compareType
,
l
,
right
));
}
}
else
if
(
r
!=
null
)
{
if
(
r
.
get
Type
()
==
left
.
getType
()
||
left
.
get
Type
()
!=
Value
.
STRING_IGNORECASE
)
{
if
(
r
.
get
ValueType
()
==
left
.
getValueType
()
||
left
.
getValue
Type
()
!=
Value
.
STRING_IGNORECASE
)
{
int
compareRev
=
getReversedCompareType
(
compareType
);
filter
.
addIndexCondition
(
IndexCondition
.
get
(
compareRev
,
r
,
left
));
...
...
h2/src/main/org/h2/expression/condition/Condition.java
浏览文件 @
473d3d9c
...
...
@@ -6,6 +6,7 @@
package
org
.
h2
.
expression
.
condition
;
import
org.h2.expression.Expression
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueBoolean
;
...
...
@@ -15,7 +16,12 @@ import org.h2.value.ValueBoolean;
abstract
class
Condition
extends
Expression
{
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
TypeInfo
.
TYPE_BOOLEAN
;
}
@Override
public
int
getValueType
()
{
return
Value
.
BOOLEAN
;
}
...
...
h2/src/main/org/h2/expression/condition/ConditionIn.java
浏览文件 @
473d3d9c
...
...
@@ -150,7 +150,7 @@ public class ConditionIn extends Condition {
return
new
Comparison
(
session
,
Comparison
.
EQUAL
,
left
,
values
.
get
(
0
)).
optimize
(
session
);
}
if
(
allValuesConstant
&&
!
allValuesNull
)
{
int
leftType
=
left
.
getType
();
int
leftType
=
left
.
get
Value
Type
();
if
(
leftType
==
Value
.
UNKNOWN
)
{
return
this
;
}
...
...
h2/src/main/org/h2/expression/condition/ConditionInConstantSet.java
浏览文件 @
473d3d9c
...
...
@@ -54,7 +54,7 @@ public class ConditionInConstantSet extends Condition {
this
.
valueList
=
valueList
;
Database
database
=
session
.
getDatabase
();
this
.
valueSet
=
new
TreeSet
<>(
database
.
getCompareMode
());
type
=
left
.
getType
();
type
=
left
.
get
Value
Type
();
Mode
mode
=
database
.
getMode
();
if
(
type
==
Value
.
ENUM
)
{
extTypeInfo
=
((
ExpressionColumn
)
left
).
getColumn
().
getType
().
getExtTypeInfo
();
...
...
h2/src/main/org/h2/expression/function/Function.java
浏览文件 @
473d3d9c
差异被折叠。
点击展开。
h2/src/main/org/h2/expression/function/FunctionCall.java
浏览文件 @
473d3d9c
...
...
@@ -36,7 +36,7 @@ public interface FunctionCall {
*
* @return the data type
*/
int
getType
();
int
get
Value
Type
();
/**
* Optimize the function if possible.
...
...
h2/src/main/org/h2/expression/function/JavaFunction.java
浏览文件 @
473d3d9c
...
...
@@ -15,6 +15,7 @@ import org.h2.expression.ValueExpression;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.DataType
;
import
org.h2.value.TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueArray
;
import
org.h2.value.ValueNull
;
...
...
@@ -41,7 +42,12 @@ public class JavaFunction extends Expression implements FunctionCall {
}
@Override
public
int
getType
()
{
public
TypeInfo
getType
()
{
return
TypeInfo
.
getTypeInfo
(
javaMethod
.
getDataType
());
}
@Override
public
int
getValueType
()
{
return
javaMethod
.
getDataType
();
}
...
...
@@ -77,7 +83,7 @@ public class JavaFunction extends Expression implements FunctionCall {
@Override
public
int
getScale
()
{
return
DataType
.
getDataType
(
getType
()).
defaultScale
;
return
DataType
.
getDataType
(
get
Value
Type
()).
defaultScale
;
}
@Override
...
...
@@ -166,7 +172,7 @@ public class JavaFunction extends Expression implements FunctionCall {
@Override
public
Expression
[]
getExpressionColumns
(
Session
session
)
{
switch
(
getType
())
{
switch
(
get
Value
Type
())
{
case
Value
.
RESULT_SET
:
ValueResultSet
rs
=
getValueForColumnList
(
session
,
getArgs
());
return
getExpressionColumns
(
session
,
rs
.
getResult
());
...
...
h2/src/main/org/h2/jdbc/JdbcParameterMetaData.java
浏览文件 @
473d3d9c
...
...
@@ -81,7 +81,7 @@ public class JdbcParameterMetaData extends TraceObject implements
try
{
debugCodeCall
(
"getParameterType"
,
param
);
ParameterInterface
p
=
getParameter
(
param
);
int
type
=
p
.
getType
();
int
type
=
p
.
get
Value
Type
();
if
(
type
==
Value
.
UNKNOWN
)
{
type
=
Value
.
STRING
;
}
...
...
@@ -174,7 +174,7 @@ public class JdbcParameterMetaData extends TraceObject implements
try
{
debugCodeCall
(
"getParameterClassName"
,
param
);
ParameterInterface
p
=
getParameter
(
param
);
int
type
=
p
.
getType
();
int
type
=
p
.
get
Value
Type
();
if
(
type
==
Value
.
UNKNOWN
)
{
type
=
Value
.
STRING
;
}
...
...
@@ -196,7 +196,7 @@ public class JdbcParameterMetaData extends TraceObject implements
try
{
debugCodeCall
(
"getParameterTypeName"
,
param
);
ParameterInterface
p
=
getParameter
(
param
);
int
type
=
p
.
getType
();
int
type
=
p
.
get
Value
Type
();
if
(
type
==
Value
.
UNKNOWN
)
{
type
=
Value
.
STRING
;
}
...
...
h2/src/main/org/h2/mode/FunctionsMySQL.java
浏览文件 @
473d3d9c
...
...
@@ -19,7 +19,7 @@ import org.h2.expression.function.Function;
import
org.h2.expression.function.FunctionInfo
;
import
org.h2.message.DbException
;
import
org.h2.util.StringUtils
;
import
org.h2.value.
DataType
;
import
org.h2.value.
TypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.ValueInt
;
import
org.h2.value.ValueNull
;
...
...
@@ -203,10 +203,7 @@ public class FunctionsMySQL extends FunctionsBase {
return
ValueExpression
.
get
(
getValue
(
session
));
}
dataType
=
info
.
returnDataType
;
DataType
dt
=
DataType
.
getDataType
(
dataType
);
precision
=
dt
.
defaultPrecision
;
scale
=
dt
.
defaultScale
;
displaySize
=
dt
.
defaultDisplaySize
;
type
=
TypeInfo
.
getTypeInfo
(
dataType
);
return
this
;
}
...
...
h2/src/main/org/h2/result/LazyResult.java
浏览文件 @
473d3d9c
...
...
@@ -140,7 +140,7 @@ public abstract class LazyResult implements ResultInterface {
@Override
public
int
getColumnType
(
int
i
)
{
return
expressions
[
i
].
getType
();
return
expressions
[
i
].
get
Value
Type
();
}
@Override
...
...
h2/src/main/org/h2/result/LocalResultImpl.java
浏览文件 @
473d3d9c
...
...
@@ -539,7 +539,7 @@ public class LocalResultImpl implements LocalResult {
@Override
public
int
getColumnType
(
int
i
)
{
return
expressions
[
i
].
getType
();
return
expressions
[
i
].
get
Value
Type
();
}
@Override
...
...
h2/src/main/org/h2/result/ResultTempTable.java
浏览文件 @
473d3d9c
...
...
@@ -117,7 +117,7 @@ public class ResultTempTable implements ResultExternal {
CreateTableData
data
=
new
CreateTableData
();
boolean
containsLob
=
false
;
for
(
int
i
=
0
;
i
<
expressions
.
length
;
i
++)
{
int
type
=
expressions
[
i
].
getType
();
int
type
=
expressions
[
i
].
get
Value
Type
();
Column
col
=
new
Column
(
COLUMN_NAME
+
i
,
type
);
if
(
DataType
.
isLargeObject
(
type
))
{
containsLob
=
true
;
...
...
h2/src/main/org/h2/table/FunctionTable.java
浏览文件 @
473d3d9c
...
...
@@ -45,7 +45,7 @@ public class FunctionTable extends Table {
rowCount
=
Long
.
MAX_VALUE
;
}
function
.
optimize
(
session
);
int
type
=
function
.
getType
();
int
type
=
function
.
get
Value
Type
();
if
(
type
!=
Value
.
RESULT_SET
)
{
throw
DbException
.
get
(
ErrorCode
.
FUNCTION_MUST_RETURN_RESULT_SET_1
,
function
.
getName
());
...
...
h2/src/main/org/h2/table/MetaTable.java
浏览文件 @
473d3d9c
...
...
@@ -1762,7 +1762,7 @@ public class MetaTable extends Table {
// CONSTANT_NAME
identifier
(
constant
.
getName
()),
// DATA_TYPE
ValueInt
.
get
(
DataType
.
convertTypeToSQLType
(
expr
.
getType
())),
ValueInt
.
get
(
DataType
.
convertTypeToSQLType
(
expr
.
get
Value
Type
())),
// REMARKS
replaceNullWithEmpty
(
constant
.
getComment
()),
// SQL
...
...
h2/src/main/org/h2/table/TableView.java
浏览文件 @
473d3d9c
...
...
@@ -191,7 +191,7 @@ public class TableView extends Table {
}
name
=
columnNamer
.
getColumnName
(
expr
,
i
,
name
);
if
(
type
==
Value
.
UNKNOWN
)
{
type
=
expr
.
getType
();
type
=
expr
.
get
Value
Type
();
}
long
precision
=
expr
.
getPrecision
();
int
scale
=
expr
.
getScale
();
...
...
@@ -818,7 +818,7 @@ public class TableView extends Table {
// expression
String
columnName
=
columnNamer
.
getColumnName
(
columnExp
,
i
,
cols
);
columnTemplateList
.
add
(
new
Column
(
columnName
,
columnExp
.
getType
()));
columnExp
.
get
Value
Type
()));
}
return
columnTemplateList
;
...
...
h2/src/main/org/h2/value/DataType.java
浏览文件 @
473d3d9c
...
...
@@ -377,6 +377,7 @@ public class DataType {
32
);
dataType
=
new
DataType
();
dataType
.
maxPrecision
=
dataType
.
defaultPrecision
=
dataType
.
defaultDisplaySize
=
Integer
.
MAX_VALUE
;
add
(
Value
.
RESULT_SET
,
DataType
.
TYPE_RESULT_SET
,
dataType
,
new
String
[]{
"RESULT_SET"
},
...
...
h2/src/main/org/h2/value/TypeInfo.java
浏览文件 @
473d3d9c
...
...
@@ -8,12 +8,18 @@ package org.h2.value;
import
org.h2.api.ErrorCode
;
import
org.h2.message.DbException
;
import
org.h2.util.JdbcUtils
;
import
org.h2.util.MathUtils
;
/**
* Data type with parameters.
*/
public
class
TypeInfo
{
/**
* UNKNOWN type with parameters.
*/
public
static
final
TypeInfo
TYPE_UNKNOWN
;
/**
* NULL type with parameters.
*/
...
...
@@ -44,6 +50,11 @@ public class TypeInfo {
*/
public
static
final
TypeInfo
TYPE_LONG
;
/**
* DECIMAL type with default parameters.
*/
public
static
final
TypeInfo
TYPE_DECIMAL_DEFAULT
;
/**
* DOUBLE type with parameters.
*/
...
...
@@ -69,6 +80,11 @@ public class TypeInfo {
*/
public
static
final
TypeInfo
TYPE_TIMESTAMP
;
/**
* STRING type with default parameters.
*/
public
static
final
TypeInfo
TYPE_STRING_DEFAULT
;
/**
* ARRAY type with parameters.
*/
...
...
@@ -104,6 +120,21 @@ public class TypeInfo {
*/
public
static
final
TypeInfo
TYPE_ENUM_UNDEFINED
;
/**
* INTERVAL DAY type with parameters.
*/
public
static
final
TypeInfo
TYPE_INTERVAL_DAY
;
/**
* INTERVAL DAY TO SECOND type with parameters.
*/
public
static
final
TypeInfo
TYPE_INTERVAL_DAY_TO_SECOND
;
/**
* INTERVAL HOUR TO SECOND type with parameters.
*/
public
static
final
TypeInfo
TYPE_INTERVAL_HOUR_TO_SECOND
;
/**
* ROW (row value) type with parameters.
*/
...
...
@@ -131,17 +162,20 @@ public class TypeInfo {
infos
[
i
]
=
createTypeInfo
(
i
,
dt
);
}
}
TYPE_UNKNOWN
=
new
TypeInfo
(
Value
.
UNKNOWN
,
-
1L
,
-
1
,
-
1
,
null
);
TYPE_NULL
=
infos
[
Value
.
NULL
];
TYPE_BOOLEAN
=
infos
[
Value
.
BOOLEAN
];
TYPE_BYTE
=
infos
[
Value
.
BYTE
];
TYPE_SHORT
=
infos
[
Value
.
SHORT
];
TYPE_INT
=
infos
[
Value
.
INT
];
TYPE_LONG
=
infos
[
Value
.
LONG
];
TYPE_DECIMAL_DEFAULT
=
infos
[
Value
.
DECIMAL
];
TYPE_DOUBLE
=
infos
[
Value
.
DOUBLE
];
TYPE_FLOAT
=
infos
[
Value
.
FLOAT
];
TYPE_TIME
=
infos
[
Value
.
TIME
];
TYPE_DATE
=
infos
[
Value
.
DATE
];
TYPE_TIMESTAMP
=
infos
[
Value
.
TIMESTAMP
];
TYPE_STRING_DEFAULT
=
infos
[
Value
.
STRING
];
TYPE_ARRAY
=
infos
[
Value
.
ARRAY
];
TYPE_RESULT_SET
=
infos
[
Value
.
RESULT_SET
];
TYPE_JAVA_OBJECT
=
infos
[
Value
.
JAVA_OBJECT
];
...
...
@@ -149,6 +183,9 @@ public class TypeInfo {
TYPE_GEOMETRY
=
infos
[
Value
.
GEOMETRY
];
TYPE_TIMESTAMP_TZ
=
infos
[
Value
.
TIMESTAMP_TZ
];
TYPE_ENUM_UNDEFINED
=
infos
[
Value
.
ENUM
];
TYPE_INTERVAL_DAY
=
infos
[
Value
.
INTERVAL_DAY
];
TYPE_INTERVAL_DAY_TO_SECOND
=
infos
[
Value
.
INTERVAL_DAY_TO_SECOND
];
TYPE_INTERVAL_HOUR_TO_SECOND
=
infos
[
Value
.
INTERVAL_HOUR_TO_SECOND
];
TYPE_ROW
=
infos
[
Value
.
ROW
];
TYPE_INFOS_BY_VALUE_TYPE
=
infos
;
}
...
...
@@ -157,7 +194,8 @@ public class TypeInfo {
* Get the data type with parameters object for the given value type and
* maximum parameters.
*
* @param type the value type
* @param type
* the value type
* @return the data type with parameters object
*/
public
static
TypeInfo
getTypeInfo
(
int
type
)
{
...
...
@@ -165,7 +203,7 @@ public class TypeInfo {
throw
DbException
.
get
(
ErrorCode
.
UNKNOWN_DATA_TYPE_1
,
"?"
);
}
if
(
type
>=
Value
.
NULL
&&
type
<
Value
.
TYPE_COUNT
)
{
TypeInfo
t
=
T
ypeInfo
.
T
YPE_INFOS_BY_VALUE_TYPE
[
type
];
TypeInfo
t
=
TYPE_INFOS_BY_VALUE_TYPE
[
type
];
if
(
t
!=
null
)
{
return
t
;
}
...
...
@@ -176,7 +214,126 @@ public class TypeInfo {
return
createTypeInfo
(
type
,
dt
);
}
}
return
TypeInfo
.
TYPE_INFOS_BY_VALUE_TYPE
[
Value
.
NULL
];
return
TYPE_NULL
;
}
/**
* Get the data type with parameters object for the given value type and the
* specified parameters.
*
* @param type
* the value type
* @param precision
* the precision
* @param scale
* the scale
* @param displaySize
* the display size in characters
* @param extTypeInfo
* the extended type information, or null
* @return the data type with parameters object
*/
public
static
TypeInfo
getTypeInfo
(
int
type
,
long
precision
,
int
scale
,
int
displaySize
,
ExtTypeInfo
extTypeInfo
)
{
switch
(
type
)
{
case
Value
.
NULL
:
case
Value
.
BOOLEAN
:
case
Value
.
BYTE
:
case
Value
.
SHORT
:
case
Value
.
INT
:
case
Value
.
DOUBLE
:
case
Value
.
FLOAT
:
case
Value
.
DATE
:
case
Value
.
ARRAY
:
case
Value
.
RESULT_SET
:
case
Value
.
JAVA_OBJECT
:
case
Value
.
UUID
:
case
Value
.
ROW
:
return
TYPE_INFOS_BY_VALUE_TYPE
[
type
];
case
Value
.
UNKNOWN
:
return
TYPE_UNKNOWN
;
case
Value
.
DECIMAL
:
if
(
precision
<
0
)
{
precision
=
ValueDecimal
.
DEFAULT_PRECISION
;
}
if
(
scale
<
0
)
{
scale
=
ValueDecimal
.
DEFAULT_SCALE
;
}
return
new
TypeInfo
(
Value
.
DECIMAL
,
precision
,
scale
,
MathUtils
.
convertLongToInt
(
precision
+
2
),
null
);
case
Value
.
TIME
:
if
(
scale
<
0
||
scale
>=
ValueTime
.
MAXIMUM_SCALE
)
{
return
TYPE_TIME
;
}
return
new
TypeInfo
(
Value
.
TIME
,
ValueTime
.
MAXIMUM_PRECISION
,
scale
,
ValueTime
.
DEFAULT_PRECISION
,
null
);
case
Value
.
TIMESTAMP
:
if
(
scale
<
0
||
scale
>=
ValueTimestamp
.
MAXIMUM_SCALE
)
{
return
TYPE_TIMESTAMP
;
}
return
new
TypeInfo
(
Value
.
TIMESTAMP
,
ValueTimestamp
.
MAXIMUM_PRECISION
,
scale
,
ValueTimestamp
.
MAXIMUM_PRECISION
,
null
);
case
Value
.
TIMESTAMP_TZ
:
if
(
scale
<
0
||
scale
>=
ValueTimestampTimeZone
.
MAXIMUM_SCALE
)
{
return
TYPE_TIMESTAMP_TZ
;
}
return
new
TypeInfo
(
Value
.
TIMESTAMP_TZ
,
ValueTimestampTimeZone
.
MAXIMUM_PRECISION
,
scale
,
ValueTimestampTimeZone
.
MAXIMUM_PRECISION
,
null
);
case
Value
.
BYTES
:
if
(
precision
<
0
)
{
precision
=
Integer
.
MAX_VALUE
;
}
return
new
TypeInfo
(
Value
.
BYTES
,
precision
,
scale
,
MathUtils
.
convertLongToInt
(
precision
)
*
2
,
null
);
case
Value
.
STRING
:
if
(
precision
<
0
)
{
return
TYPE_STRING_DEFAULT
;
}
//$FALL-THROUGH$
case
Value
.
STRING_FIXED
:
case
Value
.
STRING_IGNORECASE
:
case
Value
.
BLOB
:
case
Value
.
CLOB
:
return
new
TypeInfo
(
type
,
precision
,
0
,
MathUtils
.
convertLongToInt
(
precision
),
null
);
case
Value
.
GEOMETRY
:
if
(
extTypeInfo
==
null
)
{
return
TYPE_GEOMETRY
;
}
return
new
TypeInfo
(
Value
.
GEOMETRY
,
Integer
.
MAX_VALUE
,
0
,
Integer
.
MAX_VALUE
,
extTypeInfo
);
case
Value
.
ENUM
:
if
(
extTypeInfo
==
null
)
{
return
TYPE_ENUM_UNDEFINED
;
}
return
new
TypeInfo
(
Value
.
ENUM
,
ValueEnum
.
PRECISION
,
0
,
ValueEnum
.
DISPLAY_SIZE
,
extTypeInfo
);
case
Value
.
INTERVAL_YEAR
:
case
Value
.
INTERVAL_MONTH
:
case
Value
.
INTERVAL_DAY
:
case
Value
.
INTERVAL_HOUR
:
case
Value
.
INTERVAL_MINUTE
:
case
Value
.
INTERVAL_YEAR_TO_MONTH
:
case
Value
.
INTERVAL_DAY_TO_HOUR
:
case
Value
.
INTERVAL_DAY_TO_MINUTE
:
case
Value
.
INTERVAL_HOUR_TO_MINUTE
:
if
(
precision
<
0
||
precision
>
ValueInterval
.
MAXIMUM_PRECISION
)
{
precision
=
ValueInterval
.
MAXIMUM_PRECISION
;
}
return
new
TypeInfo
(
type
,
precision
,
0
,
ValueInterval
.
getDisplaySize
(
type
,
(
int
)
precision
,
0
),
null
);
case
Value
.
INTERVAL_SECOND
:
case
Value
.
INTERVAL_DAY_TO_SECOND
:
case
Value
.
INTERVAL_HOUR_TO_SECOND
:
case
Value
.
INTERVAL_MINUTE_TO_SECOND
:
if
(
precision
<
0
||
precision
>
ValueInterval
.
MAXIMUM_PRECISION
)
{
precision
=
ValueInterval
.
MAXIMUM_PRECISION
;
}
if
(
scale
<
0
||
scale
>
ValueInterval
.
MAXIMUM_SCALE
)
{
scale
=
ValueInterval
.
MAXIMUM_SCALE
;
}
return
new
TypeInfo
(
type
,
precision
,
scale
,
ValueInterval
.
getDisplaySize
(
type
,
(
int
)
precision
,
scale
),
null
);
}
if
(
JdbcUtils
.
customDataTypesHandler
!=
null
)
{
DataType
dt
=
JdbcUtils
.
customDataTypesHandler
.
getDataTypeById
(
type
);
if
(
dt
!=
null
)
{
return
createTypeInfo
(
type
,
dt
);
}
}
return
TYPE_NULL
;
}
private
static
TypeInfo
createTypeInfo
(
int
valueType
,
DataType
dataType
)
{
...
...
h2/src/main/org/h2/value/ValueArray.java
浏览文件 @
473d3d9c
...
...
@@ -61,11 +61,6 @@ public class ValueArray extends ValueCollectionBase {
return
(
ValueArray
)
EMPTY
;
}
@Override
public
TypeInfo
getType
()
{
return
TypeInfo
.
TYPE_ARRAY
;
}
@Override
public
int
getValueType
()
{
return
ARRAY
;
...
...
h2/src/main/org/h2/value/ValueRow.java
浏览文件 @
473d3d9c
...
...
@@ -47,11 +47,6 @@ public class ValueRow extends ValueCollectionBase {
return
(
ValueRow
)
EMPTY
;
}
@Override
public
TypeInfo
getType
()
{
return
TypeInfo
.
TYPE_ROW
;
}
@Override
public
int
getValueType
()
{
return
ROW
;
...
...
h2/src/test/org/h2/test/unit/TestDate.java
浏览文件 @
473d3d9c
...
...
@@ -143,7 +143,7 @@ public class TestDate extends TestBase {
assertEquals
((
int
)
((
nanos
>>>
32
)
^
nanos
),
t1
.
hashCode
());
// Literals return maximum precision
TypeInfo
type
=
t1
.
getType
();
assertEquals
(
ValueTime
.
MAXIMUM
_PRECISION
,
type
.
getDisplaySize
());
assertEquals
(
ValueTime
.
DEFAULT
_PRECISION
,
type
.
getDisplaySize
());
assertEquals
(
ValueTime
.
MAXIMUM_PRECISION
,
type
.
getPrecision
());
assertEquals
(
"java.sql.Time"
,
t1
.
getObject
().
getClass
().
getName
());
ValueTime
t1b
=
ValueTime
.
parse
(
"11:11:11"
);
...
...
@@ -221,7 +221,7 @@ public class TestDate extends TestBase {
t1
.
hashCode
());
// Literals return maximum precision
TypeInfo
type
=
t1
.
getType
();
assertEquals
(
ValueTimestamp
.
MAXIMUM
_PRECISION
,
type
.
getDisplaySize
());
assertEquals
(
ValueTimestamp
.
DEFAULT
_PRECISION
,
type
.
getDisplaySize
());
assertEquals
(
ValueTimestamp
.
MAXIMUM_PRECISION
,
type
.
getPrecision
());
assertEquals
(
9
,
type
.
getScale
());
assertEquals
(
"java.sql.Timestamp"
,
t1
.
getObject
().
getClass
().
getName
());
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论