Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
a3c06157
提交
a3c06157
authored
10月 22, 2015
作者:
S.Vladykin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactoring after review
上级
cd874de3
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
101 行增加
和
27 行删除
+101
-27
TableFilter.java
h2/src/main/org/h2/table/TableFilter.java
+101
-27
没有找到文件。
h2/src/main/org/h2/table/TableFilter.java
浏览文件 @
a3c06157
...
...
@@ -1081,10 +1081,6 @@ public class TableFilter implements ColumnResolver {
return
session
;
}
private
static
boolean
isRow
(
Object
x
)
{
return
x
instanceof
Row
;
}
/**
* A visitor for table filters.
*/
...
...
@@ -1145,7 +1141,11 @@ public class TableFilter implements ColumnResolver {
private
Value
getValue
(
JoinFilter
filter
,
Column
column
)
{
Object
x
=
current
.
row
[
filter
.
id
];
assert
x
!=
null
;
Row
row
=
isRow
(
x
)
?
(
Row
)
x
:
((
Cursor
)
x
).
get
();
Row
row
=
current
.
isRow
(
filter
.
id
)
?
(
Row
)
x
:
((
Cursor
)
x
).
get
();
int
columnId
=
column
.
getColumnId
();
if
(
columnId
==
-
1
)
{
return
ValueLong
.
get
(
row
.
getKey
());
}
Value
value
=
row
.
getValue
(
column
.
getColumnId
());
if
(
value
==
null
)
{
throw
DbException
.
throwInternalError
(
"value is null: "
+
column
+
" "
+
row
);
...
...
@@ -1154,6 +1154,11 @@ public class TableFilter implements ColumnResolver {
}
private
void
start
()
{
if
(
filtersCount
>
32
)
{
// This is because we store state in a 64 bit field, 2 bits per joined table.
throw
DbException
.
getUnsupportedException
(
"To many tables in join (at most 32 supported)."
);
}
// fill filters
filters
=
new
JoinFilter
[
filtersCount
];
JoinFilter
jf
=
top
;
...
...
@@ -1164,9 +1169,12 @@ public class TableFilter implements ColumnResolver {
// initialize current row
current
=
new
JoinRow
(
new
Object
[
filtersCount
]);
current
.
row
[
top
.
id
]
=
top
.
filter
.
cursor
;
current
.
incrementState
(
top
.
id
,
2
);
assert
current
.
isCursor
(
top
.
id
);
// initialize top cursor
top
.
filter
.
cursor
.
find
(
top
.
filter
.
session
,
top
.
filter
.
indexConditions
);
// we need fake first row because batchedNext always will move to the next row
JoinRow
fake
=
new
JoinRow
(
null
);
fake
.
next
=
current
;
...
...
@@ -1202,7 +1210,7 @@ public class TableFilter implements ColumnResolver {
}
}
private
Cursor
get
(
Future
<
Cursor
>
f
)
{
private
static
Cursor
get
(
Future
<
Cursor
>
f
)
{
try
{
return
f
.
get
();
}
catch
(
Exception
e
)
{
...
...
@@ -1272,12 +1280,12 @@ public class TableFilter implements ColumnResolver {
}
else
{
// here we don't care if the current was dropped
current
=
current
.
next
;
assert
!
isRow
(
current
.
row
[
jfId
]
);
assert
!
current
.
isRow
(
jfId
);
while
(
current
.
row
[
jfId
]
==
null
)
{
assert
jfId
!=
top
.
id
;
// need to go left and fetch more search rows
jfId
--;
assert
!
isRow
(
current
.
row
[
jfId
]
);
assert
!
current
.
isRow
(
jfId
);
}
}
}
...
...
@@ -1285,32 +1293,37 @@ public class TableFilter implements ColumnResolver {
@SuppressWarnings
(
"unchecked"
)
private
void
fetchCurrent
(
final
int
jfId
)
{
assert
current
.
prev
==
null
||
isRow
(
current
.
prev
.
row
[
jfId
])
:
"prev must be already fetched"
;
assert
jfId
==
0
||
isRow
(
current
.
row
[
jfId
-
1
])
:
"left must be already fetched"
;
assert
current
.
prev
==
null
||
current
.
prev
.
isRow
(
jfId
)
:
"prev must be already fetched"
;
assert
jfId
==
0
||
current
.
isRow
(
jfId
-
1
)
:
"left must be already fetched"
;
assert
!
current
.
isRow
(
jfId
)
:
"double fetching"
;
Object
x
=
current
.
row
[
jfId
];
assert
x
!=
null
:
"x null"
;
assert
!
isRow
(
x
)
:
"double fetching"
;
final
JoinFilter
jf
=
filters
[
jfId
];
// in case of outer join we don't have any future around empty cursor
boolean
newCursor
=
x
==
EMPTY_CURSOR
;
if
(!
newCursor
&&
x
instanceof
Future
)
{
if
(!
newCursor
&&
current
.
isFuture
(
jfId
)
)
{
// get cursor from a future
current
.
row
[
jfId
]
=
x
=
get
((
Future
<
Cursor
>)
x
);
current
.
incrementState
(
jfId
,
1
);
assert
current
.
isCursor
(
jfId
);
newCursor
=
true
;
}
Cursor
c
=
(
Cursor
)
x
;
assert
c
!=
null
;
JoinFilter
join
=
jf
.
join
;
for
(;;)
{
if
(
c
==
null
||
!
c
.
next
())
{
if
(
newCursor
&&
jf
.
isOuterJoin
())
{
// replace cursor with null-row
current
.
row
[
jfId
]
=
jf
.
getNullRow
();
current
.
incrementState
(
jfId
,
1
);
assert
current
.
isRow
(
jfId
);
c
=
null
;
newCursor
=
false
;
}
else
{
...
...
@@ -1336,14 +1349,19 @@ public class TableFilter implements ColumnResolver {
current
=
current
.
copyBehind
(
jf
.
id
);
// get current row from cursor
current
.
row
[
jfId
]
=
c
.
get
();
current
.
incrementState
(
jfId
,
1
);
assert
current
.
isRow
(
jfId
);
}
if
(
joinEmpty
)
{
assert
current
.
row
[
join
.
id
]
==
null
;
current
.
row
[
join
.
id
]
=
EMPTY_CURSOR
;
current
.
incrementState
(
join
.
id
,
2
);
assert
current
.
isCursor
(
join
.
id
);
}
return
;
}
}
@Override
public
String
toString
()
{
return
"JoinBatch->\nprev->"
+
(
current
==
null
?
null
:
current
.
prev
)
+
...
...
@@ -1438,7 +1456,7 @@ public class TableFilter implements ColumnResolver {
// go backwards and assign futures
ListIterator
<
Future
<
Cursor
>>
iter
=
result
.
listIterator
(
result
.
size
());
for
(;;)
{
assert
isRow
(
current
.
row
[
id
-
1
]
);
assert
current
.
isRow
(
id
-
1
);
if
(
current
.
row
[
id
]
==
EMPTY_CURSOR
)
{
// outer join support - skip row with existing empty cursor
current
=
current
.
prev
;
...
...
@@ -1446,7 +1464,15 @@ public class TableFilter implements ColumnResolver {
}
assert
current
.
row
[
id
]
==
null
;
Future
<
Cursor
>
future
=
iter
.
previous
();
current
.
row
[
id
]
=
future
==
null
?
EMPTY_CURSOR
:
future
;
if
(
future
==
null
)
{
current
.
row
[
id
]
=
EMPTY_CURSOR
;
current
.
incrementState
(
id
,
2
);
assert
current
.
isCursor
(
id
);
}
else
{
current
.
row
[
id
]
=
future
;
current
.
incrementState
(
id
,
1
);
assert
current
.
isFuture
(
id
);
}
if
(
current
.
prev
==
null
||
!
iter
.
hasPrevious
())
{
break
;
}
...
...
@@ -1458,9 +1484,9 @@ public class TableFilter implements ColumnResolver {
while
(
current
.
prev
!=
null
&&
current
.
prev
.
row
[
id
]
==
EMPTY_CURSOR
)
{
current
=
current
.
prev
;
}
assert
current
.
prev
==
null
||
isRow
(
current
.
prev
.
row
[
id
]
);
assert
current
.
prev
==
null
||
current
.
prev
.
isRow
(
id
);
assert
current
.
row
[
id
]
!=
null
;
assert
!
isRow
(
current
.
row
[
id
]
);
assert
!
current
.
isRow
(
id
);
// the last updated row
return
current
;
...
...
@@ -1476,6 +1502,12 @@ public class TableFilter implements ColumnResolver {
* Linked row in batched join.
*/
private
static
final
class
JoinRow
{
private
static
final
long
S_FUTURE
=
1
;
private
static
final
long
S_CURSOR
=
2
;
private
static
final
long
S_ROW
=
3
;
private
static
final
long
S_MASK
=
3
;
/**
* May contain one of the following:
* <br/>- {@code null}: means that we need to get future cursor for this row
...
...
@@ -1484,19 +1516,54 @@ public class TableFilter implements ColumnResolver {
* <br/>- {@link Row}: the {@link Row} is already fetched and is ready to be used
*/
Object
[]
row
;
long
state
;
JoinRow
prev
;
JoinRow
next
;
/**
* @param row Row.
*/
private
JoinRow
(
Object
[]
row
)
{
this
.
row
=
row
;
}
/**
* @param joinFilterId Join filter id.
* @return Row state.
*/
private
long
getState
(
int
joinFilterId
)
{
return
(
state
>>>
(
joinFilterId
<<
1
))
&
S_MASK
;
}
/**
* Allows to do a state transition in the following order:
* 0. Slot contains {@code null} (no constant because simple null check is sufficient).
* 1. Slot contains {@link Future} ({@link #S_FUTURE}).
* 2. Slot contains {@link Cursor} ({@link #S_CURSOR}).
* 3. Slot contains {@link Row} ({@link #S_ROW}).
*
* @param joinFilterId {@link JoinRow} filter id.
* @param i Increment by this number of moves.
*/
private
void
incrementState
(
int
joinFilterId
,
long
i
)
{
state
+=
i
<<
(
joinFilterId
<<
1
);
}
private
boolean
isRow
(
int
joinFilterId
)
{
return
getState
(
joinFilterId
)
==
S_ROW
;
}
private
boolean
isFuture
(
int
joinFilterId
)
{
return
getState
(
joinFilterId
)
==
S_FUTURE
;
}
private
boolean
isCursor
(
int
joinFilterId
)
{
return
getState
(
joinFilterId
)
==
S_CURSOR
;
}
private
boolean
isComplete
()
{
return
isRow
(
row
[
row
.
length
-
1
]
);
return
isRow
(
row
.
length
-
1
);
}
private
boolean
isDropped
()
{
...
...
@@ -1513,8 +1580,14 @@ public class TableFilter implements ColumnResolver {
row
=
null
;
}
/**
* Copy this JoinRow behind itself in linked list of all in progress rows.
*
* @param jfId The last fetched filter id.
* @return The copy.
*/
private
JoinRow
copyBehind
(
int
jfId
)
{
assert
row
[
jfId
]
instanceof
Cursor
;
assert
isCursor
(
jfId
)
;
assert
jfId
+
1
==
row
.
length
||
row
[
jfId
+
1
]
==
null
;
Object
[]
r
=
new
Object
[
row
.
length
];
...
...
@@ -1522,6 +1595,7 @@ public class TableFilter implements ColumnResolver {
System
.
arraycopy
(
row
,
0
,
r
,
0
,
jfId
);
}
JoinRow
copy
=
new
JoinRow
(
r
);
copy
.
state
=
state
;
if
(
prev
!=
null
)
{
copy
.
prev
=
prev
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论