Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
0fd0134f
提交
0fd0134f
authored
7月 31, 2013
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Spatial index (work in progress)
上级
d23ee071
全部展开
显示空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
691 行增加
和
162 行删除
+691
-162
changelog.html
h2/src/docsrc/html/changelog.html
+2
-1
Parser.java
h2/src/main/org/h2/command/Parser.java
+6
-2
Comparison.java
h2/src/main/org/h2/expression/Comparison.java
+18
-8
IndexCondition.java
h2/src/main/org/h2/index/IndexCondition.java
+7
-0
IndexCursor.java
h2/src/main/org/h2/index/IndexCursor.java
+12
-11
SpatialTreeIndex.java
h2/src/main/org/h2/index/SpatialTreeIndex.java
+130
-68
Data.java
h2/src/main/org/h2/store/Data.java
+18
-24
RegularTable.java
h2/src/main/org/h2/table/RegularTable.java
+4
-4
DataType.java
h2/src/main/org/h2/value/DataType.java
+7
-1
Value.java
h2/src/main/org/h2/value/Value.java
+9
-0
ValueGeometry.java
h2/src/main/org/h2/value/ValueGeometry.java
+42
-33
TestSpatial.java
h2/src/test/org/h2/test/db/TestSpatial.java
+436
-10
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
0fd0134f
...
...
@@ -18,7 +18,8 @@ Change Log
<h1>
Change Log
</h1>
<h2>
Next Version (unreleased)
</h2>
<ul><li>
Issue 467: OSGi Class Loader (ability to create reference to class
<ul><li>
Improved spatial index and data type.
</li><li>
Issue 467: OSGi Class Loader (ability to create reference to class
in other ClassLoader, for example in another OSGi bundle).
</li></ul>
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
0fd0134f
...
...
@@ -4,8 +4,8 @@
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*
* N
. Fortin, Atelier SIG - IRSTV CNRS 2488:
* Support for the operator "&&" as an alias for SPATIAL_INTERSECTS
.
* N
icolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
* Support for the operator "&&" as an alias for SPATIAL_INTERSECTS
*/
package
org
.
h2
.
command
;
...
...
@@ -149,6 +149,10 @@ import org.h2.value.ValueTimestamp;
/**
* The parser is used to convert a SQL statement string to an command object.
*
* @author Thomas Mueller
* @author Noel Grandin
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
public
class
Parser
{
...
...
h2/src/main/org/h2/expression/Comparison.java
浏览文件 @
0fd0134f
...
...
@@ -22,6 +22,10 @@ import org.h2.value.ValueNull;
/**
* Example comparison expressions are ID=1, NAME=NAME, NAME IS NULL.
*
* @author Thomas Mueller
* @author Noel Grandin
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
public
class
Comparison
extends
Condition
{
...
...
@@ -102,7 +106,7 @@ public class Comparison extends Condition {
/**
* This is a comparison type that is only used for spatial index
* conditions.
* conditions
(operator "&&")
.
*/
public
static
final
int
SPATIAL_INTERSECTS
=
11
;
...
...
@@ -161,6 +165,8 @@ public class Comparison extends Condition {
return
"<>"
;
case
NOT_EQUAL_NULL_SAFE:
return
"IS NOT"
;
case
SPATIAL_INTERSECTS:
return
"&&"
;
default
:
throw
DbException
.
throwInternalError
(
"compareType="
+
compareType
);
}
...
...
@@ -285,7 +291,7 @@ public class Comparison extends Condition {
case
SPATIAL_INTERSECTS:
{
ValueGeometry
lg
=
(
ValueGeometry
)
l
.
convertTo
(
Value
.
GEOMETRY
);
ValueGeometry
rg
=
(
ValueGeometry
)
r
.
convertTo
(
Value
.
GEOMETRY
);
result
=
lg
.
intersects
(
rg
);
result
=
lg
.
intersects
BoundingBox
(
rg
);
break
;
}
default
:
...
...
@@ -300,6 +306,7 @@ public class Comparison extends Condition {
case
EQUAL_NULL_SAFE:
case
NOT_EQUAL:
case
NOT_EQUAL_NULL_SAFE:
case
SPATIAL_INTERSECTS:
return
type
;
case
BIGGER_EQUAL:
return
SMALLER_EQUAL
;
...
...
@@ -314,6 +321,15 @@ public class Comparison extends Condition {
}
}
@Override
public
Expression
getNotIfPossible
(
Session
session
)
{
if
(
compareType
==
SPATIAL_INTERSECTS
)
{
return
null
;
}
int
type
=
getNotCompareType
();
return
new
Comparison
(
session
,
type
,
left
,
right
);
}
private
int
getNotCompareType
()
{
switch
(
compareType
)
{
case
EQUAL:
...
...
@@ -341,12 +357,6 @@ public class Comparison extends Condition {
}
}
@Override
public
Expression
getNotIfPossible
(
Session
session
)
{
int
type
=
getNotCompareType
();
return
new
Comparison
(
session
,
type
,
left
,
right
);
}
@Override
public
void
createIndexConditions
(
Session
session
,
TableFilter
filter
)
{
ExpressionColumn
l
=
null
;
...
...
h2/src/main/org/h2/index/IndexCondition.java
浏览文件 @
0fd0134f
...
...
@@ -29,6 +29,10 @@ import org.h2.value.Value;
* A index condition object is made for each condition that can potentially use
* an index. This class does not extend expression, but in general there is one
* expression that maps to each index condition.
*
* @author Thomas Mueller
* @author Noel Grandin
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
public
class
IndexCondition
{
...
...
@@ -210,6 +214,9 @@ public class IndexCondition {
buff
.
append
(
expressionQuery
.
getPlanSQL
());
buff
.
append
(
')'
);
break
;
case
Comparison
.
SPATIAL_INTERSECTS
:
buff
.
append
(
" && "
);
break
;
default
:
DbException
.
throwInternalError
(
"type="
+
compareType
);
}
...
...
h2/src/main/org/h2/index/IndexCursor.java
浏览文件 @
0fd0134f
...
...
@@ -26,6 +26,10 @@ import org.h2.value.ValueNull;
/**
* The filter used to walk through an index. This class supports IN(..)
* and IN(SELECT ...) optimizations.
*
* @author Thomas Mueller
* @author Noel Grandin
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
public
class
IndexCursor
implements
Cursor
{
...
...
@@ -125,7 +129,7 @@ public class IndexCursor implements Cursor {
end
=
getSearchRow
(
end
,
columnId
,
v
,
false
);
}
if
(
isIntersects
)
{
intersects
=
getSpatialSearchRow
(
intersects
,
columnId
,
v
,
true
);
intersects
=
getSpatialSearchRow
(
intersects
,
columnId
,
v
);
}
if
(
isStart
||
isEnd
)
{
// an X=? condition will produce less rows than
...
...
@@ -148,8 +152,8 @@ public class IndexCursor implements Cursor {
return
;
}
if
(!
alwaysFalse
)
{
if
(
intersects
!=
null
&&
index
instanceof
Spatial
Tree
Index
)
{
cursor
=
((
Spatial
Tree
Index
)
index
).
findByGeometry
(
tableFilter
,
if
(
intersects
!=
null
&&
index
instanceof
SpatialIndex
)
{
cursor
=
((
SpatialIndex
)
index
).
findByGeometry
(
tableFilter
,
intersects
);
}
else
{
cursor
=
index
.
find
(
tableFilter
,
start
,
end
);
...
...
@@ -174,16 +178,13 @@ public class IndexCursor implements Cursor {
return
idxCol
==
null
||
idxCol
.
column
==
column
;
}
private
SearchRow
getSpatialSearchRow
(
SearchRow
row
,
int
columnId
,
Value
v
,
boolean
isIntersects
)
{
private
SearchRow
getSpatialSearchRow
(
SearchRow
row
,
int
columnId
,
Value
v
)
{
if
(
row
==
null
)
{
row
=
table
.
getTemplateRow
();
}
else
{
ValueGeometry
vg
=
(
ValueGeometry
)
row
.
getValue
(
columnId
);
if
(
isIntersects
)
{
v
=
((
ValueGeometry
)
v
).
intersection
(
vg
);
}
else
{
v
=
((
ValueGeometry
)
v
).
union
(
vg
);
}
}
else
if
(
row
.
getValue
(
columnId
)
!=
null
)
{
// the intersection of the two envelopes
ValueGeometry
vg
=
(
ValueGeometry
)
row
.
getValue
(
columnId
).
convertTo
(
Value
.
GEOMETRY
);
v
=
((
ValueGeometry
)
v
.
convertTo
(
Value
.
GEOMETRY
)).
getEnvelopeIntersection
(
vg
);
}
if
(
columnId
<
0
)
{
row
.
setKey
(
v
.
getLong
());
...
...
h2/src/main/org/h2/index/SpatialTreeIndex.java
浏览文件 @
0fd0134f
差异被折叠。
点击展开。
h2/src/main/org/h2/store/Data.java
浏览文件 @
0fd0134f
...
...
@@ -56,6 +56,10 @@ import org.h2.value.ValueUuid;
/**
* This class represents a byte buffer that contains persistent data of a page.
*
* @author Thomas Mueller
* @author Noel Grandin
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
public
class
Data
{
...
...
@@ -520,11 +524,13 @@ public class Data {
}
break
;
}
case
Value
.
GEOMETRY
:
case
Value
.
JAVA_OBJECT
:
{
writeByte
((
byte
)
type
);
byte
[]
b
=
v
.
getBytesNoCopy
();
writeVarInt
(
b
.
length
);
write
(
b
,
0
,
b
.
length
);
int
len
=
b
.
length
;
writeVarInt
(
len
);
write
(
b
,
0
,
len
);
break
;
}
case
Value
.
BYTES
:
{
...
...
@@ -532,11 +538,11 @@ public class Data {
int
len
=
b
.
length
;
if
(
len
<
32
)
{
writeByte
((
byte
)
(
BYTES_0_31
+
len
));
write
(
b
,
0
,
b
.
length
);
write
(
b
,
0
,
len
);
}
else
{
writeByte
((
byte
)
type
);
writeVarInt
(
b
.
length
);
write
(
b
,
0
,
b
.
length
);
writeVarInt
(
len
);
write
(
b
,
0
,
len
);
}
break
;
}
...
...
@@ -671,14 +677,6 @@ public class Data {
}
break
;
}
case
Value
.
GEOMETRY
:
{
writeByte
((
byte
)
type
);
byte
[]
b
=
v
.
getBytes
();
int
len
=
b
.
length
;
writeVarInt
(
len
);
write
(
b
,
0
,
len
);
break
;
}
default
:
DbException
.
throwInternalError
(
"type="
+
v
.
getType
());
}
...
...
@@ -764,6 +762,12 @@ public class Data {
read
(
b
,
0
,
len
);
return
ValueBytes
.
getNoCopy
(
b
);
}
case
Value
.
GEOMETRY
:
{
int
len
=
readVarInt
();
byte
[]
b
=
DataUtils
.
newBytes
(
len
);
read
(
b
,
0
,
len
);
return
ValueGeometry
.
get
(
b
);
}
case
Value
.
JAVA_OBJECT
:
{
int
len
=
readVarInt
();
byte
[]
b
=
DataUtils
.
newBytes
(
len
);
...
...
@@ -848,12 +852,6 @@ public class Data {
}
return
ValueResultSet
.
get
(
rs
);
}
case
Value
.
GEOMETRY
:
{
int
len
=
readVarInt
();
byte
[]
b
=
DataUtils
.
newBytes
(
len
);
read
(
b
,
0
,
len
);
return
ValueGeometry
.
get
(
b
);
}
default
:
if
(
type
>=
INT_0_15
&&
type
<
INT_0_15
+
16
)
{
return
ValueInt
.
get
(
type
-
INT_0_15
);
...
...
@@ -999,6 +997,7 @@ public class Data {
Timestamp
ts
=
v
.
getTimestamp
();
return
1
+
getVarLongLen
(
DateTimeUtils
.
getTimeLocalWithoutDst
(
ts
))
+
getVarIntLen
(
ts
.
getNanos
());
}
case
Value
.
GEOMETRY
:
case
Value
.
JAVA_OBJECT
:
{
byte
[]
b
=
v
.
getBytesNoCopy
();
return
1
+
getVarIntLen
(
b
.
length
)
+
b
.
length
;
...
...
@@ -1089,11 +1088,6 @@ public class Data {
}
return
len
;
}
case
Value
.
GEOMETRY
:
{
byte
[]
b
=
v
.
getBytesNoCopy
();
int
len
=
b
.
length
;
return
1
+
getVarIntLen
(
len
)
+
len
;
}
default
:
throw
DbException
.
throwInternalError
(
"type="
+
v
.
getType
());
}
...
...
h2/src/main/org/h2/table/RegularTable.java
浏览文件 @
0fd0134f
...
...
@@ -228,10 +228,10 @@ public class RegularTable extends TableBase {
if
(
mainIndexColumn
!=
-
1
)
{
mainIndex
.
setMainIndexColumn
(
mainIndexColumn
);
index
=
new
PageDelegateIndex
(
this
,
indexId
,
indexName
,
indexType
,
mainIndex
,
create
,
session
);
}
else
if
(
!
indexType
.
isSpatial
())
{
index
=
new
PageBtreeIndex
(
this
,
indexId
,
indexName
,
cols
,
indexTyp
e
,
create
,
session
);
}
else
if
(
indexType
.
isSpatial
())
{
index
=
new
SpatialTreeIndex
(
this
,
indexId
,
indexName
,
cols
,
indexType
,
tru
e
,
create
,
session
);
}
else
{
throw
new
UnsupportedOperationException
(
"Spatial index only supported with the MVStore"
);
index
=
new
PageBtreeIndex
(
this
,
indexId
,
indexName
,
cols
,
indexType
,
create
,
session
);
}
}
else
{
if
(
indexType
.
isHash
()
&&
cols
.
length
<=
1
)
{
...
...
@@ -243,7 +243,7 @@ public class RegularTable extends TableBase {
}
else
if
(!
indexType
.
isSpatial
())
{
index
=
new
TreeIndex
(
this
,
indexId
,
indexName
,
cols
,
indexType
);
}
else
{
index
=
new
SpatialTreeIndex
(
this
,
indexId
,
indexName
,
cols
,
indexType
);
index
=
new
SpatialTreeIndex
(
this
,
indexId
,
indexName
,
cols
,
indexType
,
false
,
true
,
session
);
}
}
if
(
database
.
isMultiVersion
())
{
...
...
h2/src/main/org/h2/value/DataType.java
浏览文件 @
0fd0134f
...
...
@@ -961,7 +961,13 @@ public class DataType {
}
}
private
static
boolean
isGeometry
(
Object
x
)
{
/**
* Check whether a given object is a Geometry object.
*
* @param x the the object
* @return true if it is a Geometry object
*/
public
static
boolean
isGeometry
(
Object
x
)
{
if
(
x
==
null
||
GEOMETRY_CLASS
==
null
)
{
return
false
;
}
...
...
h2/src/main/org/h2/value/Value.java
浏览文件 @
0fd0134f
...
...
@@ -34,6 +34,10 @@ import org.h2.util.Utils;
/**
* This is the base class for all value classes.
* It provides conversion and comparison methods.
*
* @author Thomas Mueller
* @author Noel Grandin
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
public
abstract
class
Value
{
...
...
@@ -793,6 +797,11 @@ public abstract class Value {
switch
(
getType
())
{
case
BYTES:
return
ValueGeometry
.
get
(
getBytesNoCopy
());
case
JAVA_OBJECT:
Object
object
=
Utils
.
deserialize
(
getBytesNoCopy
());
if
(
DataType
.
isGeometry
(
object
))
{
return
ValueGeometry
.
getFromGeometry
(
object
);
}
}
}
// conversion by parsing the string value
...
...
h2/src/main/org/h2/value/ValueGeometry.java
浏览文件 @
0fd0134f
...
...
@@ -11,7 +11,9 @@ import java.sql.SQLException;
import
org.h2.message.DbException
;
import
org.h2.util.StringUtils
;
import
com.vividsolutions.jts.geom.Envelope
;
import
com.vividsolutions.jts.geom.Geometry
;
import
com.vividsolutions.jts.geom.GeometryFactory
;
import
com.vividsolutions.jts.io.ParseException
;
import
com.vividsolutions.jts.io.WKBReader
;
import
com.vividsolutions.jts.io.WKBWriter
;
...
...
@@ -20,6 +22,10 @@ import com.vividsolutions.jts.io.WKTWriter;
/**
* Implementation of the GEOMETRY data type.
*
* @author Thomas Mueller
* @author Noel Grandin
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
public
class
ValueGeometry
extends
Value
{
...
...
@@ -71,33 +77,35 @@ public class ValueGeometry extends Value {
}
/**
* Check whether two values intersect.
* Test if this geometry envelope intersects with the other geometry
* envelope.
*
* @param r the
second value
* @return true if the
y intersect
* @param r the
other geometry
* @return true if the
two envelopes overlaps
*/
public
boolean
intersects
(
ValueGeometry
r
)
{
return
geometry
.
intersects
(
r
.
getGeometry
());
public
boolean
intersectsBoundingBox
(
ValueGeometry
r
)
{
// it is useless to cache the envelope as the Geometry object do this already
return
geometry
.
getEnvelopeInternal
().
intersects
(
r
.
getGeometry
().
getEnvelopeInternal
());
}
/**
* Get the intersection
of two values
.
* Get the intersection.
*
* @param r the
second value
* @return the intersection
* @param r the
other geometry
* @return the intersection
of this geometry envelope and another geometry envelope
*/
public
Value
intersection
(
ValueGeometry
r
)
{
return
get
(
geometry
.
intersection
(
r
.
geometry
));
public
ValueGeometry
getEnvelopeIntersection
(
ValueGeometry
r
)
{
Envelope
e1
=
geometry
.
getEnvelopeInternal
();
Envelope
e2
=
r
.
getGeometry
().
getEnvelopeInternal
();
Envelope
e3
=
e1
.
intersection
(
e2
);
// try to re-use the object
if
(
e3
==
e1
)
{
return
this
;
}
else
if
(
e3
==
e2
)
{
return
r
;
}
/**
* Get the union of two values.
*
* @param r the second value
* @return the union
*/
public
Value
union
(
ValueGeometry
r
)
{
return
get
(
geometry
.
union
(
r
.
geometry
));
GeometryFactory
gf
=
new
GeometryFactory
();
return
get
(
gf
.
toGeometry
(
e3
));
}
@Override
...
...
@@ -107,7 +115,7 @@ public class ValueGeometry extends Value {
@Override
public
String
getSQL
()
{
return
StringUtils
.
quoteStringSQL
(
toWKT
());
return
StringUtils
.
quoteStringSQL
(
toWKT
())
+
"'::Geometry"
;
}
@Override
...
...
@@ -141,6 +149,11 @@ public class ValueGeometry extends Value {
return
toWKB
();
}
@Override
public
byte
[]
getBytesNoCopy
()
{
return
toWKB
();
}
@Override
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setObject
(
parameterIndex
,
geometry
);
...
...
@@ -167,18 +180,16 @@ public class ValueGeometry extends Value {
* @return the well-known-text
*/
public
String
toWKT
()
{
WKTWriter
w
=
new
WKTWriter
();
return
w
.
write
(
geometry
);
return
new
WKTWriter
().
write
(
geometry
);
}
/**
* Convert to
value to the
Well-Known-Binary format.
* Convert to Well-Known-Binary format.
*
* @return the well-known-binary
*/
public
byte
[]
toWKB
()
{
WKBWriter
w
=
new
WKBWriter
();
return
w
.
write
(
geometry
);
return
new
WKBWriter
().
write
(
geometry
);
}
/**
...
...
@@ -188,9 +199,8 @@ public class ValueGeometry extends Value {
* @return the Geometry object
*/
private
static
Geometry
fromWKT
(
String
s
)
{
WKTReader
r
=
new
WKTReader
();
try
{
return
r
.
read
(
s
);
return
new
WKTReader
()
.
read
(
s
);
}
catch
(
ParseException
ex
)
{
throw
DbException
.
convert
(
ex
);
}
...
...
@@ -203,9 +213,8 @@ public class ValueGeometry extends Value {
* @return the Geometry object
*/
private
static
Geometry
fromWKB
(
byte
[]
bytes
)
{
WKBReader
r
=
new
WKBReader
();
try
{
return
r
.
read
(
bytes
);
return
new
WKBReader
()
.
read
(
bytes
);
}
catch
(
ParseException
ex
)
{
throw
DbException
.
convert
(
ex
);
}
...
...
h2/src/test/org/h2/test/db/TestSpatial.java
浏览文件 @
0fd0134f
差异被折叠。
点击展开。
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论