Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
18a3b3c2
提交
18a3b3c2
authored
15 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
An optimization for IN(..) and IN(SELECT...) using the system property h2.optimizeInList
上级
284e2b74
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
451 行增加
和
129 行删除
+451
-129
Parser.java
h2/src/main/org/h2/command/Parser.java
+1
-1
SysProperties.java
h2/src/main/org/h2/constant/SysProperties.java
+8
-0
CompareLike.java
h2/src/main/org/h2/expression/CompareLike.java
+3
-3
Comparison.java
h2/src/main/org/h2/expression/Comparison.java
+14
-2
ConditionIn.java
h2/src/main/org/h2/expression/ConditionIn.java
+43
-31
ConditionInSelect.java
h2/src/main/org/h2/expression/ConditionInSelect.java
+25
-2
ExpressionColumn.java
h2/src/main/org/h2/expression/ExpressionColumn.java
+1
-1
ValueExpression.java
h2/src/main/org/h2/expression/ValueExpression.java
+1
-1
IndexCondition.java
h2/src/main/org/h2/index/IndexCondition.java
+125
-9
IndexCursor.java
h2/src/main/org/h2/index/IndexCursor.java
+207
-0
MetaTable.java
h2/src/main/org/h2/table/MetaTable.java
+1
-0
TableFilter.java
h2/src/main/org/h2/table/TableFilter.java
+22
-79
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
18a3b3c2
...
...
@@ -1715,7 +1715,7 @@ public class Parser {
read
(
"NULL"
);
r
=
new
Comparison
(
session
,
type
,
r
,
null
);
}
else
if
(
readIf
(
"IN"
))
{
if
(
SysProperties
.
OPTIMIZE_IN
)
{
if
(
SysProperties
.
OPTIMIZE_IN
&&
!
SysProperties
.
OPTIMIZE_IN_LIST
)
{
recompileAlways
=
true
;
}
read
(
"("
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/constant/SysProperties.java
浏览文件 @
18a3b3c2
...
...
@@ -437,6 +437,14 @@ public class SysProperties {
*/
public
static
final
boolean
OPTIMIZE_IN
=
getBooleanSetting
(
"h2.optimizeIn"
,
true
);
/**
* System property <code>h2.optimizeInList</code> (default: false).<br />
* Optimize IN(...) and IN(SELECT ...) comparisons. This includes
* optimization for SELECT, DELETE, and UPDATE. Overrides h2.optimizeIn and
* h2.optimizeInJoin if enabled.
*/
public
static
final
boolean
OPTIMIZE_IN_LIST
=
getBooleanSetting
(
"h2.optimizeInList"
,
false
);
/**
* System property <code>h2.optimizeInJoin</code> (default: false).<br />
* Optimize IN(...) comparisons by converting them to inner joins.
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/CompareLike.java
浏览文件 @
18a3b3c2
...
...
@@ -174,14 +174,14 @@ public class CompareLike extends Condition {
}
String
begin
=
buff
.
toString
();
if
(
maxMatch
==
patternLength
)
{
filter
.
addIndexCondition
(
new
IndexCondition
(
Comparison
.
EQUAL
,
l
,
ValueExpression
filter
.
addIndexCondition
(
IndexCondition
.
get
(
Comparison
.
EQUAL
,
l
,
ValueExpression
.
get
(
ValueString
.
get
(
begin
))));
}
else
{
// TODO check if this is correct according to Unicode rules (code
// points)
String
end
;
if
(
begin
.
length
()
>
0
)
{
filter
.
addIndexCondition
(
new
IndexCondition
(
Comparison
.
BIGGER_EQUAL
,
l
,
ValueExpression
.
get
(
ValueString
filter
.
addIndexCondition
(
IndexCondition
.
get
(
Comparison
.
BIGGER_EQUAL
,
l
,
ValueExpression
.
get
(
ValueString
.
get
(
begin
))));
char
next
=
begin
.
charAt
(
begin
.
length
()
-
1
);
// search the 'next' unicode character (or at least a character
...
...
@@ -189,7 +189,7 @@ public class CompareLike extends Condition {
for
(
int
i
=
1
;
i
<
2000
;
i
++)
{
end
=
begin
.
substring
(
0
,
begin
.
length
()
-
1
)
+
(
char
)
(
next
+
i
);
if
(
compareMode
.
compareString
(
begin
,
end
,
ignoreCase
)
==
-
1
)
{
filter
.
addIndexCondition
(
new
IndexCondition
(
Comparison
.
SMALLER
,
l
,
ValueExpression
filter
.
addIndexCondition
(
IndexCondition
.
get
(
Comparison
.
SMALLER
,
l
,
ValueExpression
.
get
(
ValueString
.
get
(
end
))));
break
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/Comparison.java
浏览文件 @
18a3b3c2
...
...
@@ -71,6 +71,18 @@ public class Comparison extends Condition {
*/
public
static
final
int
FALSE
=
8
;
/**
* This is a pseudo comparison type that is only used for index conditions.
* It means equals any value of a list. Example: IN(1, 2, 3).
*/
public
static
final
int
IN_LIST
=
9
;
/**
* This is a pseudo comparison type that is only used for index conditions.
* It means equals any value of a list. Example: IN(SELECT ...).
*/
public
static
final
int
IN_QUERY
=
10
;
private
final
Database
database
;
private
final
int
compareType
;
private
Expression
left
;
...
...
@@ -366,10 +378,10 @@ public class Comparison extends Condition {
}
if
(
addIndex
)
{
if
(
l
!=
null
)
{
filter
.
addIndexCondition
(
new
IndexCondition
(
compareType
,
l
,
right
));
filter
.
addIndexCondition
(
IndexCondition
.
get
(
compareType
,
l
,
right
));
}
else
if
(
r
!=
null
)
{
int
compareRev
=
getReversedCompareType
(
compareType
);
filter
.
addIndexCondition
(
new
IndexCondition
(
compareRev
,
r
,
left
));
filter
.
addIndexCondition
(
IndexCondition
.
get
(
compareRev
,
r
,
left
));
}
}
return
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/ConditionIn.java
浏览文件 @
18a3b3c2
...
...
@@ -7,7 +7,6 @@
package
org
.
h2
.
expression
;
import
java.sql.SQLException
;
import
org.h2.command.dml.Select
;
import
org.h2.constant.SysProperties
;
import
org.h2.engine.Constants
;
...
...
@@ -34,19 +33,19 @@ public class ConditionIn extends Condition {
private
final
Database
database
;
private
Expression
left
;
private
final
ObjectArray
<
Expression
>
value
s
;
private
final
ObjectArray
<
Expression
>
value
List
;
private
Value
min
,
max
;
private
int
queryLevel
;
public
ConditionIn
(
Database
database
,
Expression
left
,
ObjectArray
<
Expression
>
values
)
{
this
.
database
=
database
;
this
.
left
=
left
;
this
.
value
s
=
values
;
this
.
value
List
=
values
;
}
public
Value
getValue
(
Session
session
)
throws
SQLException
{
Value
l
=
left
.
getValue
(
session
);
if
(
value
s
.
size
()
==
0
)
{
if
(
value
List
.
size
()
==
0
)
{
return
ValueBoolean
.
get
(
false
);
}
if
(
l
==
ValueNull
.
INSTANCE
)
{
...
...
@@ -54,11 +53,12 @@ public class ConditionIn extends Condition {
}
boolean
result
=
false
;
boolean
hasNull
=
false
;
for
(
Expression
e
:
value
s
)
{
for
(
Expression
e
:
value
List
)
{
Value
r
=
e
.
getValue
(
session
);
if
(
r
==
ValueNull
.
INSTANCE
)
{
hasNull
=
true
;
}
else
{
r
=
r
.
convertTo
(
l
.
getType
());
result
=
Comparison
.
compareNotNull
(
database
,
l
,
r
,
Comparison
.
EQUAL
);
if
(
result
)
{
break
;
...
...
@@ -73,14 +73,14 @@ public class ConditionIn extends Condition {
public
void
mapColumns
(
ColumnResolver
resolver
,
int
queryLevel
)
throws
SQLException
{
left
.
mapColumns
(
resolver
,
queryLevel
);
for
(
Expression
e
:
value
s
)
{
for
(
Expression
e
:
value
List
)
{
e
.
mapColumns
(
resolver
,
queryLevel
);
}
this
.
queryLevel
=
Math
.
max
(
queryLevel
,
this
.
queryLevel
);
}
public
Expression
optimize
(
Session
session
)
throws
SQLException
{
if
(
value
s
.
size
()
==
0
)
{
if
(
value
List
.
size
()
==
0
)
{
return
ValueExpression
.
get
(
ValueBoolean
.
get
(
false
));
}
left
=
left
.
optimize
(
session
);
...
...
@@ -89,25 +89,24 @@ public class ConditionIn extends Condition {
return
left
;
}
boolean
allValuesConstant
=
true
;
for
(
int
i
=
0
;
i
<
value
s
.
size
();
i
++)
{
Expression
e
=
value
s
.
get
(
i
);
for
(
int
i
=
0
;
i
<
value
List
.
size
();
i
++)
{
Expression
e
=
value
List
.
get
(
i
);
e
=
e
.
optimize
(
session
);
if
(
allValuesConstant
&&
!
e
.
isConstant
())
{
allValuesConstant
=
false
;
}
value
s
.
set
(
i
,
e
);
value
List
.
set
(
i
,
e
);
}
if
(
constant
&&
allValuesConstant
)
{
return
ValueExpression
.
get
(
getValue
(
session
));
}
// TODO optimization: could use index in some cases (sort, use min and max)
if
(
values
.
size
()
==
1
)
{
Expression
right
=
values
.
get
(
0
);
if
(
valueList
.
size
()
==
1
)
{
Expression
right
=
valueList
.
get
(
0
);
Expression
expr
=
new
Comparison
(
session
,
Comparison
.
EQUAL
,
left
,
right
);
expr
=
expr
.
optimize
(
session
);
return
expr
;
}
if
(
SysProperties
.
OPTIMIZE_IN
)
{
if
(
SysProperties
.
OPTIMIZE_IN
&&
!
SysProperties
.
OPTIMIZE_IN_LIST
)
{
int
dataType
=
left
.
getType
();
ExpressionVisitor
independent
=
ExpressionVisitor
.
get
(
ExpressionVisitor
.
INDEPENDENT
);
independent
.
setQueryLevel
(
queryLevel
);
...
...
@@ -116,11 +115,11 @@ public class ConditionIn extends Condition {
Column
column
=
((
ExpressionColumn
)
left
).
getColumn
();
boolean
nullable
=
column
.
isNullable
();
CompareMode
mode
=
session
.
getDatabase
().
getCompareMode
();
for
(
int
i
=
0
;
i
<
value
s
.
size
();
i
++)
{
Expression
e
=
value
s
.
get
(
i
);
for
(
int
i
=
0
;
i
<
value
List
.
size
();
i
++)
{
Expression
e
=
value
List
.
get
(
i
);
Value
v
=
e
.
getValue
(
session
);
v
=
v
.
convertTo
(
dataType
);
value
s
.
set
(
i
,
ValueExpression
.
get
(
v
));
value
List
.
set
(
i
,
ValueExpression
.
get
(
v
));
if
(
min
==
null
||
min
.
compareTo
(
v
,
mode
)
>
0
)
{
if
(
v
!=
ValueNull
.
INSTANCE
||
nullable
)
{
min
=
v
;
...
...
@@ -137,26 +136,36 @@ public class ConditionIn extends Condition {
}
public
void
createIndexConditions
(
Session
session
,
TableFilter
filter
)
{
if
(!
SysProperties
.
OPTIMIZE_IN
)
{
if
(!
(
left
instanceof
ExpressionColumn
)
)
{
return
;
}
if
(
min
==
null
&&
max
==
null
)
{
ExpressionColumn
l
=
(
ExpressionColumn
)
left
;
if
(
filter
!=
l
.
getTableFilter
())
{
return
;
}
if
(!(
left
instanceof
ExpressionColumn
))
{
if
(
SysProperties
.
OPTIMIZE_IN_LIST
)
{
ExpressionVisitor
visitor
=
ExpressionVisitor
.
get
(
ExpressionVisitor
.
NOT_FROM_RESOLVER
);
visitor
.
setResolver
(
filter
);
for
(
Expression
e
:
valueList
)
{
if
(!
e
.
isEverything
(
visitor
))
{
return
;
}
}
filter
.
addIndexCondition
(
IndexCondition
.
getInList
(
l
,
valueList
));
}
if
(!
SysProperties
.
OPTIMIZE_IN
)
{
return
;
}
ExpressionColumn
l
=
(
ExpressionColumn
)
left
;
if
(
filter
!=
l
.
getTableFilter
())
{
if
(
min
==
null
&&
max
==
null
)
{
return
;
}
filter
.
addIndexCondition
(
new
IndexCondition
(
Comparison
.
BIGGER_EQUAL
,
l
,
ValueExpression
.
get
(
min
)));
filter
.
addIndexCondition
(
new
IndexCondition
(
Comparison
.
SMALLER_EQUAL
,
l
,
ValueExpression
.
get
(
max
)));
filter
.
addIndexCondition
(
IndexCondition
.
get
(
Comparison
.
BIGGER_EQUAL
,
l
,
ValueExpression
.
get
(
min
)));
filter
.
addIndexCondition
(
IndexCondition
.
get
(
Comparison
.
SMALLER_EQUAL
,
l
,
ValueExpression
.
get
(
max
)));
}
public
void
setEvaluatable
(
TableFilter
tableFilter
,
boolean
b
)
{
left
.
setEvaluatable
(
tableFilter
,
b
);
for
(
Expression
e
:
value
s
)
{
for
(
Expression
e
:
value
List
)
{
e
.
setEvaluatable
(
tableFilter
,
b
);
}
}
...
...
@@ -164,7 +173,7 @@ public class ConditionIn extends Condition {
public
String
getSQL
()
{
StatementBuilder
buff
=
new
StatementBuilder
(
"("
);
buff
.
append
(
left
.
getSQL
()).
append
(
" IN("
);
for
(
Expression
e
:
value
s
)
{
for
(
Expression
e
:
value
List
)
{
buff
.
appendExceptFirst
(
", "
);
buff
.
append
(
e
.
getSQL
());
}
...
...
@@ -173,7 +182,7 @@ public class ConditionIn extends Condition {
public
void
updateAggregate
(
Session
session
)
throws
SQLException
{
left
.
updateAggregate
(
session
);
for
(
Expression
e
:
value
s
)
{
for
(
Expression
e
:
value
List
)
{
e
.
updateAggregate
(
session
);
}
}
...
...
@@ -186,7 +195,7 @@ public class ConditionIn extends Condition {
}
private
boolean
areAllValues
(
ExpressionVisitor
visitor
)
{
for
(
Expression
e
:
value
s
)
{
for
(
Expression
e
:
value
List
)
{
if
(!
e
.
isEverything
(
visitor
))
{
return
false
;
}
...
...
@@ -196,13 +205,16 @@ public class ConditionIn extends Condition {
public
int
getCost
()
{
int
cost
=
left
.
getCost
();
for
(
Expression
e
:
value
s
)
{
for
(
Expression
e
:
value
List
)
{
cost
+=
e
.
getCost
();
}
return
cost
;
}
public
Expression
optimizeInJoin
(
Session
session
,
Select
select
)
throws
SQLException
{
if
(
SysProperties
.
OPTIMIZE_IN_LIST
)
{
return
this
;
}
if
(!
areAllValues
(
ExpressionVisitor
.
get
(
ExpressionVisitor
.
EVALUATABLE
)))
{
return
this
;
}
...
...
@@ -219,11 +231,11 @@ public class ConditionIn extends Condition {
}
Database
db
=
session
.
getDatabase
();
Schema
mainSchema
=
db
.
getSchema
(
Constants
.
SCHEMA_MAIN
);
int
rowCount
=
value
s
.
size
();
int
rowCount
=
value
List
.
size
();
TableFunction
function
=
new
TableFunction
(
database
,
Function
.
getFunctionInfo
(
"TABLE_DISTINCT"
),
rowCount
);
Expression
[]
array
=
new
Expression
[
rowCount
];
for
(
int
i
=
0
;
i
<
rowCount
;
i
++)
{
Expression
e
=
value
s
.
get
(
i
);
Expression
e
=
value
List
.
get
(
i
);
array
[
i
]
=
e
;
}
ExpressionList
list
=
new
ExpressionList
(
array
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/ConditionInSelect.java
浏览文件 @
18a3b3c2
...
...
@@ -11,9 +11,11 @@ import java.sql.SQLException;
import
org.h2.command.dml.Query
;
import
org.h2.command.dml.Select
;
import
org.h2.constant.ErrorCode
;
import
org.h2.constant.SysProperties
;
import
org.h2.engine.Database
;
import
org.h2.engine.Session
;
import
org.h2.index.Index
;
import
org.h2.index.IndexCondition
;
import
org.h2.message.Message
;
import
org.h2.result.LocalResult
;
import
org.h2.table.ColumnResolver
;
...
...
@@ -94,8 +96,7 @@ public class ConditionInSelect extends Condition {
if
(
query
.
getColumnCount
()
!=
1
)
{
throw
Message
.
getSQLException
(
ErrorCode
.
SUBQUERY_IS_NOT_SINGLE_COLUMN
);
}
// Can not optimize IN(SELECT...): the data may change
// However, could transform to an inner join
// Can not optimize: the data may change
return
this
;
}
...
...
@@ -125,6 +126,9 @@ public class ConditionInSelect extends Condition {
public
Expression
optimizeInJoin
(
Session
session
,
Select
select
)
throws
SQLException
{
query
.
setDistinct
(
true
);
if
(
SysProperties
.
OPTIMIZE_IN_LIST
)
{
return
this
;
}
if
(
all
||
compareType
!=
Comparison
.
EQUAL
)
{
return
this
;
}
...
...
@@ -157,4 +161,23 @@ public class ConditionInSelect extends Condition {
return
on
;
}
public
void
createIndexConditions
(
Session
session
,
TableFilter
filter
)
{
if
(!
SysProperties
.
OPTIMIZE_IN_LIST
)
{
return
;
}
if
(!(
left
instanceof
ExpressionColumn
))
{
return
;
}
ExpressionColumn
l
=
(
ExpressionColumn
)
left
;
if
(
filter
!=
l
.
getTableFilter
())
{
return
;
}
ExpressionVisitor
visitor
=
ExpressionVisitor
.
get
(
ExpressionVisitor
.
NOT_FROM_RESOLVER
);
visitor
.
setResolver
(
filter
);
if
(!
query
.
isEverything
(
visitor
))
{
return
;
}
filter
.
addIndexCondition
(
IndexCondition
.
getInQuery
(
l
,
query
));
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/ExpressionColumn.java
浏览文件 @
18a3b3c2
...
...
@@ -266,7 +266,7 @@ public class ExpressionColumn extends Expression {
public
void
createIndexConditions
(
Session
session
,
TableFilter
filter
)
{
TableFilter
tf
=
getTableFilter
();
if
(
filter
==
tf
&&
column
.
getType
()
==
Value
.
BOOLEAN
)
{
IndexCondition
cond
=
new
IndexCondition
(
Comparison
.
EQUAL
,
this
,
ValueExpression
IndexCondition
cond
=
IndexCondition
.
get
(
Comparison
.
EQUAL
,
this
,
ValueExpression
.
get
(
ValueBoolean
.
get
(
true
)));
filter
.
addIndexCondition
(
cond
);
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/ValueExpression.java
浏览文件 @
18a3b3c2
...
...
@@ -80,7 +80,7 @@ public class ValueExpression extends Expression {
if
(
value
.
getType
()
==
Value
.
BOOLEAN
)
{
boolean
v
=
((
ValueBoolean
)
value
).
getBoolean
().
booleanValue
();
if
(!
v
)
{
filter
.
addIndexCondition
(
new
IndexCondition
(
Comparison
.
FALSE
,
null
,
this
));
filter
.
addIndexCondition
(
IndexCondition
.
get
(
Comparison
.
FALSE
,
null
,
this
));
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/IndexCondition.java
浏览文件 @
18a3b3c2
...
...
@@ -7,14 +7,21 @@
package
org
.
h2
.
index
;
import
java.sql.SQLException
;
import
java.util.Arrays
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
org.h2.command.dml.Query
;
import
org.h2.engine.Session
;
import
org.h2.expression.Comparison
;
import
org.h2.expression.Expression
;
import
org.h2.expression.ExpressionColumn
;
import
org.h2.expression.ExpressionVisitor
;
import
org.h2.message.Message
;
import
org.h2.result.LocalResult
;
import
org.h2.table.Column
;
import
org.h2.util.ObjectArray
;
import
org.h2.util.StatementBuilder
;
import
org.h2.value.CompareMode
;
import
org.h2.value.Value
;
/**
...
...
@@ -50,20 +57,56 @@ public class IndexCondition {
public
static
final
int
ALWAYS_FALSE
=
8
;
private
Column
column
;
private
Expression
expression
;
private
int
compareType
;
private
Expression
expression
;
private
ObjectArray
<
Expression
>
expressionList
;
private
Query
expressionQuery
;
private
IndexCondition
(
int
compareType
,
ExpressionColumn
column
,
Expression
expression
)
{
this
.
compareType
=
compareType
;
this
.
column
=
column
==
null
?
null
:
column
.
getColumn
();
this
.
expression
=
expression
;
}
/**
* Create an index condition with the given parameters.
*
* @param compareType the comparison type
* @param column the column
* @param expression the expression
* @return the index condition
*/
public
IndexCondition
(
int
compareType
,
ExpressionColumn
column
,
Expression
expression
)
{
this
.
compareType
=
compareType
;
this
.
column
=
column
==
null
?
null
:
column
.
getColumn
();
this
.
expression
=
expression
;
public
static
IndexCondition
get
(
int
compareType
,
ExpressionColumn
column
,
Expression
expression
)
{
return
new
IndexCondition
(
compareType
,
column
,
expression
);
}
/**
* Create an index condition with the compare type IN_LIST and with the
* given parameters.
*
* @param column the column
* @param list the expression list
* @return the index condition
*/
public
static
IndexCondition
getInList
(
ExpressionColumn
column
,
ObjectArray
<
Expression
>
list
)
{
IndexCondition
cond
=
new
IndexCondition
(
Comparison
.
IN_LIST
,
column
,
null
);
cond
.
expressionList
=
list
;
return
cond
;
}
/**
* Create an index condition with the compare type IN_QUERY and with the
* given parameters.
*
* @param column the column
* @param query the select statement
* @return the index condition
*/
public
static
IndexCondition
getInQuery
(
ExpressionColumn
column
,
Query
query
)
{
IndexCondition
cond
=
new
IndexCondition
(
Comparison
.
IN_QUERY
,
column
,
null
);
cond
.
expressionQuery
=
query
;
return
cond
;
}
/**
...
...
@@ -76,6 +119,47 @@ public class IndexCondition {
return
expression
.
getValue
(
session
);
}
/**
* Get the current value list of the expression. The value list is of the
* same type as the column, distinct, and sorted.
*
* @param session the session
* @return the value list
*/
public
Value
[]
getCurrentValueList
(
Session
session
)
throws
SQLException
{
HashSet
<
Value
>
valueSet
=
new
HashSet
<
Value
>();
int
dataType
=
column
.
getType
();
for
(
Expression
e
:
expressionList
)
{
Value
v
=
e
.
getValue
(
session
);
v
=
v
.
convertTo
(
dataType
);
valueSet
.
add
(
v
);
}
Value
[]
array
=
new
Value
[
valueSet
.
size
()];
valueSet
.
toArray
(
array
);
final
CompareMode
mode
=
session
.
getDatabase
().
getCompareMode
();
Arrays
.
sort
(
array
,
new
Comparator
<
Value
>()
{
public
int
compare
(
Value
o1
,
Value
o2
)
{
try
{
return
o1
.
compareTo
(
o2
,
mode
);
}
catch
(
SQLException
e
)
{
throw
Message
.
convertToInternal
(
e
);
}
}
});
return
array
;
}
/**
* Get the current result of the expression. The rows may not be of the same
* type, therefore the rows may not be unique.
*
* @param session the session
* @return the result
*/
public
LocalResult
getCurrentResult
(
Session
session
)
throws
SQLException
{
return
expressionQuery
.
query
(
0
);
}
/**
* Get the SQL snippet of this comparison.
*
...
...
@@ -85,7 +169,7 @@ public class IndexCondition {
if
(
compareType
==
Comparison
.
FALSE
)
{
return
"FALSE"
;
}
St
ringBuilder
buff
=
new
String
Builder
();
St
atementBuilder
buff
=
new
Statement
Builder
();
buff
.
append
(
column
.
getSQL
());
switch
(
compareType
)
{
case
Comparison
.
EQUAL
:
...
...
@@ -103,10 +187,25 @@ public class IndexCondition {
case
Comparison
.
SMALLER
:
buff
.
append
(
" < "
);
break
;
case
Comparison
.
IN_LIST
:
buff
.
append
(
" IN("
);
for
(
Expression
e
:
expressionList
)
{
buff
.
appendExceptFirst
(
", "
);
buff
.
append
(
e
.
getSQL
());
}
buff
.
append
(
')'
);
break
;
case
Comparison
.
IN_QUERY
:
buff
.
append
(
" IN("
);
buff
.
append
(
expressionQuery
.
getPlanSQL
());
buff
.
append
(
')'
);
break
;
default
:
Message
.
throwInternalError
(
"type="
+
compareType
);
}
buff
.
append
(
expression
.
getSQL
());
if
(
expression
!=
null
)
{
buff
.
append
(
expression
.
getSQL
());
}
return
buff
.
toString
();
}
...
...
@@ -120,6 +219,8 @@ public class IndexCondition {
case
Comparison
.
FALSE
:
return
ALWAYS_FALSE
;
case
Comparison
.
EQUAL
:
case
Comparison
.
IN_LIST
:
case
Comparison
.
IN_QUERY
:
return
EQUALITY
;
case
Comparison
.
BIGGER_EQUAL
:
case
Comparison
.
BIGGER
:
...
...
@@ -175,6 +276,10 @@ public class IndexCondition {
}
}
public
int
getCompareType
()
{
return
compareType
;
}
/**
* Get the referenced column.
*
...
...
@@ -190,7 +295,18 @@ public class IndexCondition {
* @return true if it can be evaluated
*/
public
boolean
isEvaluatable
()
{
return
expression
.
isEverything
(
ExpressionVisitor
.
EVALUATABLE
);
if
(
expression
!=
null
)
{
return
expression
.
isEverything
(
ExpressionVisitor
.
EVALUATABLE
);
}
if
(
expressionList
!=
null
)
{
for
(
Expression
e
:
expressionList
)
{
if
(!
e
.
isEverything
(
ExpressionVisitor
.
EVALUATABLE
))
{
return
false
;
}
}
return
true
;
}
return
expressionQuery
.
isEverything
(
ExpressionVisitor
.
EVALUATABLE
);
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/IndexCursor.java
0 → 100644
浏览文件 @
18a3b3c2
/*
* Copyright 2004-2009 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
index
;
import
java.sql.SQLException
;
import
java.util.HashSet
;
import
org.h2.engine.Session
;
import
org.h2.expression.Comparison
;
import
org.h2.message.Message
;
import
org.h2.result.LocalResult
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
import
org.h2.result.SortOrder
;
import
org.h2.table.Column
;
import
org.h2.table.IndexColumn
;
import
org.h2.table.Table
;
import
org.h2.util.ObjectArray
;
import
org.h2.value.Value
;
/**
* The filter used to walk through an index. This class filters supports IN(..)
* and IN(SELECT ...) optimizations.
*/
public
class
IndexCursor
implements
Cursor
{
private
Session
session
;
private
Index
index
;
private
Table
table
;
private
IndexColumn
[]
indexColumns
;
private
boolean
alwaysFalse
;
private
SearchRow
start
,
end
;
private
Cursor
cursor
;
private
Column
inColumn
;
private
int
inListIndex
;
private
Value
[]
inList
;
private
LocalResult
inResult
;
private
HashSet
<
Value
>
inResultTested
;
public
IndexCursor
(
Session
session
)
{
this
.
session
=
session
;
}
public
void
setIndex
(
Index
index
)
{
this
.
index
=
index
;
this
.
table
=
index
.
getTable
();
Column
[]
columns
=
table
.
getColumns
();
indexColumns
=
new
IndexColumn
[
columns
.
length
];
IndexColumn
[]
idxCols
=
index
.
getIndexColumns
();
if
(
idxCols
!=
null
)
{
for
(
int
i
=
0
;
i
<
columns
.
length
;
i
++)
{
int
idx
=
index
.
getColumnIndex
(
columns
[
i
]);
if
(
idx
>=
0
)
{
indexColumns
[
i
]
=
idxCols
[
idx
];
}
}
}
}
/**
* Re-evaluate the start and end values of the index search for rows.
*
* @param indexConditions the index conditions
*/
public
void
find
(
ObjectArray
<
IndexCondition
>
indexConditions
)
throws
SQLException
{
alwaysFalse
=
false
;
start
=
end
=
null
;
inList
=
null
;
inResult
=
null
;
inResultTested
=
new
HashSet
<
Value
>();
for
(
IndexCondition
condition
:
indexConditions
)
{
if
(
condition
.
isAlwaysFalse
())
{
alwaysFalse
=
true
;
break
;
}
Column
column
=
condition
.
getColumn
();
int
type
=
column
.
getType
();
int
id
=
column
.
getColumnId
();
if
(
condition
.
getCompareType
()
==
Comparison
.
IN_LIST
)
{
this
.
inColumn
=
column
;
inList
=
condition
.
getCurrentValueList
(
session
);
inListIndex
=
0
;
return
;
}
else
if
(
condition
.
getCompareType
()
==
Comparison
.
IN_QUERY
)
{
this
.
inColumn
=
column
;
inResult
=
condition
.
getCurrentResult
(
session
);
return
;
}
else
{
Value
v
=
condition
.
getCurrentValue
(
session
).
convertTo
(
type
);
boolean
isStart
=
condition
.
isStart
();
boolean
isEnd
=
condition
.
isEnd
();
IndexColumn
idxCol
=
indexColumns
[
id
];
if
(
idxCol
!=
null
&&
(
idxCol
.
sortType
&
SortOrder
.
DESCENDING
)
!=
0
)
{
// if the index column is sorted the other way, we swap end and start
// NULLS_FIRST / NULLS_LAST is not a problem, as nulls never match anyway
boolean
temp
=
isStart
;
isStart
=
isEnd
;
isEnd
=
temp
;
}
if
(
isStart
)
{
start
=
getSearchRow
(
start
,
id
,
v
,
true
);
}
if
(
isEnd
)
{
end
=
getSearchRow
(
end
,
id
,
v
,
false
);
}
}
}
if
(!
alwaysFalse
)
{
cursor
=
index
.
find
(
session
,
start
,
end
);
}
}
private
SearchRow
getSearchRow
(
SearchRow
row
,
int
id
,
Value
v
,
boolean
max
)
throws
SQLException
{
if
(
row
==
null
)
{
row
=
table
.
getTemplateRow
();
}
else
{
v
=
getMax
(
row
.
getValue
(
id
),
v
,
max
);
}
row
.
setValue
(
id
,
v
);
return
row
;
}
private
Value
getMax
(
Value
a
,
Value
b
,
boolean
bigger
)
throws
SQLException
{
if
(
a
==
null
)
{
return
b
;
}
else
if
(
b
==
null
)
{
return
a
;
}
int
comp
=
a
.
compareTo
(
b
,
table
.
getDatabase
().
getCompareMode
());
if
(!
bigger
)
{
comp
=
-
comp
;
}
return
comp
>
0
?
a
:
b
;
}
/**
* Check if the result is empty for sure.
*
* @return true if it is
*/
public
boolean
isAlwaysFalse
()
{
return
alwaysFalse
;
}
public
Row
get
()
throws
SQLException
{
return
cursor
.
get
();
}
public
int
getPos
()
{
return
cursor
.
getPos
();
}
public
SearchRow
getSearchRow
()
throws
SQLException
{
return
cursor
.
getSearchRow
();
}
public
boolean
next
()
throws
SQLException
{
while
(
true
)
{
if
(
cursor
==
null
)
{
nextCursor
();
if
(
cursor
==
null
)
{
return
false
;
}
}
if
(
cursor
.
next
())
{
return
true
;
}
cursor
=
null
;
}
}
private
void
nextCursor
()
throws
SQLException
{
if
(
inList
!=
null
)
{
if
(
inListIndex
<
inList
.
length
)
{
Value
v
=
inList
[
inListIndex
++];
find
(
v
);
}
}
else
if
(
inResult
!=
null
)
{
while
(
inResult
.
next
())
{
Value
v
=
inResult
.
currentRow
()[
0
];
v
=
v
.
convertTo
(
inColumn
.
getType
());
if
(
inResultTested
.
add
(
v
))
{
find
(
v
);
break
;
}
}
}
}
private
void
find
(
Value
v
)
throws
SQLException
{
v
=
v
.
convertTo
(
inColumn
.
getType
());
int
id
=
inColumn
.
getColumnId
();
if
(
start
==
null
)
{
start
=
table
.
getTemplateRow
();
}
start
.
setValue
(
id
,
v
);
cursor
=
index
.
find
(
session
,
start
,
start
);
}
public
boolean
previous
()
{
throw
Message
.
throwInternalError
();
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/MetaTable.java
浏览文件 @
18a3b3c2
...
...
@@ -854,6 +854,7 @@ public class MetaTable extends Table {
add
(
rows
,
new
String
[]{
"h2.objectCacheMaxPerElementSize"
,
""
+
SysProperties
.
OBJECT_CACHE_MAX_PER_ELEMENT_SIZE
});
add
(
rows
,
new
String
[]{
"h2.optimizeIn"
,
""
+
SysProperties
.
OPTIMIZE_IN
});
add
(
rows
,
new
String
[]{
"h2.optimizeInJoin"
,
""
+
SysProperties
.
optimizeInJoin
});
add
(
rows
,
new
String
[]{
"h2.optimizeInList"
,
""
+
SysProperties
.
OPTIMIZE_IN_LIST
});
add
(
rows
,
new
String
[]{
"h2.optimizeMinMax"
,
""
+
SysProperties
.
OPTIMIZE_MIN_MAX
});
add
(
rows
,
new
String
[]{
"h2.optimizeSubqueryCache"
,
""
+
SysProperties
.
OPTIMIZE_SUBQUERY_CACHE
});
add
(
rows
,
new
String
[]{
"h2.overflowExceptions"
,
""
+
SysProperties
.
OVERFLOW_EXCEPTIONS
});
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/TableFilter.java
浏览文件 @
18a3b3c2
...
...
@@ -16,13 +16,12 @@ import org.h2.engine.Session;
import
org.h2.expression.ConditionAndOr
;
import
org.h2.expression.Expression
;
import
org.h2.expression.ExpressionColumn
;
import
org.h2.index.Cursor
;
import
org.h2.index.Index
;
import
org.h2.index.IndexCondition
;
import
org.h2.index.IndexCursor
;
import
org.h2.message.Message
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
import
org.h2.result.SortOrder
;
import
org.h2.util.ObjectArray
;
import
org.h2.util.StatementBuilder
;
import
org.h2.util.StringUtils
;
...
...
@@ -40,8 +39,6 @@ public class TableFilter implements ColumnResolver {
private
String
alias
;
private
Session
session
;
private
Index
index
;
private
IndexColumn
[]
indexColumns
;
private
Cursor
cursor
;
private
int
scanCount
;
/**
...
...
@@ -49,21 +46,31 @@ public class TableFilter implements ColumnResolver {
*/
private
boolean
used
;
// conditions that can be used for direct index lookup (start or end)
/**
* The filter used to walk through the index.
*/
private
final
IndexCursor
cursor
;
/**
* The index conditions used for direct index lookup (start or end).
*/
private
final
ObjectArray
<
IndexCondition
>
indexConditions
=
ObjectArray
.
newInstance
();
// conditions that can't be used for index lookup,
// but for row filter for this table (ID=ID, NAME LIKE '%X%')
/**
* Additional conditions that can't be used for index lookup,
* but for row filter for this table (ID=ID, NAME LIKE '%X%')
*/
private
Expression
filterCondition
;
// the complete join condition
/**
* The complete join condition.
*/
private
Expression
joinCondition
;
private
SearchRow
currentSearchRow
;
private
Row
current
;
private
int
state
;
private
TableFilter
join
;
private
boolean
outerJoin
;
private
ObjectArray
<
Column
>
naturalJoinColumns
;
private
boolean
foundOne
;
...
...
@@ -85,6 +92,7 @@ public class TableFilter implements ColumnResolver {
this
.
table
=
table
;
this
.
alias
=
alias
;
this
.
select
=
select
;
this
.
cursor
=
new
IndexCursor
(
session
);
if
(!
rightsChecked
)
{
session
.
getUser
().
checkRight
(
table
,
Right
.
SELECT
);
}
...
...
@@ -229,71 +237,17 @@ public class TableFilter implements ColumnResolver {
foundOne
=
false
;
}
private
Value
getMax
(
Value
a
,
Value
b
,
boolean
bigger
)
throws
SQLException
{
if
(
a
==
null
)
{
return
b
;
}
else
if
(
b
==
null
)
{
return
a
;
}
int
comp
=
a
.
compareTo
(
b
,
session
.
getDatabase
().
getCompareMode
());
if
(!
bigger
)
{
comp
=
-
comp
;
}
return
comp
>
0
?
a
:
b
;
}
/**
* Check if there are more rows to read.
*
* @return true if there are
*/
public
boolean
next
()
throws
SQLException
{
boolean
alwaysFalse
=
false
;
if
(
state
==
AFTER_LAST
)
{
return
false
;
}
else
if
(
state
==
BEFORE_FIRST
)
{
SearchRow
start
=
null
,
end
=
null
;
for
(
IndexCondition
condition
:
indexConditions
)
{
if
(
condition
.
isAlwaysFalse
())
{
alwaysFalse
=
true
;
break
;
}
Column
column
=
condition
.
getColumn
();
int
type
=
column
.
getType
();
int
id
=
column
.
getColumnId
();
Value
v
=
condition
.
getCurrentValue
(
session
).
convertTo
(
type
);
boolean
isStart
=
condition
.
isStart
(),
isEnd
=
condition
.
isEnd
();
IndexColumn
idxCol
=
indexColumns
[
id
];
if
(
idxCol
!=
null
&&
(
idxCol
.
sortType
&
SortOrder
.
DESCENDING
)
!=
0
)
{
// if the index column is sorted the other way, we swap end and start
// NULLS_FIRST / NULLS_LAST is not a problem, as nulls never match anyway
boolean
temp
=
isStart
;
isStart
=
isEnd
;
isEnd
=
temp
;
}
if
(
isStart
)
{
Value
newStart
;
if
(
start
==
null
)
{
start
=
table
.
getTemplateRow
();
newStart
=
v
;
}
else
{
newStart
=
getMax
(
start
.
getValue
(
id
),
v
,
true
);
}
start
.
setValue
(
id
,
newStart
);
}
if
(
isEnd
)
{
Value
newEnd
;
if
(
end
==
null
)
{
end
=
table
.
getTemplateRow
();
newEnd
=
v
;
}
else
{
newEnd
=
getMax
(
end
.
getValue
(
id
),
v
,
false
);
}
end
.
setValue
(
id
,
newEnd
);
}
}
if
(!
alwaysFalse
)
{
cursor
=
index
.
find
(
session
,
start
,
end
);
cursor
.
find
(
indexConditions
);
if
(!
cursor
.
isAlwaysFalse
())
{
if
(
join
!=
null
)
{
join
.
reset
();
}
...
...
@@ -310,7 +264,7 @@ public class TableFilter implements ColumnResolver {
if
(
state
==
NULL_ROW
)
{
break
;
}
if
(
alwaysFalse
)
{
if
(
cursor
.
isAlwaysFalse
()
)
{
state
=
AFTER_LAST
;
}
else
{
if
((++
scanCount
&
4095
)
==
0
)
{
...
...
@@ -319,7 +273,6 @@ public class TableFilter implements ColumnResolver {
if
(
cursor
.
next
())
{
currentSearchRow
=
cursor
.
getSearchRow
();
current
=
null
;
// cursor.get();
state
=
FOUND
;
}
else
{
state
=
AFTER_LAST
;
...
...
@@ -566,17 +519,7 @@ public class TableFilter implements ColumnResolver {
public
void
setIndex
(
Index
index
)
{
this
.
index
=
index
;
Column
[]
columns
=
table
.
getColumns
();
indexColumns
=
new
IndexColumn
[
columns
.
length
];
IndexColumn
[]
idxCols
=
index
.
getIndexColumns
();
if
(
idxCols
!=
null
)
{
for
(
int
i
=
0
;
i
<
columns
.
length
;
i
++)
{
int
idx
=
index
.
getColumnIndex
(
columns
[
i
]);
if
(
idx
>=
0
)
{
indexColumns
[
i
]
=
idxCols
[
idx
];
}
}
}
cursor
.
setIndex
(
index
);
}
public
void
setUsed
(
boolean
used
)
{
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论