Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
86dc865d
提交
86dc865d
authored
6月 29, 2017
作者:
Noel Grandin
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/master'
# Conflicts: # h2/src/docsrc/html/changelog.html
上级
d1ae0048
a8640fd5
显示空白字符变更
内嵌
并排
正在显示
34 个修改的文件
包含
438 行增加
和
90 行删除
+438
-90
.gitignore
.gitignore
+4
-0
.travis.yml
.travis.yml
+24
-8
pom.xml
h2/pom.xml
+1
-1
help.csv
h2/src/docsrc/help/help.csv
+3
-6
changelog.html
h2/src/docsrc/html/changelog.html
+10
-0
release.txt
h2/src/installer/release.txt
+1
-1
Parser.java
h2/src/main/org/h2/command/Parser.java
+1
-1
Insert.java
h2/src/main/org/h2/command/dml/Insert.java
+2
-2
Constants.java
h2/src/main/org/h2/engine/Constants.java
+4
-4
FunctionAlias.java
h2/src/main/org/h2/engine/FunctionAlias.java
+1
-1
Mode.java
h2/src/main/org/h2/engine/Mode.java
+12
-0
Comparison.java
h2/src/main/org/h2/expression/Comparison.java
+2
-1
Function.java
h2/src/main/org/h2/expression/Function.java
+1
-1
help.csv
h2/src/main/org/h2/res/help.csv
+1
-1
Column.java
h2/src/main/org/h2/table/Column.java
+14
-1
RangeTable.java
h2/src/main/org/h2/table/RangeTable.java
+1
-1
TableView.java
h2/src/main/org/h2/table/TableView.java
+4
-1
NetUtils.java
h2/src/main/org/h2/util/NetUtils.java
+17
-23
DataType.java
h2/src/main/org/h2/value/DataType.java
+2
-0
Transfer.java
h2/src/main/org/h2/value/Transfer.java
+1
-1
Value.java
h2/src/main/org/h2/value/Value.java
+18
-2
ValueGeometry.java
h2/src/main/org/h2/value/ValueGeometry.java
+4
-2
ValueLob.java
h2/src/main/org/h2/value/ValueLob.java
+3
-2
ValueLobDb.java
h2/src/main/org/h2/value/ValueLobDb.java
+3
-2
ValueNull.java
h2/src/main/org/h2/value/ValueNull.java
+2
-1
ValueStringFixed.java
h2/src/main/org/h2/value/ValueStringFixed.java
+66
-2
ValueTimestamp.java
h2/src/main/org/h2/value/ValueTimestamp.java
+33
-5
newsfeed.sql
h2/src/test/org/h2/samples/newsfeed.sql
+1
-0
TestCompatibility.java
h2/src/test/org/h2/test/db/TestCompatibility.java
+36
-0
TestGeneralCommonTableQueries.java
...rc/test/org/h2/test/db/TestGeneralCommonTableQueries.java
+98
-19
TestQueryCache.java
h2/src/test/org/h2/test/db/TestQueryCache.java
+11
-1
TestPreparedStatement.java
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
+9
-0
TestMvccMultiThreaded.java
h2/src/test/org/h2/test/mvcc/TestMvccMultiThreaded.java
+47
-0
dictionary.txt
h2/src/tools/org/h2/build/doc/dictionary.txt
+1
-0
没有找到文件。
.gitignore
浏览文件 @
86dc865d
...
...
@@ -11,5 +11,9 @@
/test.out.txt
.DS_Store
/.idea/
*.iml
*.ipr
*.iws
.checkstyle
/temp/
/h2web/
\ No newline at end of file
.travis.yml
浏览文件 @
86dc865d
sudo
:
false
language
:
java
jdk
:
-
openjdk7
-
oraclejdk8
before_script
:
cd h2
script
:
./build.sh jar testFast
cache
:
directories
:
-
$HOME/.m2/repository
matrix
:
include
:
-
jdk
:
oraclejdk8
dist
:
trusty
group
:
edge
sudo
:
required
addons
:
apt
:
packages
:
-
oracle-java8-installer
before_script
:
-
"
cd
h2"
-
"
echo
$JAVA_OPTS"
-
"
export
JAVA_OPTS=-Xmx512m"
-
jdk
:
openjdk7
dist
:
trusty
group
:
edge
sudo
:
required
addons
:
apt
:
packages
:
-
openjdk-7-jdk
before_script
:
-
"
cd
h2"
h2/pom.xml
浏览文件 @
86dc865d
...
...
@@ -4,7 +4,7 @@
<groupId>
com.h2database
</groupId>
<artifactId>
h2
</artifactId>
<version>
1.4.19
5
-SNAPSHOT
</version>
<version>
1.4.19
6
-SNAPSHOT
</version>
<packaging>
jar
</packaging>
<name>
H2 Database Engine
</name>
<url>
http://www.h2database.com
</url>
...
...
h2/src/docsrc/help/help.csv
浏览文件 @
86dc865d
...
...
@@ -197,12 +197,10 @@ WITH [ RECURSIVE ] { name [( columnName [,...] )]
AS ( select ) [,...] }
select
","
Can be used to create a recursive
query.
Can be used to create a recursive
or non-recursive query (common table expression).
For recursive queries the first select has to be a UNION.
Non-recursive queries are also supported.
One or more common table entries can be use referred to by name..
One or more common table entries can be referred to by name.
Column name declarations are now optional - the column names will be inferred from the named select queries.
Positional parameters are not currently supported.
","
WITH RECURSIVE t(n) AS (
SELECT 1
...
...
@@ -215,8 +213,7 @@ SELECT sum(n) FROM t;
","
WITH t1 AS (
SELECT 1 AS FIRST_COLUMN
),
t2 AS (
), t2 AS (
SELECT FIRST_COLUMN+1 AS FIRST_COLUMN FROM t1
)
SELECT sum(FIRST_COLUMN) FROM t2;
...
...
h2/src/docsrc/html/changelog.html
浏览文件 @
86dc865d
...
...
@@ -23,6 +23,14 @@ Change Log
<ul>
<li>
Fix bug in parsing ANALYZE TABLE xxx SAMPLE_SIZE yyy
</li>
<li>
Add padding for CHAR(N) values in PostgreSQL mode
</li>
<li>
Issue #89: Add DB2 timestamp format compatibility
</li>
</ul>
<h2>
Version 1.4.196 (2017-06-10)
</h2>
<ul>
<li>
Issue#479 Allow non-recursive CTEs (WITH statements), patch from stumc
</li>
<li>
Fix startup issue when using "CHECK" as a column name.
...
...
@@ -37,6 +45,8 @@ Change Log
</li>
<li>
Issue #479: Allow non-recursive Common Table Expressions (CTE)
</li>
<li>
On Mac OS X, with IPv6 and no network connection, the Console tool was not working as expected.
</li>
</ul>
<h2>
Version 1.4.195 (2017-04-23)
</h2>
...
...
h2/src/installer/release.txt
浏览文件 @
86dc865d
...
...
@@ -28,7 +28,7 @@ Add to http://twitter.com
Sign files and publish files on Maven Central
(check java version is 1.7)
./build.sh compile jar mavenDeployCentral
./build.sh c
lean c
ompile jar mavenDeployCentral
cd /data/h2database/m2-repo/com/h2database
# remove sha and md5 files:
find . -name "*.sha1" -delete
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
86dc865d
...
...
@@ -2906,7 +2906,7 @@ public class Parser {
String
timestamp
=
currentValue
.
getString
();
read
();
r
=
ValueExpression
.
get
(
ValueTimestamp
.
parse
(
timestamp
));
.
get
(
ValueTimestamp
.
parse
(
timestamp
,
session
.
getDatabase
().
getMode
()
));
}
else
if
(
equalsToken
(
"X"
,
name
))
{
read
();
byte
[]
buffer
=
StringUtils
...
...
h2/src/main/org/h2/command/dml/Insert.java
浏览文件 @
86dc865d
...
...
@@ -140,7 +140,7 @@ public class Insert extends Prepared implements ResultTarget {
// e can be null (DEFAULT)
e
=
e
.
optimize
(
session
);
try
{
Value
v
=
c
.
convert
(
e
.
getValue
(
session
));
Value
v
=
c
.
convert
(
e
.
getValue
(
session
)
,
session
.
getDatabase
().
getMode
()
);
newRow
.
setValue
(
index
,
v
);
}
catch
(
DbException
ex
)
{
throw
setRow
(
ex
,
x
,
getSQL
(
expr
));
...
...
@@ -186,7 +186,7 @@ public class Insert extends Prepared implements ResultTarget {
Column
c
=
columns
[
j
];
int
index
=
c
.
getColumnId
();
try
{
Value
v
=
c
.
convert
(
values
[
j
]);
Value
v
=
c
.
convert
(
values
[
j
]
,
session
.
getDatabase
().
getMode
()
);
newRow
.
setValue
(
index
,
v
);
}
catch
(
DbException
ex
)
{
throw
setRow
(
ex
,
rowNumber
,
getSQL
(
values
));
...
...
h2/src/main/org/h2/engine/Constants.java
浏览文件 @
86dc865d
...
...
@@ -16,22 +16,22 @@ public class Constants {
/**
* The build date is updated for each public release.
*/
public
static
final
String
BUILD_DATE
=
"2017-0
4-23
"
;
public
static
final
String
BUILD_DATE
=
"2017-0
6-10
"
;
/**
* The build date of the last stable release.
*/
public
static
final
String
BUILD_DATE_STABLE
=
"2017-0
3-10
"
;
public
static
final
String
BUILD_DATE_STABLE
=
"2017-0
4-23
"
;
/**
* The build id is incremented for each public release.
*/
public
static
final
int
BUILD_ID
=
19
5
;
public
static
final
int
BUILD_ID
=
19
6
;
/**
* The build id of the last stable release.
*/
public
static
final
int
BUILD_ID_STABLE
=
19
4
;
public
static
final
int
BUILD_ID_STABLE
=
19
5
;
/**
* Whether this is a snapshot version.
...
...
h2/src/main/org/h2/engine/FunctionAlias.java
浏览文件 @
86dc865d
...
...
@@ -439,7 +439,7 @@ public class FunctionAlias extends SchemaObjectBase {
}
o
=
objArray
;
}
else
{
v
=
v
.
convertTo
(
type
);
v
=
v
.
convertTo
(
type
,
-
1
,
session
.
getDatabase
().
getMode
()
);
o
=
v
.
getObject
();
}
if
(
o
==
null
)
{
...
...
h2/src/main/org/h2/engine/Mode.java
浏览文件 @
86dc865d
...
...
@@ -160,6 +160,16 @@ public class Mode {
*/
public
boolean
allowAffinityKey
;
/**
* Whether to right-pad fixed strings with spaces.
*/
public
boolean
padFixedLengthStrings
;
/**
* Whether DB2 TIMESTAMP formats are allowed.
*/
public
boolean
allowDB2TimestampFormat
;
private
final
String
name
;
static
{
...
...
@@ -179,6 +189,7 @@ public class Mode {
Pattern
.
compile
(
"ApplicationName|ClientAccountingInformation|"
+
"ClientUser|ClientCorrelationToken"
);
mode
.
prohibitEmptyInPredicate
=
true
;
mode
.
allowDB2TimestampFormat
=
true
;
add
(
mode
);
mode
=
new
Mode
(
"Derby"
);
...
...
@@ -256,6 +267,7 @@ public class Mode {
mode
.
supportedClientInfoPropertiesRegEx
=
Pattern
.
compile
(
"ApplicationName"
);
mode
.
prohibitEmptyInPredicate
=
true
;
mode
.
padFixedLengthStrings
=
true
;
add
(
mode
);
mode
=
new
Mode
(
"Ignite"
);
...
...
h2/src/main/org/h2/expression/Comparison.java
浏览文件 @
86dc865d
...
...
@@ -13,6 +13,7 @@ import org.h2.index.IndexCondition;
import
org.h2.message.DbException
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.util.MathUtils
;
import
org.h2.util.New
;
import
org.h2.value.Value
;
import
org.h2.value.ValueBoolean
;
...
...
@@ -201,7 +202,7 @@ public class Comparison extends Condition {
// to constant type, but vise versa, then let's do this here
// once.
if
(
constType
!=
resType
)
{
right
=
ValueExpression
.
get
(
r
.
convertTo
(
resType
));
right
=
ValueExpression
.
get
(
r
.
convertTo
(
resType
,
MathUtils
.
convertLongToInt
(
left
.
getPrecision
()),
session
.
getDatabase
().
getMode
()
));
}
}
else
if
(
right
instanceof
Parameter
)
{
((
Parameter
)
right
).
setColumn
(
...
...
h2/src/main/org/h2/expression/Function.java
浏览文件 @
86dc865d
...
...
@@ -1263,7 +1263,7 @@ public class Function extends Expression implements FunctionCall {
}
else
if
(
v0
.
getType
()
==
Value
.
STRING
)
{
ValueString
vd
=
(
ValueString
)
v0
;
Calendar
c
=
Calendar
.
getInstance
();
c
.
setTime
(
ValueTimestamp
.
parse
(
vd
.
getString
()).
getDate
());
c
.
setTime
(
ValueTimestamp
.
parse
(
vd
.
getString
()
,
session
.
getDatabase
().
getMode
()
).
getDate
());
c
.
set
(
Calendar
.
HOUR_OF_DAY
,
0
);
c
.
set
(
Calendar
.
MINUTE
,
0
);
c
.
set
(
Calendar
.
SECOND
,
0
);
...
...
h2/src/main/org/h2/res/help.csv
浏览文件 @
86dc865d
...
...
@@ -71,7 +71,7 @@ WITH [ RECURSIVE ] { name [( columnName [,...] )]
AS ( select ) [,...] }
select
","
Can be used to create a recursive
query
."
Can be used to create a recursive
or non-recursive query (common table expression)
."
"Commands (DDL)","ALTER INDEX RENAME","
ALTER INDEX [ IF EXISTS ] indexName RENAME TO newIndexName
","
...
...
h2/src/main/org/h2/table/Column.java
浏览文件 @
86dc865d
...
...
@@ -163,8 +163,21 @@ public class Column {
* @return the value
*/
public
Value
convert
(
Value
v
)
{
return
convert
(
v
,
null
);
}
/**
* Convert a value to this column's type using the given {@link Mode}.
* <p>
* Use this method in case the conversion is Mode-dependent.
*
* @param v the value
* @param mode the database {@link Mode} to use
* @return the value
*/
public
Value
convert
(
Value
v
,
Mode
mode
)
{
try
{
return
v
.
convertTo
(
type
);
return
v
.
convertTo
(
type
,
MathUtils
.
convertLongToInt
(
precision
),
mode
);
}
catch
(
DbException
e
)
{
if
(
e
.
getErrorCode
()
==
ErrorCode
.
DATA_CONVERSION_ERROR_1
)
{
String
target
=
(
table
==
null
?
""
:
table
.
getName
()
+
": "
)
+
...
...
h2/src/main/org/h2/table/RangeTable.java
浏览文件 @
86dc865d
h2/src/main/org/h2/table/TableView.java
浏览文件 @
86dc865d
...
...
@@ -207,7 +207,8 @@ public class TableView extends Table {
// If it can't be compiled, then it's a 'zero column table'
// this avoids problems when creating the view when opening the
// database.
// If it can not be compiled - it could also be a recursive common table expression query.
// If it can not be compiled - it could also be a recursive common
// table expression query.
if
(
isRecursiveQueryExceptionDetected
(
createException
))
{
this
.
isRecursiveQueryDetected
=
true
;
}
...
...
@@ -673,6 +674,8 @@ public class TableView extends Table {
/**
* Was query recursion detected during compiling.
*
* @return true if yes
*/
public
boolean
isRecursiveQueryDetected
()
{
return
isRecursiveQueryDetected
;
...
...
h2/src/main/org/h2/util/NetUtils.java
浏览文件 @
86dc865d
...
...
@@ -44,12 +44,9 @@ public class NetUtils {
*/
public
static
Socket
createLoopbackSocket
(
int
port
,
boolean
ssl
)
throws
IOException
{
InetAddress
address
=
getBindAddress
();
if
(
address
==
null
)
{
address
=
InetAddress
.
getLocalHost
();
}
String
local
=
getLocalAddress
();
try
{
return
createSocket
(
getHostAddress
(
address
)
,
port
,
ssl
);
return
createSocket
(
local
,
port
,
ssl
);
}
catch
(
IOException
e
)
{
try
{
return
createSocket
(
"localhost"
,
port
,
ssl
);
...
...
@@ -60,23 +57,6 @@ public class NetUtils {
}
}
/**
* Get the host address. This method adds '[' and ']' if required for
* Inet6Address that contain a ':'.
*
* @param address the address
* @return the host address
*/
private
static
String
getHostAddress
(
InetAddress
address
)
{
String
host
=
address
.
getHostAddress
();
if
(
address
instanceof
Inet6Address
)
{
if
(
host
.
indexOf
(
':'
)
>=
0
&&
!
host
.
startsWith
(
"["
))
{
host
=
"["
+
host
+
"]"
;
}
}
return
host
;
}
/**
* Create a client socket that is connected to the given address and port.
*
...
...
@@ -274,7 +254,21 @@ public class NetUtils {
throw
DbException
.
convert
(
e
);
}
}
String
address
=
bind
==
null
?
"localhost"
:
getHostAddress
(
bind
);
String
address
;
if
(
bind
==
null
)
{
address
=
"localhost"
;
}
else
{
address
=
bind
.
getHostAddress
();
if
(
bind
instanceof
Inet6Address
)
{
if
(
address
.
indexOf
(
"%"
)
>=
0
)
{
address
=
"localhost"
;
}
else
if
(
address
.
indexOf
(
':'
)
>=
0
&&
!
address
.
startsWith
(
"["
))
{
// adds'[' and ']' if required for
// Inet6Address that contain a ':'.
address
=
"["
+
address
+
"]"
;
}
}
}
if
(
address
.
equals
(
"127.0.0.1"
))
{
address
=
"localhost"
;
}
...
...
h2/src/main/org/h2/value/DataType.java
浏览文件 @
86dc865d
...
...
@@ -902,6 +902,8 @@ public class DataType {
return
Value
.
TIME
;
case
Types
.
TIMESTAMP
:
return
Value
.
TIMESTAMP
;
case
2014
:
// Types.TIMESTAMP_WITH_TIMEZONE
return
Value
.
TIMESTAMP_TZ
;
case
Types
.
BLOB
:
return
Value
.
BLOB
;
case
Types
.
CLOB
:
...
...
h2/src/main/org/h2/value/Transfer.java
浏览文件 @
86dc865d
...
...
@@ -615,7 +615,7 @@ public class Transfer {
case
Value
.
STRING_IGNORECASE
:
return
ValueStringIgnoreCase
.
get
(
readString
());
case
Value
.
STRING_FIXED
:
return
ValueStringFixed
.
get
(
readString
());
return
ValueStringFixed
.
get
(
readString
()
,
ValueStringFixed
.
PRECISION_DO_NOT_TRIM
,
null
);
case
Value
.
BLOB
:
{
long
length
=
readLong
();
if
(
version
>=
Constants
.
TCP_PROTOCOL_VERSION_11
)
{
...
...
h2/src/main/org/h2/value/Value.java
浏览文件 @
86dc865d
...
...
@@ -20,6 +20,7 @@ import java.sql.Timestamp;
import
java.sql.Types
;
import
org.h2.api.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Mode
;
import
org.h2.engine.SysProperties
;
import
org.h2.message.DbException
;
import
org.h2.store.DataHandler
;
...
...
@@ -541,6 +542,21 @@ public abstract class Value {
* @return the converted value
*/
public
Value
convertTo
(
int
targetType
)
{
// Use -1 to indicate "default behaviour" where value conversion should not
// depend on any datatype precision.
return
convertTo
(
targetType
,
-
1
,
null
);
}
/**
* Compare a value to the specified type.
*
* @param targetType the type of the returned value
* @param the precision of the column to convert this value to.
* The special constant <code>-1</code> is used to indicate that
* the precision plays no role when converting the value
* @return the converted value
*/
public
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
)
{
// converting NULL is done in ValueNull
// converting BLOB to CLOB and vice versa is done in ValueLob
if
(
getType
()
==
targetType
)
{
...
...
@@ -947,7 +963,7 @@ public abstract class Value {
case
DATE:
return
ValueDate
.
parse
(
s
.
trim
());
case
TIMESTAMP:
return
ValueTimestamp
.
parse
(
s
.
trim
());
return
ValueTimestamp
.
parse
(
s
.
trim
()
,
mode
);
case
TIMESTAMP_TZ:
return
ValueTimestampTimeZone
.
parse
(
s
.
trim
());
case
BYTES:
...
...
@@ -962,7 +978,7 @@ public abstract class Value {
case
STRING_IGNORECASE:
return
ValueStringIgnoreCase
.
get
(
s
);
case
STRING_FIXED:
return
ValueStringFixed
.
get
(
s
);
return
ValueStringFixed
.
get
(
s
,
precision
,
mode
);
case
DOUBLE:
return
ValueDouble
.
get
(
Double
.
parseDouble
(
s
.
trim
()));
case
FLOAT:
...
...
h2/src/main/org/h2/value/ValueGeometry.java
浏览文件 @
86dc865d
...
...
@@ -12,6 +12,8 @@ import java.util.Arrays;
import
com.vividsolutions.jts.geom.CoordinateSequence
;
import
com.vividsolutions.jts.geom.CoordinateSequenceFilter
;
import
com.vividsolutions.jts.geom.PrecisionModel
;
import
org.h2.engine.Mode
;
import
org.h2.message.DbException
;
import
org.h2.util.StringUtils
;
import
com.vividsolutions.jts.geom.Envelope
;
...
...
@@ -272,11 +274,11 @@ public class ValueGeometry extends Value {
}
@Override
public
Value
convertTo
(
int
targetType
)
{
public
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
)
{
if
(
targetType
==
Value
.
JAVA_OBJECT
)
{
return
this
;
}
return
super
.
convertTo
(
targetType
);
return
super
.
convertTo
(
targetType
,
precision
,
mode
);
}
/**
...
...
h2/src/main/org/h2/value/ValueLob.java
浏览文件 @
86dc865d
...
...
@@ -14,6 +14,7 @@ import java.io.Reader;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Mode
;
import
org.h2.engine.SysProperties
;
import
org.h2.message.DbException
;
import
org.h2.mvstore.DataUtils
;
...
...
@@ -443,7 +444,7 @@ public class ValueLob extends Value {
* @return the converted value
*/
@Override
public
Value
convertTo
(
int
t
)
{
public
Value
convertTo
(
int
t
,
int
precision
,
Mode
mode
)
{
if
(
t
==
type
)
{
return
this
;
}
else
if
(
t
==
Value
.
CLOB
)
{
...
...
@@ -453,7 +454,7 @@ public class ValueLob extends Value {
ValueLob
copy
=
ValueLob
.
createBlob
(
getInputStream
(),
-
1
,
handler
);
return
copy
;
}
return
super
.
convertTo
(
t
);
return
super
.
convertTo
(
t
,
precision
,
mode
);
}
@Override
...
...
h2/src/main/org/h2/value/ValueLobDb.java
浏览文件 @
86dc865d
...
...
@@ -14,6 +14,7 @@ import java.io.Reader;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Mode
;
import
org.h2.engine.SysProperties
;
import
org.h2.message.DbException
;
import
org.h2.mvstore.DataUtils
;
...
...
@@ -184,7 +185,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
* @return the converted value
*/
@Override
public
Value
convertTo
(
int
t
)
{
public
Value
convertTo
(
int
t
,
int
precision
,
Mode
mode
)
{
if
(
t
==
type
)
{
return
this
;
}
else
if
(
t
==
Value
.
CLOB
)
{
...
...
@@ -204,7 +205,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return
ValueLobDb
.
createSmallLob
(
t
,
small
);
}
}
return
super
.
convertTo
(
t
);
return
super
.
convertTo
(
t
,
precision
,
mode
);
}
@Override
...
...
h2/src/main/org/h2/value/ValueNull.java
浏览文件 @
86dc865d
...
...
@@ -14,6 +14,7 @@ import java.sql.SQLException;
import
java.sql.Time
;
import
java.sql.Timestamp
;
import
org.h2.engine.Mode
;
import
org.h2.message.DbException
;
/**
...
...
@@ -132,7 +133,7 @@ public class ValueNull extends Value {
}
@Override
public
Value
convertTo
(
int
type
)
{
public
Value
convertTo
(
int
type
,
int
precision
,
Mode
mode
)
{
return
this
;
}
...
...
h2/src/main/org/h2/value/ValueStringFixed.java
浏览文件 @
86dc865d
...
...
@@ -5,6 +5,9 @@
*/
package
org
.
h2
.
value
;
import
java.util.Arrays
;
import
org.h2.engine.Mode
;
import
org.h2.engine.SysProperties
;
import
org.h2.util.StringUtils
;
...
...
@@ -13,6 +16,18 @@ import org.h2.util.StringUtils;
*/
public
class
ValueStringFixed
extends
ValueString
{
/**
* Special value for the precision in {@link #get(String, int, Mode)} to indicate that the value
* should <i>not</i> be trimmed.
*/
public
static
final
int
PRECISION_DO_NOT_TRIM
=
Integer
.
MIN_VALUE
;
/**
* Special value for the precision in {@link #get(String, int, Mode)} to indicate that the default
* behaviour should of trimming the value should apply.
*/
public
static
final
int
PRECISION_TRIM
=
-
1
;
private
static
final
ValueStringFixed
EMPTY
=
new
ValueStringFixed
(
""
);
protected
ValueStringFixed
(
String
value
)
{
...
...
@@ -20,15 +35,29 @@ public class ValueStringFixed extends ValueString {
}
private
static
String
trimRight
(
String
s
)
{
return
trimRight
(
s
,
0
);
}
private
static
String
trimRight
(
String
s
,
int
minLength
)
{
int
endIndex
=
s
.
length
()
-
1
;
int
i
=
endIndex
;
while
(
i
>=
0
&&
s
.
charAt
(
i
)
==
' '
)
{
while
(
i
>=
minLength
&&
s
.
charAt
(
i
)
==
' '
)
{
i
--;
}
s
=
i
==
endIndex
?
s
:
s
.
substring
(
0
,
i
+
1
);
return
s
;
}
private
static
String
rightPadWithSpaces
(
String
s
,
int
length
)
{
int
pad
=
length
-
s
.
length
();
if
(
pad
<=
0
)
{
return
s
;
}
char
[]
res
=
new
char
[
length
];
s
.
getChars
(
0
,
s
.
length
(),
res
,
0
);
Arrays
.
fill
(
res
,
s
.
length
(),
length
,
' '
);
return
new
String
(
res
);
}
@Override
public
int
getType
()
{
return
Value
.
STRING_FIXED
;
...
...
@@ -42,7 +71,42 @@ public class ValueStringFixed extends ValueString {
* @return the value
*/
public
static
ValueStringFixed
get
(
String
s
)
{
// Use the special precision constant PRECISION_TRIM to indicate
// default H2 behaviour of trimming the value.
return
get
(
s
,
PRECISION_TRIM
,
null
);
}
/**
* Get or create a fixed length string value for the given string.
* <p>
* This method will use a {@link Mode}-specific conversion when <code>mode</code> is not <code>null</code>.
* Otherwise it will use the default H2 behaviour of trimming the given string if <code>precision</code>
* is not {@link #PRECISION_DO_NOT_TRIM}.
*
* @param s the string
* @param precision if the {@link Mode#padFixedLengthStrings} indicates that strings should be padded, this
* defines the overall length of the (potentially padded) string.
* If the special constant {@link #PRECISION_DO_NOT_TRIM} is used the value will not be trimmed.
* @return the value
*/
public
static
ValueStringFixed
get
(
String
s
,
int
precision
,
Mode
mode
)
{
// Should fixed strings be padded?
if
(
mode
!=
null
&&
mode
.
padFixedLengthStrings
)
{
if
(
precision
==
Integer
.
MAX_VALUE
)
{
// CHAR without a length specification is identical to CHAR(1)
precision
=
1
;
}
if
(
s
.
length
()
<
precision
)
{
// We have to pad
s
=
rightPadWithSpaces
(
s
,
precision
);
}
else
{
// We should trim, because inserting 'A ' into a CHAR(1) is possible!
s
=
trimRight
(
s
,
precision
);
}
}
else
if
(
precision
!=
PRECISION_DO_NOT_TRIM
)
{
// Default behaviour of H2
s
=
trimRight
(
s
);
}
if
(
s
.
length
()
==
0
)
{
return
EMPTY
;
}
...
...
h2/src/main/org/h2/value/ValueTimestamp.java
浏览文件 @
86dc865d
...
...
@@ -13,6 +13,7 @@ import java.sql.Timestamp;
import
java.util.Calendar
;
import
java.util.TimeZone
;
import
org.h2.api.ErrorCode
;
import
org.h2.engine.Mode
;
import
org.h2.message.DbException
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.util.MathUtils
;
...
...
@@ -109,26 +110,53 @@ public class ValueTimestamp extends Value {
/**
* Parse a string to a ValueTimestamp. This method supports the format
* +/-year-month-day hour
:minute:
seconds.fractional and an optional timezone
* +/-year-month-day hour
[:.]minute[:.]
seconds.fractional and an optional timezone
* part.
*
* @param s the string to parse
* @return the date
*/
public
static
ValueTimestamp
parse
(
String
s
)
{
return
parse
(
s
,
null
);
}
/**
* Parse a string to a ValueTimestamp, using the given {@link Mode}.
* This method supports the format +/-year-month-day[ -]hour[:.]minute[:.]seconds.fractional
* and an optional timezone part.
*
* @param s the string to parse
* @param mode the database {@link Mode}
* @return the date
*/
public
static
ValueTimestamp
parse
(
String
s
,
Mode
mode
)
{
try
{
return
parseTry
(
s
);
return
parseTry
(
s
,
mode
);
}
catch
(
Exception
e
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_DATETIME_CONSTANT_2
,
e
,
"TIMESTAMP"
,
s
);
}
}
private
static
ValueTimestamp
parseTry
(
String
s
)
{
/**
* See: https://stackoverflow.com/questions/3976616/how-to-find-nth-occurrence-of-character-in-a-string#answer-3976656
*/
private
static
int
findNthIndexOf
(
String
str
,
char
chr
,
int
n
)
{
int
pos
=
str
.
indexOf
(
chr
);
while
(--
n
>
0
&&
pos
!=
-
1
)
pos
=
str
.
indexOf
(
chr
,
pos
+
1
);
return
pos
;
}
private
static
ValueTimestamp
parseTry
(
String
s
,
Mode
mode
)
{
int
dateEnd
=
s
.
indexOf
(
' '
);
if
(
dateEnd
<
0
)
{
// ISO 8601 compatibility
dateEnd
=
s
.
indexOf
(
'T'
);
if
(
dateEnd
<
0
&&
mode
!=
null
&&
mode
.
allowDB2TimestampFormat
)
{
// DB2 also allows dash between date and time
dateEnd
=
findNthIndexOf
(
s
,
'-'
,
3
);
}
}
int
timeStart
;
if
(
dateEnd
<
0
)
{
...
...
@@ -148,9 +176,9 @@ public class ValueTimestamp extends Value {
tz
=
TimeZone
.
getTimeZone
(
"UTC"
);
timeEnd
--;
}
else
{
int
timeZoneStart
=
s
.
indexOf
(
'+'
,
dateEnd
);
int
timeZoneStart
=
s
.
indexOf
(
'+'
,
dateEnd
+
1
);
if
(
timeZoneStart
<
0
)
{
timeZoneStart
=
s
.
indexOf
(
'-'
,
dateEnd
);
timeZoneStart
=
s
.
indexOf
(
'-'
,
dateEnd
+
1
);
}
if
(
timeZoneStart
>=
0
)
{
String
tzName
=
"GMT"
+
s
.
substring
(
timeZoneStart
);
...
...
h2/src/test/org/h2/samples/newsfeed.sql
浏览文件 @
86dc865d
...
...
@@ -7,6 +7,7 @@
CREATE
TABLE
VERSION
(
ID
INT
PRIMARY
KEY
,
VERSION
VARCHAR
,
CREATED
VARCHAR
);
INSERT
INTO
VERSION
VALUES
(
146
,
'1.4.197'
,
'2017-06-10'
),
(
145
,
'1.4.195'
,
'2017-04-23'
),
(
144
,
'1.4.194'
,
'2017-03-10'
),
(
143
,
'1.4.193'
,
'2016-10-31'
),
...
...
h2/src/test/org/h2/test/db/TestCompatibility.java
浏览文件 @
86dc865d
...
...
@@ -245,6 +245,34 @@ public class TestCompatibility extends TestBase {
assertResult
(
"ABC"
,
stat
,
"SELECT SUBSTRING('ABCDEF' FOR 3)"
);
assertResult
(
"ABCD"
,
stat
,
"SELECT SUBSTRING('0ABCDEF' FROM 2 FOR 4)"
);
/* Test right-padding of CHAR(N) at INSERT */
stat
.
execute
(
"CREATE TABLE TEST(CH CHAR(10))"
);
stat
.
execute
(
"INSERT INTO TEST (CH) VALUES ('Hello')"
);
assertResult
(
"Hello "
,
stat
,
"SELECT CH FROM TEST"
);
/* Test that WHERE clauses accept unpadded values and will pad before comparison */
assertResult
(
"Hello "
,
stat
,
"SELECT CH FROM TEST WHERE CH = 'Hello'"
);
/* Test CHAR which is identical to CHAR(1) */
stat
.
execute
(
"DROP TABLE IF EXISTS TEST"
);
stat
.
execute
(
"CREATE TABLE TEST(CH CHAR)"
);
stat
.
execute
(
"INSERT INTO TEST (CH) VALUES ('')"
);
assertResult
(
" "
,
stat
,
"SELECT CH FROM TEST"
);
assertResult
(
" "
,
stat
,
"SELECT CH FROM TEST WHERE CH = ''"
);
/* Test that excessive spaces are trimmed */
stat
.
execute
(
"DELETE FROM TEST"
);
stat
.
execute
(
"INSERT INTO TEST (CH) VALUES ('1 ')"
);
assertResult
(
"1"
,
stat
,
"SELECT CH FROM TEST"
);
assertResult
(
"1"
,
stat
,
"SELECT CH FROM TEST WHERE CH = '1 '"
);
/* Test that we do not trim too far */
stat
.
execute
(
"DROP TABLE IF EXISTS TEST"
);
stat
.
execute
(
"CREATE TABLE TEST(CH CHAR(2))"
);
stat
.
execute
(
"INSERT INTO TEST (CH) VALUES ('1 ')"
);
assertResult
(
"1 "
,
stat
,
"SELECT CH FROM TEST"
);
assertResult
(
"1 "
,
stat
,
"SELECT CH FROM TEST WHERE CH = '1 '"
);
}
private
void
testMySQL
()
throws
SQLException
{
...
...
@@ -469,6 +497,14 @@ public class TestCompatibility extends TestBase {
"fetch next 2 rows only with rs use and keep update locks"
);
res
=
stat
.
executeQuery
(
"select * from test order by id "
+
"fetch next 2 rows only with rr use and keep exclusive locks"
);
// Test DB2 TIMESTAMP format with dash separating date and time
stat
.
execute
(
"drop table test if exists"
);
stat
.
execute
(
"create table test(date TIMESTAMP)"
);
stat
.
executeUpdate
(
"insert into test (date) values ('2014-04-05-09.48.28.020005')"
);
assertResult
(
"2014-04-05 09:48:28.020005"
,
stat
,
"select date from test"
);
// <- result is always H2 format timestamp!
assertResult
(
"2014-04-05 09:48:28.020005"
,
stat
,
"select date from test where date = '2014-04-05-09.48.28.020005'"
);
assertResult
(
"2014-04-05 09:48:28.020005"
,
stat
,
"select date from test where date = '2014-04-05 09:48:28.020005'"
);
}
private
void
testDerby
()
throws
SQLException
{
...
...
h2/src/test/org/h2/test/db/TestGeneralCommonTableQueries.java
浏览文件 @
86dc865d
...
...
@@ -30,6 +30,8 @@ public class TestGeneralCommonTableQueries extends TestBase {
testSimple
();
testImpliedColumnNames
();
testChainedQuery
();
testParameterizedQuery
();
testNumberedParameterizedQuery
();
}
private
void
testSimple
()
throws
Exception
{
...
...
@@ -119,16 +121,93 @@ public class TestGeneralCommonTableQueries extends TestBase {
PreparedStatement
prep
;
ResultSet
rs
;
prep
=
conn
.
prepareStatement
(
" WITH t1 AS ("
+
" SELECT 1 AS FIRST_COLUMN"
prep
=
conn
.
prepareStatement
(
" WITH t1 AS ("
+
" SELECT 1 AS FIRST_COLUMN"
+
"),"
+
" t2 AS ("
+
" SELECT FIRST_COLUMN+1 AS FIRST_COLUMN FROM t1 "
+
") "
+
"SELECT sum(FIRST_COLUMN) FROM t2"
);
rs
=
prep
.
executeQuery
();
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertFalse
(
rs
.
next
());
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
private
void
testParameterizedQuery
()
throws
Exception
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
PreparedStatement
prep
;
ResultSet
rs
;
prep
=
conn
.
prepareStatement
(
"WITH t1 AS ("
+
" SELECT X, 'T1' FROM SYSTEM_RANGE(?,?)"
+
"),"
+
"t2 AS ("
+
" SELECT X, 'T2' FROM SYSTEM_RANGE(?,?)"
+
") "
+
"SELECT * FROM t1 UNION ALL SELECT * FROM t2 "
+
"UNION ALL SELECT X, 'Q' FROM SYSTEM_RANGE(?,?)"
);
prep
.
setInt
(
1
,
1
);
prep
.
setInt
(
2
,
2
);
prep
.
setInt
(
3
,
3
);
prep
.
setInt
(
4
,
4
);
prep
.
setInt
(
5
,
5
);
prep
.
setInt
(
6
,
6
);
rs
=
prep
.
executeQuery
();
for
(
int
n:
new
int
[]{
1
,
2
,
3
,
4
,
5
,
6
}
){
assertTrue
(
rs
.
next
());
assertEquals
(
n
,
rs
.
getInt
(
1
));
}
assertFalse
(
rs
.
next
());
// call it twice
rs
=
prep
.
executeQuery
();
for
(
int
n:
new
int
[]{
1
,
2
,
3
,
4
,
5
,
6
}
){
assertTrue
(
rs
.
next
());
assertEquals
(
n
,
rs
.
getInt
(
1
));
}
assertFalse
(
rs
.
next
());
conn
.
close
();
deleteDb
(
"commonTableExpressionQueries"
);
}
private
void
testNumberedParameterizedQuery
()
throws
Exception
{
deleteDb
(
"commonTableExpressionQueries"
);
Connection
conn
=
getConnection
(
"commonTableExpressionQueries"
);
PreparedStatement
prep
;
ResultSet
rs
;
prep
=
conn
.
prepareStatement
(
"WITH t1 AS ("
+
" SELECT R.X, 'T1' FROM SYSTEM_RANGE(?1,?2) R"
+
"),"
+
"
t2 AS ("
+
" SELECT FIRST_COLUMN+1 AS FIRST_COLUMN FROM t1
"
+
"
t2 AS ("
+
" SELECT R.X, 'T2' FROM SYSTEM_RANGE(?3,?4) R
"
+
") "
+
"SELECT sum(FIRST_COLUMN) FROM t2"
);
+
"SELECT * FROM t1 UNION ALL SELECT * FROM t2 UNION ALL SELECT X, 'Q' FROM SYSTEM_RANGE(?5,?6)"
);
prep
.
setInt
(
1
,
1
);
prep
.
setInt
(
2
,
2
);
prep
.
setInt
(
3
,
3
);
prep
.
setInt
(
4
,
4
);
prep
.
setInt
(
5
,
5
);
prep
.
setInt
(
6
,
6
);
rs
=
prep
.
executeQuery
();
for
(
int
n
:
new
int
[]
{
1
,
2
,
3
,
4
,
5
,
6
})
{
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertEquals
(
n
,
rs
.
getInt
(
1
));
}
assertEquals
(
"X"
,
rs
.
getMetaData
().
getColumnLabel
(
1
));
assertEquals
(
"'T1'"
,
rs
.
getMetaData
().
getColumnLabel
(
2
));
assertFalse
(
rs
.
next
());
conn
.
close
();
...
...
h2/src/test/org/h2/test/db/TestQueryCache.java
浏览文件 @
86dc865d
...
...
@@ -50,6 +50,8 @@ public class TestQueryCache extends TestBase {
}
String
query
=
queryBuilder
.
toString
();
conn
.
prepareStatement
(
query
);
int
firstGreater
=
0
;
int
firstSmaller
=
0
;
long
time
;
ResultSet
rs
;
long
first
=
0
;
...
...
@@ -77,9 +79,17 @@ public class TestQueryCache extends TestBase {
// try to avoid pauses in subsequent iterations
System
.
gc
();
}
else
if
(
i
>
1001
)
{
assertSmaller
(
time
,
first
);
if
(
first
>
time
)
{
firstGreater
++;
}
else
{
firstSmaller
++;
}
}
}
// first prepare time must be always greater because of query cache,
// but JVM is too unpredictable to assert that, so just check that
// usually this is true
assertSmaller
(
firstSmaller
,
firstGreater
);
stat
.
execute
(
"drop table test"
);
conn
.
close
();
}
...
...
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
浏览文件 @
86dc865d
...
...
@@ -682,6 +682,15 @@ public class TestPreparedStatement extends TestBase {
rs
.
next
();
Object
offsetDateTime2
=
rs
.
getObject
(
1
,
LocalDateTimeUtils
.
getOffsetDateTimeClass
());
assertEquals
(
offsetDateTime
,
offsetDateTime2
);
assertFalse
(
rs
.
next
());
rs
.
close
();
prep
.
setObject
(
1
,
offsetDateTime
,
2014
);
// Types.TIMESTAMP_WITH_TIMEZONE
rs
=
prep
.
executeQuery
();
rs
.
next
();
offsetDateTime2
=
rs
.
getObject
(
1
,
LocalDateTimeUtils
.
getOffsetDateTimeClass
());
assertEquals
(
offsetDateTime
,
offsetDateTime2
);
assertFalse
(
rs
.
next
());
rs
.
close
();
}
...
...
h2/src/test/org/h2/test/mvcc/TestMvccMultiThreaded.java
浏览文件 @
86dc865d
...
...
@@ -7,7 +7,9 @@ package org.h2.test.mvcc;
import
java.sql.Connection
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
java.util.ArrayList
;
import
java.util.concurrent.CountDownLatch
;
import
org.h2.api.ErrorCode
;
...
...
@@ -30,6 +32,7 @@ public class TestMvccMultiThreaded extends TestBase {
@Override
public
void
test
()
throws
Exception
{
testConcurrentSelectForUpdate
();
testMergeWithUniqueKeyViolation
();
// not supported currently
if
(!
config
.
multiThreaded
)
{
...
...
@@ -38,6 +41,50 @@ public class TestMvccMultiThreaded extends TestBase {
}
}
private
void
testConcurrentSelectForUpdate
()
throws
Exception
{
deleteDb
(
getTestName
());
Connection
conn
=
getConnection
(
getTestName
()
+
";MULTI_THREADED=TRUE"
);
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"create table test(id int not null primary key, updated int not null)"
);
stat
.
execute
(
"insert into test(id, updated) values(1, 100)"
);
ArrayList
<
Task
>
tasks
=
new
ArrayList
<>();
int
count
=
3
;
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Task
task
=
new
Task
()
{
@Override
public
void
call
()
throws
Exception
{
Connection
conn
=
getConnection
(
getTestName
());
Statement
stat
=
conn
.
createStatement
();
try
{
while
(!
stop
)
{
try
{
stat
.
execute
(
"select * from test where id=1 for update"
);
}
catch
(
SQLException
e
)
{
int
errorCode
=
e
.
getErrorCode
();
assertEquals
(
e
.
getMessage
(),
errorCode
==
ErrorCode
.
DEADLOCK_1
||
errorCode
==
ErrorCode
.
LOCK_TIMEOUT_1
);
}
}
}
finally
{
conn
.
close
();
}
}
}.
execute
();
tasks
.
add
(
task
);
}
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
Thread
.
sleep
(
100
);
ResultSet
rs
=
stat
.
executeQuery
(
"select * from test"
);
assertTrue
(
rs
.
next
());
}
for
(
Task
t
:
tasks
)
{
t
.
get
();
}
conn
.
close
();
deleteDb
(
getTestName
());
}
private
void
testMergeWithUniqueKeyViolation
()
throws
Exception
{
deleteDb
(
getTestName
());
Connection
conn
=
getConnection
(
getTestName
());
...
...
h2/src/tools/org/h2/build/doc/dictionary.txt
浏览文件 @
86dc865d
...
...
@@ -736,3 +736,4 @@ arbonaut exposing obscure determined turkey buildings indexhints acct
choosing optimise arte preparator katzyn bla jenkins tot artes pgserver npe
suffers closeablem mni significance vise identiy vitalus aka ilike uppercasing reentrant
aff ignite warm upstream producing sfu jit smtm affinity stashed tbl
stumc numbered
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论