Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
fc22c549
提交
fc22c549
authored
5月 04, 2018
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add javadoc and some assertions
上级
7f7480d7
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
185 行增加
和
1 行删除
+185
-1
MVPlainTempResult.java
h2/src/main/org/h2/mvstore/db/MVPlainTempResult.java
+36
-0
MVSortedTempResult.java
h2/src/main/org/h2/mvstore/db/MVSortedTempResult.java
+104
-1
MVTempResult.java
h2/src/main/org/h2/mvstore/db/MVTempResult.java
+45
-0
没有找到文件。
h2/src/main/org/h2/mvstore/db/MVPlainTempResult.java
浏览文件 @
fc22c549
...
@@ -22,20 +22,54 @@ import org.h2.value.ValueLong;
...
@@ -22,20 +22,54 @@ import org.h2.value.ValueLong;
*/
*/
class
MVPlainTempResult
extends
MVTempResult
{
class
MVPlainTempResult
extends
MVTempResult
{
/**
* The type of the values in the main map and keys in the index.
*/
private
final
ValueDataType
valueType
;
private
final
ValueDataType
valueType
;
/**
* Map with identities of rows as keys rows as values.
*/
private
final
MVMap
<
ValueLong
,
ValueArray
>
map
;
private
final
MVMap
<
ValueLong
,
ValueArray
>
map
;
/**
* Counter for the identities of rows. A separate counter is used instead of
* {@link #rowCount} because rows due to presence of {@link #removeRow(Value[])}
* method to ensure that each row will have an own identity.
*/
private
long
counter
;
private
long
counter
;
/**
* Optional index. This index is created only if {@link #contains(Value[])}
* method is invoked. Only the root result should have an index if required.
*/
private
MVMap
<
ValueArray
,
Boolean
>
index
;
private
MVMap
<
ValueArray
,
Boolean
>
index
;
/**
* Cursor for the {@link #next()} method.
*/
private
Cursor
<
ValueLong
,
ValueArray
>
cursor
;
private
Cursor
<
ValueLong
,
ValueArray
>
cursor
;
/**
* Creates a shallow copy of the result.
*
* @param parent
* parent result
*/
private
MVPlainTempResult
(
MVPlainTempResult
parent
)
{
private
MVPlainTempResult
(
MVPlainTempResult
parent
)
{
super
(
parent
);
super
(
parent
);
this
.
valueType
=
null
;
this
.
valueType
=
null
;
this
.
map
=
parent
.
map
;
this
.
map
=
parent
.
map
;
}
}
/**
* Creates a new plain temporary result.
*
* @param session
* database session.
* @param expressions
* column expressions
*/
MVPlainTempResult
(
Session
session
,
Expression
[]
expressions
)
{
MVPlainTempResult
(
Session
session
,
Expression
[]
expressions
)
{
super
(
session
);
super
(
session
);
Database
db
=
session
.
getDatabase
();
Database
db
=
session
.
getDatabase
();
...
@@ -48,12 +82,14 @@ class MVPlainTempResult extends MVTempResult {
...
@@ -48,12 +82,14 @@ class MVPlainTempResult extends MVTempResult {
@Override
@Override
public
int
addRow
(
Value
[]
values
)
{
public
int
addRow
(
Value
[]
values
)
{
assert
parent
==
null
&&
index
==
null
;
map
.
put
(
ValueLong
.
get
(
counter
++),
ValueArray
.
get
(
values
));
map
.
put
(
ValueLong
.
get
(
counter
++),
ValueArray
.
get
(
values
));
return
++
rowCount
;
return
++
rowCount
;
}
}
@Override
@Override
public
boolean
contains
(
Value
[]
values
)
{
public
boolean
contains
(
Value
[]
values
)
{
// Only parent result maintains the index
if
(
parent
!=
null
)
{
if
(
parent
!=
null
)
{
return
parent
.
contains
(
values
);
return
parent
.
contains
(
values
);
}
}
...
...
h2/src/main/org/h2/mvstore/db/MVSortedTempResult.java
浏览文件 @
fc22c549
...
@@ -20,17 +20,53 @@ import org.h2.value.ValueArray;
...
@@ -20,17 +20,53 @@ import org.h2.value.ValueArray;
/**
/**
* Sorted temporary result.
* Sorted temporary result.
*
* <p>
* This result is used for distinct and/or sorted results.
* </p>
*/
*/
class
MVSortedTempResult
extends
MVTempResult
{
class
MVSortedTempResult
extends
MVTempResult
{
/**
* Whether this result is distinct.
*/
private
final
boolean
distinct
;
private
final
boolean
distinct
;
/**
* Mapping of indexes of columns to its positions in the store, or {@code null}
* if columns are not reordered.
*/
private
final
int
[]
indexes
;
private
final
int
[]
indexes
;
/**
* Map with rows as keys and counts of duplicate rows as values. If this map is
* distinct all values are 1.
*/
private
final
MVMap
<
ValueArray
,
Long
>
map
;
private
final
MVMap
<
ValueArray
,
Long
>
map
;
/**
* Cursor for the {@link #next()} method.
*/
private
Cursor
<
ValueArray
,
Long
>
cursor
;
private
Cursor
<
ValueArray
,
Long
>
cursor
;
/**
* Current value for the {@link #next()} method. Used in non-distinct results
* with duplicate rows.
*/
private
Value
[]
current
;
private
Value
[]
current
;
/**
* Count of remaining duplicate rows for the {@link #next()} method. Used in
* non-distinct results.
*/
private
long
valueCount
;
private
long
valueCount
;
/**
* Creates a shallow copy of the result.
*
* @param parent
* parent result
*/
private
MVSortedTempResult
(
MVSortedTempResult
parent
)
{
private
MVSortedTempResult
(
MVSortedTempResult
parent
)
{
super
(
parent
);
super
(
parent
);
this
.
distinct
=
parent
.
distinct
;
this
.
distinct
=
parent
.
distinct
;
...
@@ -41,6 +77,16 @@ class MVSortedTempResult extends MVTempResult {
...
@@ -41,6 +77,16 @@ class MVSortedTempResult extends MVTempResult {
/**
/**
* Creates a new sorted temporary result.
* Creates a new sorted temporary result.
*
* @param session
* database session
* @param expressions
* column expressions
* @param distinct
* whether this result should be distinct
* @param sort
* sort order, or {@code null} if this result does not
* need any sorting
*/
*/
MVSortedTempResult
(
Session
session
,
Expression
[]
expressions
,
boolean
distinct
,
SortOrder
sort
)
{
MVSortedTempResult
(
Session
session
,
Expression
[]
expressions
,
boolean
distinct
,
SortOrder
sort
)
{
super
(
session
);
super
(
session
);
...
@@ -50,31 +96,53 @@ class MVSortedTempResult extends MVTempResult {
...
@@ -50,31 +96,53 @@ class MVSortedTempResult extends MVTempResult {
int
[]
sortTypes
=
new
int
[
length
];
int
[]
sortTypes
=
new
int
[
length
];
int
[]
indexes
;
int
[]
indexes
;
if
(
sort
!=
null
)
{
if
(
sort
!=
null
)
{
/*
* If sorting is specified we need to reorder columns in requested order and set
* sort types (ASC, DESC etc) for them properly.
*/
indexes
=
new
int
[
length
];
indexes
=
new
int
[
length
];
int
[]
colIndex
=
sort
.
getQueryColumnIndexes
();
int
[]
colIndex
=
sort
.
getQueryColumnIndexes
();
int
len
=
colIndex
.
length
;
int
len
=
colIndex
.
length
;
// This set is used to remember columns that are already included
BitSet
used
=
new
BitSet
();
BitSet
used
=
new
BitSet
();
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
int
idx
=
colIndex
[
i
];
int
idx
=
colIndex
[
i
];
assert
!
used
.
get
(
idx
);
used
.
set
(
idx
);
used
.
set
(
idx
);
indexes
[
i
]
=
idx
;
indexes
[
i
]
=
idx
;
sortTypes
[
i
]
=
sort
.
getSortTypes
()[
i
];
sortTypes
[
i
]
=
sort
.
getSortTypes
()[
i
];
}
}
/*
* Because this result may have more columns than specified in sorting we need
* to add all remaining columns to the mapping of columns. A default sorting
* order (ASC / 0) will be used for them.
*/
int
idx
=
0
;
int
idx
=
0
;
for
(
int
i
=
len
;
i
<
length
;
i
++)
{
for
(
int
i
=
len
;
i
<
length
;
i
++)
{
idx
=
used
.
nextClearBit
(
idx
);
idx
=
used
.
nextClearBit
(
idx
);
indexes
[
i
]
=
idx
;
indexes
[
i
]
=
idx
;
idx
++;
idx
++;
}
}
/*
* Sometimes columns may be not reordered. Because reordering of columns
* slightly slows down other methods we check whether columns are really
* reordered or have the same order.
*/
sameOrder:
{
sameOrder:
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
if
(
indexes
[
i
]
!=
i
)
{
if
(
indexes
[
i
]
!=
i
)
{
// Columns are reordered
break
sameOrder
;
break
sameOrder
;
}
}
}
}
/*
* Columns are not reordered, set this field to null to disable reordering in
* other methods.
*/
indexes
=
null
;
indexes
=
null
;
}
}
}
else
{
}
else
{
// Columns are not reordered if sort order is not specified
indexes
=
null
;
indexes
=
null
;
}
}
this
.
indexes
=
indexes
;
this
.
indexes
=
indexes
;
...
@@ -85,14 +153,18 @@ class MVSortedTempResult extends MVTempResult {
...
@@ -85,14 +153,18 @@ class MVSortedTempResult extends MVTempResult {
@Override
@Override
public
int
addRow
(
Value
[]
values
)
{
public
int
addRow
(
Value
[]
values
)
{
assert
parent
==
null
;
ValueArray
key
=
getKey
(
values
);
ValueArray
key
=
getKey
(
values
);
if
(
distinct
)
{
if
(
distinct
)
{
// Add a row and increment the counter only if row does not exist
if
(
map
.
putIfAbsent
(
key
,
1L
)
==
null
)
{
if
(
map
.
putIfAbsent
(
key
,
1L
)
==
null
)
{
rowCount
++;
rowCount
++;
}
}
}
else
{
}
else
{
// Try to set counter to 1 first if such row does not exist yet
Long
old
=
map
.
putIfAbsent
(
key
,
1L
);
Long
old
=
map
.
putIfAbsent
(
key
,
1L
);
if
(
old
!=
null
)
{
if
(
old
!=
null
)
{
// This rows is already in the map, increment its own counter
map
.
put
(
key
,
old
+
1
);
map
.
put
(
key
,
old
+
1
);
}
}
rowCount
++;
rowCount
++;
...
@@ -117,6 +189,13 @@ class MVSortedTempResult extends MVTempResult {
...
@@ -117,6 +189,13 @@ class MVSortedTempResult extends MVTempResult {
return
new
MVSortedTempResult
(
this
);
return
new
MVSortedTempResult
(
this
);
}
}
/**
* Reorder values if required and convert them into {@link ValueArray}.
*
* @param values
* values
* @return ValueArray for maps
*/
private
ValueArray
getKey
(
Value
[]
values
)
{
private
ValueArray
getKey
(
Value
[]
values
)
{
if
(
indexes
!=
null
)
{
if
(
indexes
!=
null
)
{
Value
[]
r
=
new
Value
[
indexes
.
length
];
Value
[]
r
=
new
Value
[
indexes
.
length
];
...
@@ -128,6 +207,13 @@ class MVSortedTempResult extends MVTempResult {
...
@@ -128,6 +207,13 @@ class MVSortedTempResult extends MVTempResult {
return
ValueArray
.
get
(
values
);
return
ValueArray
.
get
(
values
);
}
}
/**
* Reorder values back if required.
*
* @param key
* reordered values
* @return original values
*/
private
Value
[]
getValue
(
Value
[]
key
)
{
private
Value
[]
getValue
(
Value
[]
key
)
{
if
(
indexes
!=
null
)
{
if
(
indexes
!=
null
)
{
Value
[]
r
=
new
Value
[
indexes
.
length
];
Value
[]
r
=
new
Value
[
indexes
.
length
];
...
@@ -146,22 +232,35 @@ class MVSortedTempResult extends MVTempResult {
...
@@ -146,22 +232,35 @@ class MVSortedTempResult extends MVTempResult {
current
=
null
;
current
=
null
;
valueCount
=
0L
;
valueCount
=
0L
;
}
}
// If we have multiple rows with the same values return them all
if
(--
valueCount
>
0
)
{
if
(--
valueCount
>
0
)
{
/*
* Underflow in valueCount is hypothetically possible after a lot of invocations
* (not really possible in practice), but current will be null anyway.
*/
return
current
;
return
current
;
}
}
current
=
null
;
if
(!
cursor
.
hasNext
())
{
if
(!
cursor
.
hasNext
())
{
// Set current to null to be sure
current
=
null
;
return
null
;
return
null
;
}
}
// Read the next row
current
=
getValue
(
cursor
.
next
().
getList
());
current
=
getValue
(
cursor
.
next
().
getList
());
/*
* If valueCount is greater than 1 that is possible for non-distinct results the
* following invocations of next() will use this.current and this.valueCount.
*/
valueCount
=
cursor
.
getValue
();
valueCount
=
cursor
.
getValue
();
return
current
;
return
current
;
}
}
@Override
@Override
public
int
removeRow
(
Value
[]
values
)
{
public
int
removeRow
(
Value
[]
values
)
{
assert
parent
==
null
;
ValueArray
key
=
getKey
(
values
);
ValueArray
key
=
getKey
(
values
);
if
(
distinct
)
{
if
(
distinct
)
{
// If an entry was removed decrement the counter
if
(
map
.
remove
(
key
)
!=
null
)
{
if
(
map
.
remove
(
key
)
!=
null
)
{
rowCount
--;
rowCount
--;
}
}
...
@@ -170,6 +269,10 @@ class MVSortedTempResult extends MVTempResult {
...
@@ -170,6 +269,10 @@ class MVSortedTempResult extends MVTempResult {
if
(
old
!=
null
)
{
if
(
old
!=
null
)
{
long
l
=
old
;
long
l
=
old
;
if
(
l
>
1
)
{
if
(
l
>
1
)
{
/*
* We have more than one such row. Decrement its counter by 1 and put this row
* back into map.
*/
map
.
put
(
key
,
l
-
1
);
map
.
put
(
key
,
l
-
1
);
}
}
rowCount
--;
rowCount
--;
...
...
h2/src/main/org/h2/mvstore/db/MVTempResult.java
浏览文件 @
fc22c549
...
@@ -23,6 +23,13 @@ import org.h2.value.Value;
...
@@ -23,6 +23,13 @@ import org.h2.value.Value;
/**
/**
* Temporary result.
* Temporary result.
*
* <p>
* A separate MVStore in a temporary file is used for each result. The file is
* removed when this result and all its copies are closed.
* {@link TempFileDeleter} is also used to delete this file if results are not
* closed properly.
* </p>
*/
*/
public
abstract
class
MVTempResult
implements
ResultExternal
{
public
abstract
class
MVTempResult
implements
ResultExternal
{
...
@@ -44,20 +51,52 @@ public abstract class MVTempResult implements ResultExternal {
...
@@ -44,20 +51,52 @@ public abstract class MVTempResult implements ResultExternal {
:
new
MVPlainTempResult
(
session
,
expressions
);
:
new
MVPlainTempResult
(
session
,
expressions
);
}
}
/**
* MVStore.
*/
final
MVStore
store
;
final
MVStore
store
;
/**
* Count of rows. Used only in a root results, copies always have 0 value.
*/
int
rowCount
;
int
rowCount
;
/**
* Parent store for copies. If {@code null} this result is a root result.
*/
final
MVTempResult
parent
;
final
MVTempResult
parent
;
/**
* Count of child results.
*/
int
childCount
;
int
childCount
;
/**
* Whether this result is closed.
*/
boolean
closed
;
boolean
closed
;
/**
* Temporary file deleter.
*/
private
final
TempFileDeleter
tempFileDeleter
;
private
final
TempFileDeleter
tempFileDeleter
;
/**
* Name of the temporary file.
*/
private
final
String
fileName
;
private
final
String
fileName
;
/**
* Reference to the record in the temporary file deleter.
*/
private
final
Reference
<?>
fileRef
;
private
final
Reference
<?>
fileRef
;
/**
* Creates a shallow copy of the result.
*
* @param parent
* parent result
*/
MVTempResult
(
MVTempResult
parent
)
{
MVTempResult
(
MVTempResult
parent
)
{
this
.
parent
=
parent
;
this
.
parent
=
parent
;
this
.
store
=
parent
.
store
;
this
.
store
=
parent
.
store
;
...
@@ -66,6 +105,12 @@ public abstract class MVTempResult implements ResultExternal {
...
@@ -66,6 +105,12 @@ public abstract class MVTempResult implements ResultExternal {
this
.
fileRef
=
null
;
this
.
fileRef
=
null
;
}
}
/**
* Creates a new temporary result.
*
* @param session
* database session
*/
MVTempResult
(
Session
session
)
{
MVTempResult
(
Session
session
)
{
try
{
try
{
fileName
=
FileUtils
.
createTempFile
(
"h2tmp"
,
Constants
.
SUFFIX_TEMP_FILE
,
false
,
true
);
fileName
=
FileUtils
.
createTempFile
(
"h2tmp"
,
Constants
.
SUFFIX_TEMP_FILE
,
false
,
true
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论