Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
0dd766c9
提交
0dd766c9
authored
9 年前
作者:
S.Vladykin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip
上级
1e9b6d64
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
164 行增加
和
125 行删除
+164
-125
ViewIndex.java
h2/src/main/org/h2/index/ViewIndex.java
+57
-113
JoinBatch.java
h2/src/main/org/h2/table/JoinBatch.java
+97
-10
TableFilter.java
h2/src/main/org/h2/table/TableFilter.java
+10
-2
没有找到文件。
h2/src/main/org/h2/index/ViewIndex.java
浏览文件 @
0dd766c9
...
...
@@ -6,8 +6,6 @@
package
org
.
h2
.
index
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.Future
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.Prepared
;
import
org.h2.command.dml.Query
;
...
...
@@ -103,12 +101,8 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
// we do not support batching for recursive queries
return
null
;
}
IndexLookupBatch
lookupBatch
=
query
.
isUnion
()
?
createLookupBatchUnion
((
SelectUnion
)
query
)
:
createLookupBatchSimple
((
Select
)
query
);
// TODO not initialize index cursor on the top table filter but work as usual batching
// TODO return wrapper which goes through all the joins an collects all the rows
return
null
;
// currently do not support unions
return
query
.
isUnion
()
?
null
:
createLookupBatchSimple
((
Select
)
query
);
}
private
IndexLookupBatch
createLookupBatchSimple
(
Select
select
)
{
...
...
@@ -119,30 +113,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
// our sub-query itself is not batched, will run usual way
return
null
;
}
// TODO wrap the join batch into lookup batch
return
null
;
}
private
IndexLookupBatch
createLookupBatchUnion
(
SelectUnion
union
)
{
Query
left
=
union
.
getLeft
();
IndexLookupBatch
leftLookupBatch
=
left
.
isUnion
()
?
createLookupBatchUnion
((
SelectUnion
)
left
):
createLookupBatchSimple
((
Select
)
left
);
Query
right
=
union
.
getRight
();
IndexLookupBatch
rightLookupBatch
=
right
.
isUnion
()
?
createLookupBatchUnion
((
SelectUnion
)
right
)
:
createLookupBatchSimple
((
Select
)
right
);
if
(
leftLookupBatch
==
null
)
{
if
(
rightLookupBatch
==
null
)
{
return
null
;
}
leftLookupBatch
=
null
;
// TODO
}
else
if
(
rightLookupBatch
==
null
)
{
rightLookupBatch
=
null
;
// TODO
}
return
new
UnionLookupBatch
(
leftLookupBatch
,
rightLookupBatch
);
return
joinBatch
.
asViewIndexLookupBatch
(
this
);
}
public
Session
getSession
()
{
...
...
@@ -263,57 +234,60 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
return
(
Query
)
p
;
}
private
Cursor
find
(
Session
session
,
SearchRow
first
,
SearchRow
last
,
private
Cursor
find
Recursive
(
Session
session
,
SearchRow
first
,
SearchRow
last
,
SearchRow
intersection
)
{
if
(
recursive
)
{
LocalResult
recResult
=
view
.
getRecursiveResult
();
if
(
recResult
!=
null
)
{
recResult
.
reset
();
return
new
ViewCursor
(
this
,
recResult
,
first
,
last
);
}
if
(
query
==
null
)
{
query
=
(
Query
)
createSession
.
prepare
(
querySQL
,
true
);
}
if
(!
query
.
isUnion
())
{
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_2
,
"recursive queries without UNION ALL"
);
}
SelectUnion
union
=
(
SelectUnion
)
query
;
if
(
union
.
getUnionType
()
!=
SelectUnion
.
UNION_ALL
)
{
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_2
,
"recursive queries without UNION ALL"
);
assert
recursive
;
LocalResult
recResult
=
view
.
getRecursiveResult
();
if
(
recResult
!=
null
)
{
recResult
.
reset
();
return
new
ViewCursor
(
this
,
recResult
,
first
,
last
);
}
if
(
query
==
null
)
{
query
=
(
Query
)
createSession
.
prepare
(
querySQL
,
true
);
}
if
(!
query
.
isUnion
())
{
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_2
,
"recursive queries without UNION ALL"
);
}
SelectUnion
union
=
(
SelectUnion
)
query
;
if
(
union
.
getUnionType
()
!=
SelectUnion
.
UNION_ALL
)
{
throw
DbException
.
get
(
ErrorCode
.
SYNTAX_ERROR_2
,
"recursive queries without UNION ALL"
);
}
Query
left
=
union
.
getLeft
();
// to ensure the last result is not closed
left
.
disableCache
();
LocalResult
r
=
left
.
query
(
0
);
LocalResult
result
=
union
.
getEmptyResult
();
// ensure it is not written to disk,
// because it is not closed normally
result
.
setMaxMemoryRows
(
Integer
.
MAX_VALUE
);
while
(
r
.
next
())
{
result
.
addRow
(
r
.
currentRow
());
}
Query
right
=
union
.
getRight
();
r
.
reset
();
view
.
setRecursiveResult
(
r
);
// to ensure the last result is not closed
right
.
disableCache
();
while
(
true
)
{
r
=
right
.
query
(
0
);
if
(
r
.
getRowCount
()
==
0
)
{
break
;
}
Query
left
=
union
.
getLeft
();
// to ensure the last result is not closed
left
.
disableCache
();
LocalResult
r
=
left
.
query
(
0
);
LocalResult
result
=
union
.
getEmptyResult
();
// ensure it is not written to disk,
// because it is not closed normally
result
.
setMaxMemoryRows
(
Integer
.
MAX_VALUE
);
while
(
r
.
next
())
{
result
.
addRow
(
r
.
currentRow
());
}
Query
right
=
union
.
getRight
();
r
.
reset
();
view
.
setRecursiveResult
(
r
);
// to ensure the last result is not closed
right
.
disableCache
();
while
(
true
)
{
r
=
right
.
query
(
0
);
if
(
r
.
getRowCount
()
==
0
)
{
break
;
}
while
(
r
.
next
())
{
result
.
addRow
(
r
.
currentRow
());
}
r
.
reset
();
view
.
setRecursiveResult
(
r
);
}
view
.
setRecursiveResult
(
null
);
result
.
done
();
return
new
ViewCursor
(
this
,
result
,
first
,
last
);
}
view
.
setRecursiveResult
(
null
);
result
.
done
();
return
new
ViewCursor
(
this
,
result
,
first
,
last
);
}
public
void
setupQueryParameters
(
Session
session
,
SearchRow
first
,
SearchRow
last
,
SearchRow
intersection
)
{
ArrayList
<
Parameter
>
paramList
=
query
.
getParameters
();
if
(
originalParameters
!=
null
)
{
for
(
int
i
=
0
,
size
=
originalParameters
.
size
();
i
<
size
;
i
++)
{
...
...
@@ -350,6 +324,14 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
setParameter
(
paramList
,
idx
++,
intersection
.
getValue
(
i
));
}
}
}
private
Cursor
find
(
Session
session
,
SearchRow
first
,
SearchRow
last
,
SearchRow
intersection
)
{
if
(
recursive
)
{
return
findRecursive
(
session
,
first
,
last
,
intersection
);
}
setupQueryParameters
(
session
,
first
,
last
,
intersection
);
LocalResult
result
=
query
.
query
(
0
);
return
new
ViewCursor
(
this
,
result
,
first
,
last
);
}
...
...
@@ -506,42 +488,4 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
public
boolean
isRecursive
()
{
return
recursive
;
}
/**
* Lookup batch for unions.
*/
private
static
final
class
UnionLookupBatch
implements
IndexLookupBatch
{
private
final
IndexLookupBatch
left
;
private
final
IndexLookupBatch
right
;
private
UnionLookupBatch
(
IndexLookupBatch
left
,
IndexLookupBatch
right
)
{
this
.
left
=
left
;
this
.
right
=
right
;
}
@Override
public
void
addSearchRows
(
SearchRow
first
,
SearchRow
last
)
{
assert
!
left
.
isBatchFull
();
assert
!
right
.
isBatchFull
();
left
.
addSearchRows
(
first
,
last
);
right
.
addSearchRows
(
first
,
last
);
}
@Override
public
boolean
isBatchFull
()
{
return
left
.
isBatchFull
()
||
right
.
isBatchFull
();
}
@Override
public
List
<
Future
<
Cursor
>>
find
()
{
// TODO Auto-generated method stub
return
null
;
}
@Override
public
void
reset
()
{
left
.
reset
();
right
.
reset
();
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/JoinBatch.java
浏览文件 @
0dd766c9
...
...
@@ -6,6 +6,7 @@
package
org
.
h2
.
table
;
import
java.util.AbstractList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.List
;
...
...
@@ -13,10 +14,12 @@ import java.util.concurrent.Future;
import
org.h2.index.Cursor
;
import
org.h2.index.IndexCursor
;
import
org.h2.index.IndexLookupBatch
;
import
org.h2.index.ViewIndex
;
import
org.h2.message.DbException
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
import
org.h2.util.DoneFuture
;
import
org.h2.util.New
;
import
org.h2.value.Value
;
import
org.h2.value.ValueLong
;
...
...
@@ -28,7 +31,6 @@ import org.h2.value.ValueLong;
* @author Sergi Vladykin
*/
public
final
class
JoinBatch
{
private
static
final
Cursor
EMPTY_CURSOR
=
new
Cursor
()
{
@Override
public
boolean
previous
()
{
...
...
@@ -54,7 +56,11 @@ public final class JoinBatch {
public
String
toString
()
{
return
"EMPTY_CURSOR"
;
}
};
};
private
static
final
Future
<
Cursor
>
PLACEHOLDER
=
new
DoneFuture
<
Cursor
>(
null
);
private
ViewIndexLookupBatch
lookupBatchWrapper
;
private
JoinFilter
[]
filters
;
private
JoinFilter
top
;
...
...
@@ -148,14 +154,16 @@ public final class JoinBatch {
}
private
void
start
()
{
// TODO if filters[0].isBatched() then use batching instead of top.filter.getIndexCursor()
// initialize current row
current
=
new
JoinRow
(
new
Object
[
filters
.
length
]);
current
.
updateRow
(
top
.
id
,
top
.
filter
.
getIndexCursor
(),
JoinRow
.
S_NULL
,
JoinRow
.
S_CURSOR
);
// initialize top cursor
top
.
filter
.
getIndexCursor
().
find
(
top
.
filter
.
getSession
(),
top
.
filter
.
getIndexConditions
());
if
(
lookupBatchWrapper
==
null
)
{
current
.
updateRow
(
top
.
id
,
top
.
filter
.
getIndexCursor
(),
JoinRow
.
S_NULL
,
JoinRow
.
S_CURSOR
);
// initialize top cursor
top
.
filter
.
getIndexCursor
().
find
(
top
.
filter
.
getSession
(),
top
.
filter
.
getIndexConditions
());
}
else
{
// we are sub-query and joined to upper level query
// TODO setup
}
// we need fake first row because batchedNext always will move to the next row
JoinRow
fake
=
new
JoinRow
(
null
);
fake
.
next
=
current
;
...
...
@@ -239,7 +247,7 @@ public final class JoinBatch {
current
=
join
.
find
(
current
);
}
if
(
current
.
row
(
join
.
id
)
!=
null
)
{
// either find called or outer join with null
row
// either find called or outer join with null
-
row
jfId
=
join
.
id
;
continue
;
}
...
...
@@ -340,13 +348,23 @@ public final class JoinBatch {
}
}
/**
* @return Adapter to allow joining to this batch in sub-queries.
*/
public
IndexLookupBatch
asViewIndexLookupBatch
(
ViewIndex
viewIndex
)
{
if
(
lookupBatchWrapper
==
null
)
{
lookupBatchWrapper
=
new
ViewIndexLookupBatch
(
viewIndex
);
}
return
lookupBatchWrapper
;
}
@Override
public
String
toString
()
{
return
"JoinBatch->\nprev->"
+
(
current
==
null
?
null
:
current
.
prev
)
+
"\ncurr->"
+
current
+
"\nnext->"
+
(
current
==
null
?
null
:
current
.
next
);
}
/**
* Table filter participating in batched join.
*/
...
...
@@ -404,6 +422,10 @@ public final class JoinBatch {
return
true
;
}
private
List
<
Future
<
Cursor
>>
find
()
{
return
lookupBatch
.
find
();
}
private
JoinRow
find
(
JoinRow
current
)
{
assert
current
!=
null
;
...
...
@@ -655,5 +677,70 @@ public final class JoinBatch {
return
1
;
}
}
/**
* Lookup batch over this join batch for a sub-query or view.
*/
private
final
class
ViewIndexLookupBatch
implements
IndexLookupBatch
{
private
final
ViewIndex
viewIndex
;
private
final
ArrayList
<
Future
<
Cursor
>>
result
=
New
.
arrayList
();
private
boolean
findCalled
;
private
ViewIndexLookupBatch
(
ViewIndex
viewIndex
)
{
this
.
viewIndex
=
viewIndex
;
}
@Override
public
void
addSearchRows
(
SearchRow
first
,
SearchRow
last
)
{
if
(
findCalled
)
{
result
.
clear
();
findCalled
=
false
;
}
viewIndex
.
setupQueryParameters
(
viewIndex
.
getSession
(),
first
,
last
,
null
);
if
(
top
.
collectSearchRows
())
{
result
.
add
(
PLACEHOLDER
);
if
(
top
.
isBatchFull
())
{
// TODO
}
}
else
{
result
.
add
(
null
);
}
}
@Override
public
boolean
isBatchFull
()
{
assert
!
findCalled
;
return
top
.
isBatchFull
();
}
@Override
public
List
<
Future
<
Cursor
>>
find
()
{
JoinBatch
jb
=
JoinBatch
.
this
;
List
<
Future
<
Cursor
>>
topCursors
=
top
.
find
();
for
(
int
i
=
0
;
i
<
topCursors
.
size
();
i
++)
{
// jb.setCursor
while
(
jb
.
next
())
{
// collect result
}
}
findCalled
=
true
;
return
result
;
}
@Override
public
void
reset
()
{
findCalled
=
false
;
result
.
clear
();
JoinBatch
.
this
.
reset
();
}
}
/**
* State of the
*/
enum
State
{
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/TableFilter.java
浏览文件 @
0dd766c9
...
...
@@ -371,7 +371,10 @@ public class TableFilter implements ColumnResolver {
jb
=
join
.
prepareBatch
(
id
+
1
);
}
IndexLookupBatch
lookupBatch
=
null
;
// TODO review the !isAlwaysTopTableFilter condition
// the globally top table filter does not need batching, if isAlwaysTopTableFilter is false
// then we either not a top table filter or top table filter in a sub-query which is not
// top in outer query, thus we need to enable batching here to allow outer query run batched
// join against this sub-query
if
(
jb
==
null
&&
select
!=
null
&&
!
isAlwaysTopTableFilter
(
id
))
{
lookupBatch
=
index
.
createLookupBatch
(
this
);
if
(
lookupBatch
!=
null
)
{
...
...
@@ -384,8 +387,13 @@ public class TableFilter implements ColumnResolver {
}
joinBatch
=
jb
;
joinFilterId
=
id
;
// TODO review the !isAlwaysTopTableFilter condition
// for globally top table filter we don't need to create lookup batch
// currently it will not be used, probably later on it will make sense
// to create it to better support X IN (...) conditions, but this needs
// to be implemented separately
if
(
lookupBatch
==
null
&&
!
isAlwaysTopTableFilter
(
id
))
{
// index.createLookupBatch will be called only once because jb can be created only if
// lookupBatch is not null from the first call above
lookupBatch
=
index
.
createLookupBatch
(
this
);
}
jb
.
register
(
this
,
lookupBatch
);
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论