Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
df4cc289
提交
df4cc289
authored
9月 13, 2018
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add extended parameters for GEOMETRY data type
上级
e5098b56
显示空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
370 行增加
和
56 行删除
+370
-56
Parser.java
h2/src/main/org/h2/command/Parser.java
+27
-0
CreateTable.java
h2/src/main/org/h2/command/ddl/CreateTable.java
+8
-6
Column.java
h2/src/main/org/h2/table/Column.java
+6
-1
TableView.java
h2/src/main/org/h2/table/TableView.java
+2
-1
EWKBUtils.java
h2/src/main/org/h2/util/geometry/EWKBUtils.java
+29
-3
EWKTUtils.java
h2/src/main/org/h2/util/geometry/EWKTUtils.java
+99
-6
GeometryUtils.java
h2/src/main/org/h2/util/geometry/GeometryUtils.java
+7
-7
DataType.java
h2/src/main/org/h2/value/DataType.java
+22
-1
ExtTypeInfoGeometry.java
h2/src/main/org/h2/value/ExtTypeInfoGeometry.java
+68
-0
ValueGeometry.java
h2/src/main/org/h2/value/ValueGeometry.java
+63
-29
TestGeometryUtils.java
h2/src/test/org/h2/test/unit/TestGeometryUtils.java
+39
-2
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
df4cc289
...
@@ -194,10 +194,12 @@ import org.h2.util.ParserUtil;
...
@@ -194,10 +194,12 @@ import org.h2.util.ParserUtil;
import
org.h2.util.StatementBuilder
;
import
org.h2.util.StatementBuilder
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
import
org.h2.util.Utils
;
import
org.h2.util.Utils
;
import
org.h2.util.geometry.EWKTUtils
;
import
org.h2.value.CompareMode
;
import
org.h2.value.CompareMode
;
import
org.h2.value.DataType
;
import
org.h2.value.DataType
;
import
org.h2.value.ExtTypeInfo
;
import
org.h2.value.ExtTypeInfo
;
import
org.h2.value.ExtTypeInfoEnum
;
import
org.h2.value.ExtTypeInfoEnum
;
import
org.h2.value.ExtTypeInfoGeometry
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
import
org.h2.value.ValueBoolean
;
import
org.h2.value.ValueBoolean
;
import
org.h2.value.ValueBytes
;
import
org.h2.value.ValueBytes
;
...
@@ -5027,6 +5029,31 @@ public class Parser {
...
@@ -5027,6 +5029,31 @@ public class Parser {
}
}
original
+=
extTypeInfo
.
toString
();
original
+=
extTypeInfo
.
toString
();
}
}
}
else
if
(
dataType
.
type
==
Value
.
GEOMETRY
)
{
if
(
extTypeInfo
==
null
)
{
if
(
readIf
(
OPEN_PAREN
))
{
int
type
=
0
;
if
(
currentTokenType
==
IDENTIFIER
&&
!
currentTokenQuoted
)
{
try
{
type
=
EWKTUtils
.
parseGeometryType
(
currentToken
);
read
();
if
(
type
/
1_000
==
0
&&
currentTokenType
==
IDENTIFIER
&&
!
currentTokenQuoted
)
{
type
+=
EWKTUtils
.
parseDimensionSystem
(
currentToken
)
*
1_000
;
read
();
}
}
catch
(
IllegalArgumentException
ex
)
{
throw
getSyntaxError
();
}
}
Integer
srid
=
null
;
if
(
type
==
0
||
readIf
(
COMMA
))
{
srid
=
readInt
();
}
read
(
CLOSE_PAREN
);
extTypeInfo
=
new
ExtTypeInfoGeometry
(
type
,
srid
);
original
+=
extTypeInfo
.
toString
();
}
}
}
else
if
(
readIf
(
OPEN_PAREN
))
{
}
else
if
(
readIf
(
OPEN_PAREN
))
{
// Support for MySQL: INT(11), MEDIUMINT(8) and so on.
// Support for MySQL: INT(11), MEDIUMINT(8) and so on.
// Just ignore the precision.
// Just ignore the precision.
...
...
h2/src/main/org/h2/command/ddl/CreateTable.java
浏览文件 @
df4cc289
...
@@ -199,15 +199,17 @@ public class CreateTable extends CommandWithColumns {
...
@@ -199,15 +199,17 @@ public class CreateTable extends CommandWithColumns {
precision
=
scale
;
precision
=
scale
;
}
}
ExtTypeInfo
extTypeInfo
=
null
;
ExtTypeInfo
extTypeInfo
=
null
;
if
(
dt
.
type
==
Value
.
ENUM
)
{
int
t
=
dt
.
type
;
/**
if
(
DataType
.
isExtInfoType
(
t
))
{
if
(
expr
instanceof
ExpressionColumn
)
{
extTypeInfo
=
((
ExpressionColumn
)
expr
).
getColumn
().
getExtTypeInfo
();
}
else
if
(
t
==
Value
.
ENUM
)
{
/*
* Only columns of tables may be enumerated.
* Only columns of tables may be enumerated.
*/
*/
if
(!(
expr
instanceof
ExpressionColumn
))
{
throw
DbException
.
get
(
ErrorCode
.
GENERAL_ERROR_1
,
throw
DbException
.
get
(
ErrorCode
.
GENERAL_ERROR_1
,
"Unable to resolve enumerators of expression"
);
"Unable to resolve enumerators of expression"
);
}
}
extTypeInfo
=
((
ExpressionColumn
)
expr
).
getColumn
().
getExtTypeInfo
();
}
}
Column
col
=
new
Column
(
name
,
type
,
precision
,
scale
,
displaySize
,
extTypeInfo
);
Column
col
=
new
Column
(
name
,
type
,
precision
,
scale
,
displaySize
,
extTypeInfo
);
addColumn
(
col
);
addColumn
(
col
);
...
...
h2/src/main/org/h2/table/Column.java
浏览文件 @
df4cc289
...
@@ -402,7 +402,7 @@ public class Column {
...
@@ -402,7 +402,7 @@ public class Column {
getCreateSQL
(),
s
+
" ("
+
value
.
getPrecision
()
+
")"
);
getCreateSQL
(),
s
+
" ("
+
value
.
getPrecision
()
+
")"
);
}
}
}
}
if
(
type
==
Value
.
ENUM
&&
value
!=
ValueNull
.
INSTANCE
)
{
if
(
value
!=
ValueNull
.
INSTANCE
&&
DataType
.
isExtInfoType
(
type
)
&&
extTypeInfo
!=
null
)
{
value
=
extTypeInfo
.
cast
(
value
);
value
=
extTypeInfo
.
cast
(
value
);
}
}
updateSequenceIfRequired
(
session
,
value
);
updateSequenceIfRequired
(
session
,
value
);
...
@@ -509,6 +509,11 @@ public class Column {
...
@@ -509,6 +509,11 @@ public class Column {
case
Value
.
DECIMAL
:
case
Value
.
DECIMAL
:
buff
.
append
(
'('
).
append
(
precision
).
append
(
", "
).
append
(
scale
).
append
(
')'
);
buff
.
append
(
'('
).
append
(
precision
).
append
(
", "
).
append
(
scale
).
append
(
')'
);
break
;
break
;
case
Value
.
GEOMETRY
:
if
(
extTypeInfo
==
null
)
{
break
;
}
//$FALL-THROUGH$
case
Value
.
ENUM
:
case
Value
.
ENUM
:
buff
.
append
(
extTypeInfo
.
toString
());
buff
.
append
(
extTypeInfo
.
toString
());
break
;
break
;
...
...
h2/src/main/org/h2/table/TableView.java
浏览文件 @
df4cc289
...
@@ -38,6 +38,7 @@ import org.h2.util.ColumnNamer;
...
@@ -38,6 +38,7 @@ import org.h2.util.ColumnNamer;
import
org.h2.util.StatementBuilder
;
import
org.h2.util.StatementBuilder
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
import
org.h2.util.Utils
;
import
org.h2.util.Utils
;
import
org.h2.value.DataType
;
import
org.h2.value.ExtTypeInfo
;
import
org.h2.value.ExtTypeInfo
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
...
@@ -196,7 +197,7 @@ public class TableView extends Table {
...
@@ -196,7 +197,7 @@ public class TableView extends Table {
int
scale
=
expr
.
getScale
();
int
scale
=
expr
.
getScale
();
int
displaySize
=
expr
.
getDisplaySize
();
int
displaySize
=
expr
.
getDisplaySize
();
ExtTypeInfo
extTypeInfo
=
null
;
ExtTypeInfo
extTypeInfo
=
null
;
if
(
type
==
Value
.
ENUM
)
{
if
(
DataType
.
isExtInfoType
(
type
)
)
{
if
(
expr
instanceof
ExpressionColumn
)
{
if
(
expr
instanceof
ExpressionColumn
)
{
extTypeInfo
=
((
ExpressionColumn
)
expr
).
getColumn
().
getExtTypeInfo
();
extTypeInfo
=
((
ExpressionColumn
)
expr
).
getColumn
().
getExtTypeInfo
();
}
}
...
...
h2/src/main/org/h2/util/geometry/EWKBUtils.java
浏览文件 @
df4cc289
...
@@ -233,17 +233,17 @@ public final class EWKBUtils {
...
@@ -233,17 +233,17 @@ public final class EWKBUtils {
/**
/**
* Geometry type mask that indicates presence of dimension Z.
* Geometry type mask that indicates presence of dimension Z.
*/
*/
p
rivate
static
final
int
EWKB_Z
=
0x8000_0000
;
p
ublic
static
final
int
EWKB_Z
=
0x8000_0000
;
/**
/**
* Geometry type mask that indicates presence of dimension M.
* Geometry type mask that indicates presence of dimension M.
*/
*/
p
rivate
static
final
int
EWKB_M
=
0x4000_0000
;
p
ublic
static
final
int
EWKB_M
=
0x4000_0000
;
/**
/**
* Geometry type mask that indicates presence of SRID.
* Geometry type mask that indicates presence of SRID.
*/
*/
p
rivate
static
final
int
EWKB_SRID
=
0x2000_0000
;
p
ublic
static
final
int
EWKB_SRID
=
0x2000_0000
;
/**
/**
* Converts any supported EWKB to EWKB representation that is used by this
* Converts any supported EWKB to EWKB representation that is used by this
...
@@ -296,6 +296,32 @@ public final class EWKBUtils {
...
@@ -296,6 +296,32 @@ public final class EWKBUtils {
}
}
}
}
/**
* Converts geometry type with flags to a dimension system.
*
* @param type
* geometry type with flags
* @return dimension system
*/
public
static
int
type2dimensionSystem
(
int
type
)
{
// PostGIS extensions
boolean
useZ
=
(
type
&
EWKB_Z
)
!=
0
;
boolean
useM
=
(
type
&
EWKB_M
)
!=
0
;
// OGC 06-103r4
type
&=
0xffff
;
switch
(
type
/
1_000
)
{
case
DIMENSION_SYSTEM_XYZ:
useZ
=
true
;
break
;
case
DIMENSION_SYSTEM_XYZM:
useZ
=
true
;
//$FALL-THROUGH$
case
DIMENSION_SYSTEM_XYM:
useM
=
true
;
}
return
(
useZ
?
DIMENSION_SYSTEM_XYZ
:
0
)
|
(
useM
?
DIMENSION_SYSTEM_XYM
:
0
);
}
/**
/**
* Parses a EWKB.
* Parses a EWKB.
*
*
...
...
h2/src/main/org/h2/util/geometry/EWKTUtils.java
浏览文件 @
df4cc289
...
@@ -41,6 +41,30 @@ import org.h2.util.geometry.GeometryUtils.Target;
...
@@ -41,6 +41,30 @@ import org.h2.util.geometry.GeometryUtils.Target;
*/
*/
public
final
class
EWKTUtils
{
public
final
class
EWKTUtils
{
/**
* 0-based type names of geometries, subtract 1 from type code to get index
* in this array.
*/
private
static
final
String
[]
TYPES
=
{
//
"POINT"
,
//
"LINESTRING"
,
//
"POLYGON"
,
//
"MULTIPOINT"
,
//
"MULTILINESTRING"
,
//
"MULTIPOLYGON"
,
//
"GEOMETRYCOLLECTION"
,
//
};
/**
* Names of dimension systems.
*/
private
static
final
String
[]
DIMENSION_SYTEMS
=
{
//
"XY"
,
//
"Z"
,
//
"M"
,
//
"ZM"
,
//
};
/**
/**
* Converter output target that writes a EWKT.
* Converter output target that writes a EWKT.
*/
*/
...
@@ -328,7 +352,7 @@ public final class EWKTUtils {
...
@@ -328,7 +352,7 @@ public final class EWKTUtils {
int
o
=
offset
;
int
o
=
offset
;
skipWS
();
skipWS
();
int
len
=
ewkt
.
length
();
int
len
=
ewkt
.
length
();
if
(
offset
>
len
-
2
)
{
if
(
offset
>
=
len
)
{
throw
new
IllegalArgumentException
();
throw
new
IllegalArgumentException
();
}
}
int
result
;
int
result
;
...
@@ -342,6 +366,9 @@ public final class EWKTUtils {
...
@@ -342,6 +366,9 @@ public final class EWKTUtils {
case
'Z'
:
case
'Z'
:
case
'z'
:
case
'z'
:
offset
++;
offset
++;
if
(
offset
>=
len
)
{
result
=
DIMENSION_SYSTEM_XYZ
;
}
else
{
ch
=
ewkt
.
charAt
(
offset
);
ch
=
ewkt
.
charAt
(
offset
);
if
(
ch
==
'M'
||
ch
==
'm'
)
{
if
(
ch
==
'M'
||
ch
==
'm'
)
{
offset
++;
offset
++;
...
@@ -349,6 +376,7 @@ public final class EWKTUtils {
...
@@ -349,6 +376,7 @@ public final class EWKTUtils {
}
else
{
}
else
{
result
=
DIMENSION_SYSTEM_XYZ
;
result
=
DIMENSION_SYSTEM_XYZ
;
}
}
}
break
;
break
;
default
:
default
:
result
=
DIMENSION_SYSTEM_XY
;
result
=
DIMENSION_SYSTEM_XY
;
...
@@ -589,6 +617,71 @@ public final class EWKTUtils {
...
@@ -589,6 +617,71 @@ public final class EWKTUtils {
parseEWKT
(
new
EWKTSource
(
ewkt
),
target
,
0
,
0
);
parseEWKT
(
new
EWKTSource
(
ewkt
),
target
,
0
,
0
);
}
}
/**
* Parses geometry type and dimension system from the given string.
*
* @param s
* string to parse
* @return geometry type and dimension system in OGC geometry code format
* (type + dimensionSystem * 1000)
* @throws IllegalArgumentException
* if input is not valid
*/
public
static
int
parseGeometryType
(
String
s
)
{
EWKTSource
source
=
new
EWKTSource
(
s
);
int
type
=
source
.
readType
();
int
dimensionSystem
=
0
;
if
(
source
.
hasData
())
{
dimensionSystem
=
source
.
readDimensionSystem
();
if
(
source
.
hasData
())
{
throw
new
IllegalArgumentException
();
}
}
return
dimensionSystem
*
1_000
+
type
;
}
/**
* Parses a dimension system from the given string.
*
* @param s
* string to parse
* @return dimension system, one of XYZ, XYM, or XYZM
* @see GeometryUtils#DIMENSION_SYSTEM_XYZ
* @see GeometryUtils#DIMENSION_SYSTEM_XYM
* @see GeometryUtils#DIMENSION_SYSTEM_XYZM
* @throws IllegalArgumentException
* if input is not valid
*/
public
static
int
parseDimensionSystem
(
String
s
)
{
EWKTSource
source
=
new
EWKTSource
(
s
);
int
dimensionSystem
=
source
.
readDimensionSystem
();
if
(
source
.
hasData
()
||
dimensionSystem
==
DIMENSION_SYSTEM_XY
)
{
throw
new
IllegalArgumentException
();
}
return
dimensionSystem
;
}
/**
* Formats type and dimension system as a string.
*
* @param type
* OGC geometry code format (type + dimensionSystem * 1000)
* @return formatted string
* @throws IllegalArgumentException
* if type is not valid
*/
public
static
String
formatGeometryTypeAndDimensionSystem
(
int
type
)
{
int
t
=
type
%
1_000
,
d
=
type
/
1_000
;
if
(
t
<
POINT
||
t
>
GEOMETRY_COLLECTION
||
d
<
DIMENSION_SYSTEM_XY
||
d
>
DIMENSION_SYSTEM_XYZM
)
{
throw
new
IllegalArgumentException
();
}
String
result
=
TYPES
[
t
-
1
];
if
(
d
!=
DIMENSION_SYSTEM_XY
)
{
result
=
result
+
' '
+
DIMENSION_SYTEMS
[
d
];
}
return
result
;
}
/**
/**
* Parses a EWKB.
* Parses a EWKB.
*
*
...
...
h2/src/main/org/h2/util/geometry/GeometryUtils.java
浏览文件 @
df4cc289
...
@@ -362,37 +362,37 @@ public final class GeometryUtils {
...
@@ -362,37 +362,37 @@ public final class GeometryUtils {
/**
/**
* POINT geometry type.
* POINT geometry type.
*/
*/
static
final
int
POINT
=
1
;
public
static
final
int
POINT
=
1
;
/**
/**
* LINESTRING geometry type.
* LINESTRING geometry type.
*/
*/
static
final
int
LINE_STRING
=
2
;
public
static
final
int
LINE_STRING
=
2
;
/**
/**
* POLYGON geometry type.
* POLYGON geometry type.
*/
*/
static
final
int
POLYGON
=
3
;
public
static
final
int
POLYGON
=
3
;
/**
/**
* MULTIPOINT geometry type.
* MULTIPOINT geometry type.
*/
*/
static
final
int
MULTI_POINT
=
4
;
public
static
final
int
MULTI_POINT
=
4
;
/**
/**
* MULTILINESTRING geometry type.
* MULTILINESTRING geometry type.
*/
*/
static
final
int
MULTI_LINE_STRING
=
5
;
public
static
final
int
MULTI_LINE_STRING
=
5
;
/**
/**
* MULTIPOLYGON geometry type.
* MULTIPOLYGON geometry type.
*/
*/
static
final
int
MULTI_POLYGON
=
6
;
public
static
final
int
MULTI_POLYGON
=
6
;
/**
/**
* GEOMETRYCOLLECTION geometry type.
* GEOMETRYCOLLECTION geometry type.
*/
*/
static
final
int
GEOMETRY_COLLECTION
=
7
;
public
static
final
int
GEOMETRY_COLLECTION
=
7
;
/**
/**
* Number of X coordinate.
* Number of X coordinate.
...
...
h2/src/main/org/h2/value/DataType.java
浏览文件 @
df4cc289
...
@@ -358,7 +358,7 @@ public class DataType {
...
@@ -358,7 +358,7 @@ public class DataType {
104
104
);
);
add
(
Value
.
GEOMETRY
,
Types
.
OTHER
,
add
(
Value
.
GEOMETRY
,
Types
.
OTHER
,
create
String
(
false
),
create
Geometry
(
),
new
String
[]{
"GEOMETRY"
},
new
String
[]{
"GEOMETRY"
},
32
32
);
);
...
@@ -548,6 +548,17 @@ public class DataType {
...
@@ -548,6 +548,17 @@ public class DataType {
return
t
;
return
t
;
}
}
private
static
DataType
createGeometry
()
{
DataType
dataType
=
new
DataType
();
dataType
.
prefix
=
"'"
;
dataType
.
suffix
=
"'"
;
dataType
.
params
=
"TYPE,SRID"
;
dataType
.
maxPrecision
=
Integer
.
MAX_VALUE
;
dataType
.
defaultPrecision
=
Integer
.
MAX_VALUE
;
dataType
.
defaultDisplaySize
=
Integer
.
MAX_VALUE
;
return
dataType
;
}
/**
/**
* Get the list of data types.
* Get the list of data types.
*
*
...
@@ -1403,6 +1414,16 @@ public class DataType {
...
@@ -1403,6 +1414,16 @@ public class DataType {
return
type
==
Value
.
STRING
||
type
==
Value
.
STRING_FIXED
||
type
==
Value
.
STRING_IGNORECASE
;
return
type
==
Value
.
STRING
||
type
==
Value
.
STRING_FIXED
||
type
==
Value
.
STRING_IGNORECASE
;
}
}
/**
* Check if the given type may have extended type information.
*
* @param type the value type
* @return true if the value type may have extended type information
*/
public
static
boolean
isExtInfoType
(
int
type
)
{
return
type
==
Value
.
GEOMETRY
||
type
==
Value
.
ENUM
;
}
/**
/**
* Check if the given value type supports the add operation.
* Check if the given value type supports the add operation.
*
*
...
...
h2/src/main/org/h2/value/ExtTypeInfoGeometry.java
0 → 100644
浏览文件 @
df4cc289
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
org.h2.api.ErrorCode
;
import
org.h2.message.DbException
;
import
org.h2.util.geometry.EWKTUtils
;
/**
* Extended parameters of the GEOMETRY data type.
*/
public
final
class
ExtTypeInfoGeometry
extends
ExtTypeInfo
{
private
final
int
type
;
private
final
Integer
srid
;
private
static
String
toString
(
int
type
,
Integer
srid
)
{
if
(
type
==
0
&&
srid
==
null
)
{
return
""
;
}
StringBuilder
builder
=
new
StringBuilder
();
builder
.
append
(
'('
);
if
(
type
!=
0
)
{
builder
.
append
(
EWKTUtils
.
formatGeometryTypeAndDimensionSystem
(
type
));
}
if
(
srid
!=
null
)
{
if
(
type
!=
0
)
{
builder
.
append
(
", "
);
}
builder
.
append
((
int
)
srid
);
}
return
builder
.
append
(
')'
).
toString
();
}
/**
* Creates new instance of extended parameters of the GEOMETRY data type.
*
* @param type
* the type and dimension system of geometries, or 0 if not
* constrained
* @param srid
* the SRID of geometries, or {@code null} if not constrained
*/
public
ExtTypeInfoGeometry
(
int
type
,
Integer
srid
)
{
this
.
type
=
type
;
this
.
srid
=
srid
;
}
@Override
public
Value
cast
(
Value
value
)
{
ValueGeometry
g
=
(
ValueGeometry
)
value
.
convertTo
(
Value
.
GEOMETRY
);
if
(
type
!=
0
&&
g
.
getTypeAndDimensionSystem
()
!=
type
||
srid
!=
null
&&
g
.
getSRID
()
!=
srid
)
{
throw
DbException
.
get
(
ErrorCode
.
CHECK_CONSTRAINT_VIOLATED_1
,
toString
(
g
.
getTypeAndDimensionSystem
(),
g
.
getSRID
())
+
" <> "
+
toString
());
}
return
g
;
}
@Override
public
String
toString
()
{
return
toString
(
type
,
srid
);
}
}
h2/src/main/org/h2/value/ValueGeometry.java
浏览文件 @
df4cc289
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
*/
*/
package
org
.
h2
.
value
;
package
org
.
h2
.
value
;
import
static
org
.
h2
.
util
.
geometry
.
EWKBUtils
.
EWKB_SRID
;
import
java.sql.PreparedStatement
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
java.util.Arrays
;
import
java.util.Arrays
;
...
@@ -18,6 +19,7 @@ import org.h2.util.geometry.EWKBUtils;
...
@@ -18,6 +19,7 @@ import org.h2.util.geometry.EWKBUtils;
import
org.h2.util.geometry.EWKTUtils
;
import
org.h2.util.geometry.EWKTUtils
;
import
org.h2.util.geometry.GeometryUtils
;
import
org.h2.util.geometry.GeometryUtils
;
import
org.h2.util.geometry.GeometryUtils.EnvelopeAndDimensionSystemTarget
;
import
org.h2.util.geometry.GeometryUtils.EnvelopeAndDimensionSystemTarget
;
import
org.h2.util.geometry.GeometryUtils.EnvelopeTarget
;
import
org.h2.util.geometry.JTSUtils
;
import
org.h2.util.geometry.JTSUtils
;
import
org.locationtech.jts.geom.Geometry
;
import
org.locationtech.jts.geom.Geometry
;
...
@@ -30,6 +32,8 @@ import org.locationtech.jts.geom.Geometry;
...
@@ -30,6 +32,8 @@ import org.locationtech.jts.geom.Geometry;
*/
*/
public
class
ValueGeometry
extends
Value
{
public
class
ValueGeometry
extends
Value
{
private
static
final
double
[]
UNKNOWN_ENVELOPE
=
new
double
[
0
];
/**
/**
* As conversion from/to WKB cost a significant amount of CPU cycles, WKB
* As conversion from/to WKB cost a significant amount of CPU cycles, WKB
* are kept in ValueGeometry instance.
* are kept in ValueGeometry instance.
...
@@ -43,9 +47,15 @@ public class ValueGeometry extends Value {
...
@@ -43,9 +47,15 @@ public class ValueGeometry extends Value {
private
final
int
hashCode
;
private
final
int
hashCode
;
/**
/**
* Dimension system. -1 if not known yet.
* Geometry type and dimension system in OGC geometry code format (type +
* dimensionSystem * 1000).
*/
private
final
int
typeAndDimensionSystem
;
/**
* Spatial reference system identifier.
*/
*/
private
int
dimensionSystem
;
private
final
int
srid
;
/**
/**
* The envelope of the value. Calculated only on request.
* The envelope of the value. Calculated only on request.
...
@@ -62,14 +72,18 @@ public class ValueGeometry extends Value {
...
@@ -62,14 +72,18 @@ public class ValueGeometry extends Value {
* Create a new geometry object.
* Create a new geometry object.
*
*
* @param bytes the EWKB bytes
* @param bytes the EWKB bytes
* @param dimensionSystem dimension system
* @param envelope the envelope
* @param envelope the envelope
*/
*/
private
ValueGeometry
(
byte
[]
bytes
,
int
dimensionSystem
,
double
[]
envelope
)
{
private
ValueGeometry
(
byte
[]
bytes
,
double
[]
envelope
)
{
if
(
bytes
.
length
<
9
||
bytes
[
0
]
!=
0
)
{
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
StringUtils
.
convertBytesToHex
(
bytes
));
}
this
.
bytes
=
bytes
;
this
.
bytes
=
bytes
;
this
.
hashCode
=
Arrays
.
hashCode
(
bytes
);
this
.
dimensionSystem
=
dimensionSystem
;
this
.
envelope
=
envelope
;
this
.
envelope
=
envelope
;
int
t
=
Bits
.
readInt
(
bytes
,
1
);
srid
=
(
t
&
EWKB_SRID
)
!=
0
?
Bits
.
readInt
(
bytes
,
5
)
:
0
;
typeAndDimensionSystem
=
(
t
&
0xffff
)
%
1_000
+
EWKBUtils
.
type2dimensionSystem
(
t
)
*
1_000
;
hashCode
=
Arrays
.
hashCode
(
bytes
);
}
}
/**
/**
...
@@ -84,9 +98,8 @@ public class ValueGeometry extends Value {
...
@@ -84,9 +98,8 @@ public class ValueGeometry extends Value {
EnvelopeAndDimensionSystemTarget
target
=
new
EnvelopeAndDimensionSystemTarget
();
EnvelopeAndDimensionSystemTarget
target
=
new
EnvelopeAndDimensionSystemTarget
();
Geometry
g
=
(
Geometry
)
o
;
Geometry
g
=
(
Geometry
)
o
;
JTSUtils
.
parseGeometry
(
g
,
target
);
JTSUtils
.
parseGeometry
(
g
,
target
);
int
dimensionSystem
=
target
.
getDimensionSystem
();
return
(
ValueGeometry
)
Value
.
cache
(
new
ValueGeometry
(
//
return
(
ValueGeometry
)
Value
.
cache
(
new
ValueGeometry
(
JTSUtils
.
geometry2ewkb
(
g
,
dimensionSystem
),
JTSUtils
.
geometry2ewkb
(
g
,
target
.
getDimensionSystem
()),
target
.
getEnvelope
()));
dimensionSystem
,
target
.
getEnvelope
()));
}
catch
(
RuntimeException
ex
)
{
}
catch
(
RuntimeException
ex
)
{
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
String
.
valueOf
(
o
));
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
String
.
valueOf
(
o
));
}
}
...
@@ -102,9 +115,8 @@ public class ValueGeometry extends Value {
...
@@ -102,9 +115,8 @@ public class ValueGeometry extends Value {
try
{
try
{
EnvelopeAndDimensionSystemTarget
target
=
new
EnvelopeAndDimensionSystemTarget
();
EnvelopeAndDimensionSystemTarget
target
=
new
EnvelopeAndDimensionSystemTarget
();
EWKTUtils
.
parseEWKT
(
s
,
target
);
EWKTUtils
.
parseEWKT
(
s
,
target
);
int
dimensionSystem
=
target
.
getDimensionSystem
();
return
(
ValueGeometry
)
Value
.
cache
(
new
ValueGeometry
(
//
return
(
ValueGeometry
)
Value
.
cache
(
new
ValueGeometry
(
EWKTUtils
.
ewkt2ewkb
(
s
,
dimensionSystem
),
EWKTUtils
.
ewkt2ewkb
(
s
,
target
.
getDimensionSystem
()),
target
.
getEnvelope
()));
dimensionSystem
,
target
.
getEnvelope
()));
}
catch
(
RuntimeException
ex
)
{
}
catch
(
RuntimeException
ex
)
{
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
s
);
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
s
);
}
}
...
@@ -129,7 +141,7 @@ public class ValueGeometry extends Value {
...
@@ -129,7 +141,7 @@ public class ValueGeometry extends Value {
* @return the value
* @return the value
*/
*/
public
static
ValueGeometry
get
(
byte
[]
bytes
)
{
public
static
ValueGeometry
get
(
byte
[]
bytes
)
{
return
(
ValueGeometry
)
Value
.
cache
(
new
ValueGeometry
(
bytes
,
-
1
,
null
));
return
(
ValueGeometry
)
Value
.
cache
(
new
ValueGeometry
(
bytes
,
UNKNOWN_ENVELOPE
));
}
}
/**
/**
...
@@ -142,9 +154,8 @@ public class ValueGeometry extends Value {
...
@@ -142,9 +154,8 @@ public class ValueGeometry extends Value {
try
{
try
{
EnvelopeAndDimensionSystemTarget
target
=
new
EnvelopeAndDimensionSystemTarget
();
EnvelopeAndDimensionSystemTarget
target
=
new
EnvelopeAndDimensionSystemTarget
();
EWKBUtils
.
parseEWKB
(
bytes
,
target
);
EWKBUtils
.
parseEWKB
(
bytes
,
target
);
int
dimensionSystem
=
target
.
getDimensionSystem
();
return
(
ValueGeometry
)
Value
.
cache
(
new
ValueGeometry
(
//
return
(
ValueGeometry
)
Value
.
cache
(
new
ValueGeometry
(
EWKBUtils
.
ewkb2ewkb
(
bytes
,
dimensionSystem
),
EWKBUtils
.
ewkb2ewkb
(
bytes
,
target
.
getDimensionSystem
()),
target
.
getEnvelope
()));
dimensionSystem
,
target
.
getEnvelope
()));
}
catch
(
RuntimeException
ex
)
{
}
catch
(
RuntimeException
ex
)
{
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
StringUtils
.
convertBytesToHex
(
bytes
));
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
StringUtils
.
convertBytesToHex
(
bytes
));
}
}
...
@@ -158,8 +169,7 @@ public class ValueGeometry extends Value {
...
@@ -158,8 +169,7 @@ public class ValueGeometry extends Value {
*/
*/
public
static
Value
fromEnvelope
(
double
[]
envelope
)
{
public
static
Value
fromEnvelope
(
double
[]
envelope
)
{
return
envelope
!=
null
return
envelope
!=
null
?
Value
.
cache
(
new
ValueGeometry
(
EWKBUtils
.
envelope2wkb
(
envelope
),
GeometryUtils
.
DIMENSION_SYSTEM_XY
,
?
Value
.
cache
(
new
ValueGeometry
(
EWKBUtils
.
envelope2wkb
(
envelope
),
envelope
))
envelope
))
:
ValueNull
.
INSTANCE
;
:
ValueNull
.
INSTANCE
;
}
}
...
@@ -180,13 +190,23 @@ public class ValueGeometry extends Value {
...
@@ -180,13 +190,23 @@ public class ValueGeometry extends Value {
return
((
Geometry
)
geometry
).
copy
();
return
((
Geometry
)
geometry
).
copy
();
}
}
private
void
calculateInfo
()
{
/**
if
(
dimensionSystem
<
0
)
{
* Returns geometry type and dimension system in OGC geometry code format
EnvelopeAndDimensionSystemTarget
target
=
new
EnvelopeAndDimensionSystemTarget
();
* (type + dimensionSystem * 1000).
EWKBUtils
.
parseEWKB
(
bytes
,
target
);
*
envelope
=
target
.
getEnvelope
();
* @return geometry type and dimension system
dimensionSystem
=
target
.
getDimensionSystem
();
*/
public
int
getTypeAndDimensionSystem
()
{
return
typeAndDimensionSystem
;
}
}
/**
* Returns geometry type.
*
* @return geometry type and dimension system
*/
public
int
getGeometryType
()
{
return
typeAndDimensionSystem
%
1_000
;
}
}
/**
/**
...
@@ -195,8 +215,16 @@ public class ValueGeometry extends Value {
...
@@ -195,8 +215,16 @@ public class ValueGeometry extends Value {
* @return dimension system
* @return dimension system
*/
*/
public
int
getDimensionSystem
()
{
public
int
getDimensionSystem
()
{
calculateInfo
();
return
typeAndDimensionSystem
/
1_000
;
return
dimensionSystem
;
}
/**
* Return a spatial reference system identifier.
*
* @return spatial reference system identifier
*/
public
int
getSRID
()
{
return
srid
;
}
}
/**
/**
...
@@ -205,7 +233,11 @@ public class ValueGeometry extends Value {
...
@@ -205,7 +233,11 @@ public class ValueGeometry extends Value {
* @return envelope of this geometry
* @return envelope of this geometry
*/
*/
public
double
[]
getEnvelopeNoCopy
()
{
public
double
[]
getEnvelopeNoCopy
()
{
calculateInfo
();
if
(
envelope
==
UNKNOWN_ENVELOPE
)
{
EnvelopeTarget
target
=
new
EnvelopeTarget
();
EWKBUtils
.
parseEWKB
(
bytes
,
target
);
envelope
=
target
.
getEnvelope
();
}
return
envelope
;
return
envelope
;
}
}
...
@@ -319,7 +351,9 @@ public class ValueGeometry extends Value {
...
@@ -319,7 +351,9 @@ public class ValueGeometry extends Value {
@Override
@Override
public
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
,
Object
column
,
ExtTypeInfo
extTypeInfo
)
{
public
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
,
Object
column
,
ExtTypeInfo
extTypeInfo
)
{
if
(
targetType
==
Value
.
JAVA_OBJECT
)
{
if
(
targetType
==
Value
.
GEOMETRY
)
{
return
extTypeInfo
!=
null
?
extTypeInfo
.
cast
(
this
)
:
this
;
}
else
if
(
targetType
==
Value
.
JAVA_OBJECT
)
{
return
this
;
return
this
;
}
}
return
super
.
convertTo
(
targetType
,
precision
,
mode
,
column
,
null
);
return
super
.
convertTo
(
targetType
,
precision
,
mode
,
column
,
null
);
...
...
h2/src/test/org/h2/test/unit/TestGeometryUtils.java
浏览文件 @
df4cc289
...
@@ -8,6 +8,8 @@ package org.h2.test.unit;
...
@@ -8,6 +8,8 @@ package org.h2.test.unit;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
DIMENSION_SYSTEM_XY
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
DIMENSION_SYSTEM_XY
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
DIMENSION_SYSTEM_XYM
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
DIMENSION_SYSTEM_XYM
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
DIMENSION_SYSTEM_XYZ
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
DIMENSION_SYSTEM_XYZ
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
DIMENSION_SYSTEM_XYZM
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
GEOMETRY_COLLECTION
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
M
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
M
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
MAX_X
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
MAX_X
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
MAX_Y
;
import
static
org
.
h2
.
util
.
geometry
.
GeometryUtils
.
MAX_Y
;
...
@@ -33,6 +35,7 @@ import org.h2.util.geometry.GeometryUtils.EnvelopeAndDimensionSystemTarget;
...
@@ -33,6 +35,7 @@ import org.h2.util.geometry.GeometryUtils.EnvelopeAndDimensionSystemTarget;
import
org.h2.util.geometry.GeometryUtils.Target
;
import
org.h2.util.geometry.GeometryUtils.Target
;
import
org.h2.util.geometry.JTSUtils
;
import
org.h2.util.geometry.JTSUtils
;
import
org.h2.util.geometry.JTSUtils.GeometryTarget
;
import
org.h2.util.geometry.JTSUtils.GeometryTarget
;
import
org.h2.value.ValueGeometry
;
import
org.locationtech.jts.geom.CoordinateSequence
;
import
org.locationtech.jts.geom.CoordinateSequence
;
import
org.locationtech.jts.geom.Envelope
;
import
org.locationtech.jts.geom.Envelope
;
import
org.locationtech.jts.geom.Geometry
;
import
org.locationtech.jts.geom.Geometry
;
...
@@ -234,8 +237,11 @@ public class TestGeometryUtils extends TestBase {
...
@@ -234,8 +237,11 @@ public class TestGeometryUtils extends TestBase {
testEnvelope
(
envelopeFromJTS
,
target
.
getEnvelope
());
testEnvelope
(
envelopeFromJTS
,
target
.
getEnvelope
());
// Test dimensions
// Test dimensions
testDimensions
(
numOfDimensions
>
2
?
GeometryUtils
.
DIMENSION_SYSTEM_XYZ
:
GeometryUtils
.
DIMENSION_SYSTEM_XY
,
int
expectedDimensionSystem
=
numOfDimensions
>
2
?
GeometryUtils
.
DIMENSION_SYSTEM_XYZ
wkbFromJTS
);
:
GeometryUtils
.
DIMENSION_SYSTEM_XY
;
testDimensions
(
expectedDimensionSystem
,
wkbFromJTS
);
testValueGeometryProperties
(
wkbFromJTS
);
}
}
private
void
testEnvelope
(
Envelope
envelopeFromJTS
,
double
[]
envelopeFromH2
)
{
private
void
testEnvelope
(
Envelope
envelopeFromJTS
,
double
[]
envelopeFromH2
)
{
...
@@ -274,6 +280,7 @@ public class TestGeometryUtils extends TestBase {
...
@@ -274,6 +280,7 @@ public class TestGeometryUtils extends TestBase {
testDimensionMCheckPoint
(
cs
);
testDimensionMCheckPoint
(
cs
);
assertEquals
(
ewkb
,
JTSUtils
.
geometry2ewkb
(
p
));
assertEquals
(
ewkb
,
JTSUtils
.
geometry2ewkb
(
p
));
testDimensions
(
GeometryUtils
.
DIMENSION_SYSTEM_XYM
,
ewkb
);
testDimensions
(
GeometryUtils
.
DIMENSION_SYSTEM_XYM
,
ewkb
);
testValueGeometryProperties
(
ewkb
);
if
(
JTSUtils
.
M_IS_SUPPORTED
)
{
if
(
JTSUtils
.
M_IS_SUPPORTED
)
{
p
=
(
Point
)
new
WKTReader
().
read
(
"POINT M (1 2 3)"
);
p
=
(
Point
)
new
WKTReader
().
read
(
"POINT M (1 2 3)"
);
...
@@ -310,6 +317,7 @@ public class TestGeometryUtils extends TestBase {
...
@@ -310,6 +317,7 @@ public class TestGeometryUtils extends TestBase {
testDimensionZMCheckPoint
(
cs
);
testDimensionZMCheckPoint
(
cs
);
assertEquals
(
ewkb
,
JTSUtils
.
geometry2ewkb
(
p
));
assertEquals
(
ewkb
,
JTSUtils
.
geometry2ewkb
(
p
));
testDimensions
(
GeometryUtils
.
DIMENSION_SYSTEM_XYZM
,
ewkb
);
testDimensions
(
GeometryUtils
.
DIMENSION_SYSTEM_XYZM
,
ewkb
);
testValueGeometryProperties
(
ewkb
);
if
(
JTSUtils
.
M_IS_SUPPORTED
)
{
if
(
JTSUtils
.
M_IS_SUPPORTED
)
{
p
=
(
Point
)
new
WKTReader
().
read
(
"POINT ZM (1 2 3 4)"
);
p
=
(
Point
)
new
WKTReader
().
read
(
"POINT ZM (1 2 3 4)"
);
...
@@ -333,6 +341,32 @@ public class TestGeometryUtils extends TestBase {
...
@@ -333,6 +341,32 @@ public class TestGeometryUtils extends TestBase {
assertEquals
(
4
,
cs
.
getOrdinate
(
0
,
M
));
assertEquals
(
4
,
cs
.
getOrdinate
(
0
,
M
));
}
}
private
void
testValueGeometryProperties
(
byte
[]
ewkb
)
{
ValueGeometry
vg
=
ValueGeometry
.
getFromEWKB
(
ewkb
);
DimensionSystemTarget
target
=
new
DimensionSystemTarget
();
EWKBUtils
.
parseEWKB
(
ewkb
,
target
);
int
dimensionSystem
=
target
.
getDimensionSystem
();
assertEquals
(
dimensionSystem
,
vg
.
getDimensionSystem
());
String
formattedType
=
EWKTUtils
.
formatGeometryTypeAndDimensionSystem
(
vg
.
getTypeAndDimensionSystem
());
assertTrue
(
EWKTUtils
.
ewkb2ewkt
(
ewkb
).
startsWith
(
formattedType
));
switch
(
dimensionSystem
)
{
case
DIMENSION_SYSTEM_XY:
assertTrue
(
formattedType
.
indexOf
(
' '
)
<
0
);
break
;
case
DIMENSION_SYSTEM_XYZ:
assertTrue
(
formattedType
.
endsWith
(
" Z"
));
break
;
case
DIMENSION_SYSTEM_XYM:
assertTrue
(
formattedType
.
endsWith
(
" M"
));
break
;
case
DIMENSION_SYSTEM_XYZM:
assertTrue
(
formattedType
.
endsWith
(
" ZM"
));
break
;
}
assertEquals
(
vg
.
getTypeAndDimensionSystem
(),
vg
.
getGeometryType
()
+
vg
.
getDimensionSystem
()
*
1_000
);
assertEquals
(
0
,
vg
.
getSRID
());
}
private
void
testFiniteOnly
()
{
private
void
testFiniteOnly
()
{
for
(
int
i
=
0
;
i
<
NON_FINITE
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
NON_FINITE
.
length
;
i
++)
{
testFiniteOnly
(
NON_FINITE
[
i
],
new
EWKBTarget
(
new
ByteArrayOutputStream
(),
NON_FINITE_DIMENSIONS
[
i
]));
testFiniteOnly
(
NON_FINITE
[
i
],
new
EWKBTarget
(
new
ByteArrayOutputStream
(),
NON_FINITE_DIMENSIONS
[
i
]));
...
@@ -381,6 +415,9 @@ public class TestGeometryUtils extends TestBase {
...
@@ -381,6 +415,9 @@ public class TestGeometryUtils extends TestBase {
assertEquals
(
10
,
gc
.
getSRID
());
assertEquals
(
10
,
gc
.
getSRID
());
assertEquals
(
10
,
gc
.
getGeometryN
(
0
).
getSRID
());
assertEquals
(
10
,
gc
.
getGeometryN
(
0
).
getSRID
());
assertEquals
(
ewkb
,
JTSUtils
.
geometry2ewkb
(
gc
));
assertEquals
(
ewkb
,
JTSUtils
.
geometry2ewkb
(
gc
));
ValueGeometry
vg
=
ValueGeometry
.
getFromEWKB
(
ewkb
);
assertEquals
(
10
,
vg
.
getSRID
());
assertEquals
(
GEOMETRY_COLLECTION
,
vg
.
getTypeAndDimensionSystem
());
assertEquals
(
"SRID=-1;POINT EMPTY"
,
EWKTUtils
.
ewkb2ewkt
(
EWKTUtils
.
ewkt2ewkb
(
" srid=-1 ; POINT EMPTY "
)));
assertEquals
(
"SRID=-1;POINT EMPTY"
,
EWKTUtils
.
ewkb2ewkt
(
EWKTUtils
.
ewkt2ewkb
(
" srid=-1 ; POINT EMPTY "
)));
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论