Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
9ca0e68e
Unverified
提交
9ca0e68e
authored
2月 09, 2018
作者:
ScaY
提交者:
GitHub
2月 09, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into scay-issue#832
上级
2f21e5d7
e0619d3a
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
34 个修改的文件
包含
761 行增加
和
769 行删除
+761
-769
help.csv
h2/src/docsrc/help/help.csv
+7
-4
changelog.html
h2/src/docsrc/html/changelog.html
+29
-406
performance.html
h2/src/docsrc/html/performance.html
+1
-1
release.txt
h2/src/installer/release.txt
+55
-9
DbContextRule.java
h2/src/main/org/h2/bnf/context/DbContextRule.java
+3
-3
Parser.java
h2/src/main/org/h2/command/Parser.java
+18
-157
Aggregate.java
h2/src/main/org/h2/expression/Aggregate.java
+1
-1
AggregateDataMedian.java
h2/src/main/org/h2/expression/AggregateDataMedian.java
+21
-11
Comparison.java
h2/src/main/org/h2/expression/Comparison.java
+3
-1
ConditionInParameter.java
h2/src/main/org/h2/expression/ConditionInParameter.java
+1
-1
Function.java
h2/src/main/org/h2/expression/Function.java
+119
-37
JdbcStatement.java
h2/src/main/org/h2/jdbc/JdbcStatement.java
+2
-2
LazyResult.java
h2/src/main/org/h2/result/LazyResult.java
+2
-2
LocalResult.java
h2/src/main/org/h2/result/LocalResult.java
+3
-2
ResultInterface.java
h2/src/main/org/h2/result/ResultInterface.java
+2
-2
ResultRemote.java
h2/src/main/org/h2/result/ResultRemote.java
+2
-2
Column.java
h2/src/main/org/h2/table/Column.java
+1
-1
DateTimeUtils.java
h2/src/main/org/h2/util/DateTimeUtils.java
+85
-60
ParserUtil.java
h2/src/main/org/h2/util/ParserUtil.java
+212
-0
Value.java
h2/src/main/org/h2/value/Value.java
+18
-18
ValueGeometry.java
h2/src/main/org/h2/value/ValueGeometry.java
+2
-3
ValueLob.java
h2/src/main/org/h2/value/ValueLob.java
+5
-4
ValueLobDb.java
h2/src/main/org/h2/value/ValueLobDb.java
+6
-4
ValueNull.java
h2/src/main/org/h2/value/ValueNull.java
+2
-2
TestBase.java
h2/src/test/org/h2/test/TestBase.java
+23
-3
AbstractBaseForCommonTableExpressions.java
...org/h2/test/db/AbstractBaseForCommonTableExpressions.java
+14
-1
TestOptimizations.java
h2/src/test/org/h2/test/db/TestOptimizations.java
+22
-13
TestScript.java
h2/src/test/org/h2/test/scripts/TestScript.java
+9
-9
dateadd.sql
...est/org/h2/test/scripts/functions/timeanddate/dateadd.sql
+34
-1
datediff.sql
...st/org/h2/test/scripts/functions/timeanddate/datediff.sql
+31
-0
testScript.sql
h2/src/test/org/h2/test/scripts/testScript.sql
+3
-3
TestDateTimeUtils.java
h2/src/test/org/h2/test/unit/TestDateTimeUtils.java
+20
-4
Build.java
h2/src/tools/org/h2/build/Build.java
+2
-2
dictionary.txt
h2/src/tools/org/h2/build/doc/dictionary.txt
+3
-0
没有找到文件。
h2/src/docsrc/help/help.csv
浏览文件 @
9ca0e68e
...
@@ -3668,12 +3668,14 @@ CURRENT_TIMESTAMP()
...
@@ -3668,12 +3668,14 @@ CURRENT_TIMESTAMP()
"Functions (Time and Date)","DATEADD","
"Functions (Time and Date)","DATEADD","
{ DATEADD| TIMESTAMPADD } (unitString, addIntLong, timestamp)
{ DATEADD| TIMESTAMPADD } (unitString, addIntLong, timestamp)
","
","
Adds units to a
timestamp
. The string indicates the unit.
Adds units to a
date-time value
. The string indicates the unit.
Use negative values to subtract units.
Use negative values to subtract units.
addIntLong may be a long value when manipulating milliseconds,
addIntLong may be a long value when manipulating milliseconds,
otherwise it's range is restricted to int.
otherwise it's range is restricted to int.
The same units as in the EXTRACT function are supported.
The same units as in the EXTRACT function are supported.
DATEADD method returns a timestamp. TIMESTAMPADD method returns a long.
This method returns a value with the same type as specified value if unit is compatible with this value.
If specified unit is a HOUR, MINUTE, SECOND, MILLISECOND, etc and value is a DATE value DATEADD returns combined TIMESTAMP.
Units DAY, MONTH, YEAR, WEEK, etc are not allowed for TIME values.
","
","
DATEADD('MONTH', 1, DATE '2001-01-31')
DATEADD('MONTH', 1, DATE '2001-01-31')
"
"
...
@@ -3723,8 +3725,9 @@ DAY_OF_YEAR(CREATED)
...
@@ -3723,8 +3725,9 @@ DAY_OF_YEAR(CREATED)
"
"
"Functions (Time and Date)","EXTRACT","
"Functions (Time and Date)","EXTRACT","
EXTRACT ( { YEAR | YY | MONTH | MM | WEEK | ISO_WEEK | DAY | DD | DAY_OF_YEAR
EXTRACT ( { YEAR | YY | MONTH | MM | QUARTER | WEEK | ISO_WEEK
| DOY | HOUR | HH | MINUTE | MI | SECOND | SS | MILLISECOND | MS }
| DAY | DD | DAY_OF_YEAR | DOY
| HOUR | HH | MINUTE | MI | SECOND | SS | MILLISECOND | MS }
FROM timestamp )
FROM timestamp )
","
","
Returns a specific value from a timestamps.
Returns a specific value from a timestamps.
...
...
h2/src/docsrc/html/changelog.html
浏览文件 @
9ca0e68e
差异被折叠。
点击展开。
h2/src/docsrc/html/performance.html
浏览文件 @
9ca0e68e
...
@@ -490,7 +490,7 @@ Instead, use a prepared statement with arrays as in the following example:
...
@@ -490,7 +490,7 @@ Instead, use a prepared statement with arrays as in the following example:
</p>
</p>
<pre>
<pre>
PreparedStatement prep = conn.prepareStatement(
PreparedStatement prep = conn.prepareStatement(
"SELECT *
TEST.
ID = ANY(?)");
"SELECT *
FROM TEST WHERE
ID = ANY(?)");
prep.setObject(1, new Object[] { "1", "2" });
prep.setObject(1, new Object[] { "1", "2" });
ResultSet rs = prep.executeQuery();
ResultSet rs = prep.executeQuery();
</pre>
</pre>
...
...
h2/src/installer/release.txt
浏览文件 @
9ca0e68e
...
@@ -17,7 +17,28 @@ Ensure lines are not overly long:
...
@@ -17,7 +17,28 @@ Ensure lines are not overly long:
./build.sh docs
./build.sh docs
## Jar File Size Verification
## JDBC Client Jar File Size Verification
The JDBC client is supposed to not have dependencies to the database engine.
To verify, run
./build.sh clean jarClient
If this fails with eg. "Expected file size 400 - 500 KB, got: 1687", then
find out where the dependency is, and resolve. As follows:
start by renaming Database to Database2:
mv src/main/org/h2/engine/Database.java src/main/org/h2/engine/Database2.java
./build.sh clean jarClient
This will fail, the first error is for example can not compile Session because Database was not found.
So rename Session to Session2 and try again.
This will fail again, the first error is different, now for example can not compile ResultInterface
because Session was not found. Now, ResultInterface should not depend on the Session.
So this needs to be fixed (the JDBC API shouldn't indirectly depend on it).
After everything is resolved, rename the classes back.
## MVStore Jar File Size Verification
To ensure the MVStore jar file is not too large
To ensure the MVStore jar file is not too large
(does not reference the database code by accident).
(does not reference the database code by accident).
...
@@ -27,14 +48,39 @@ The file size should be about 200 KB:
...
@@ -27,14 +48,39 @@ The file size should be about 200 KB:
## Changing Version Numbers
## Changing Version Numbers
Update Constants.java - change version and build number
Update org.h2.engine.Constants.java:
Update changelog.html - add new version, remove oldest
if the last build was stable (the normal case):
Update newsfeed.sql - add new version, remove oldest
set BUILD_DATE_STABLE to current BUILD_DATE
Minor version change: change sourceError.html and source.html
set BUILD_ID_STABLE to current BUILD_ID
If a beta, change download.html: Version ${version} (${versionDate}), Beta
change the version and build number:
If a beta, change mainWeb.html: Version ${version} (${versionDate}), Beta
set BUILD_DATE to today
Benchmark: use latest versions of other dbs, change version(s) in performance.html
increment BUILD_ID
Run ./buildRelease.sh / buildRelease.bat
Update changelog.html:
* create a new "Next Version (unreleased)" with an empty list
* add a new version
* remove change log entries of the oldest version (keeping about 500 lines)
Update newsfeed.sql:
* add new version, for example:
* (146, '1.4.197', '2017-06-10'),
* remove oldest entry in that list
## Skipped
The following can be skipped currently, as sourceError.html and source.html
are no longer working (they can be removed, or fixed):
* Minor version change: change sourceError.html and source.html
* If a beta, change download.html: Version ${version} (${versionDate}), Beta
* If a beta, change mainWeb.html: Version ${version} (${versionDate}), Beta
The following can be skipped currently; benchmarks should probably be removed:
* To update benchmark data: use latest versions of other dbs, change version(s) in performance.html
## Build the release
Change directory to src/installer
Run ./buildRelease.sh (non-Windows) or buildRelease.bat (Windows)
Scan for viruses
Scan for viruses
Test installer, H2 Console (test new languages)
Test installer, H2 Console (test new languages)
...
...
h2/src/main/org/h2/bnf/context/DbContextRule.java
浏览文件 @
9ca0e68e
...
@@ -15,8 +15,8 @@ import org.h2.bnf.RuleElement;
...
@@ -15,8 +15,8 @@ import org.h2.bnf.RuleElement;
import
org.h2.bnf.RuleHead
;
import
org.h2.bnf.RuleHead
;
import
org.h2.bnf.RuleList
;
import
org.h2.bnf.RuleList
;
import
org.h2.bnf.Sentence
;
import
org.h2.bnf.Sentence
;
import
org.h2.command.Parser
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.util.ParserUtil
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
/**
/**
...
@@ -154,7 +154,7 @@ public class DbContextRule implements Rule {
...
@@ -154,7 +154,7 @@ public class DbContextRule implements Rule {
break
;
break
;
}
}
String
alias
=
up
.
substring
(
0
,
i
);
String
alias
=
up
.
substring
(
0
,
i
);
if
(
Parser
.
isKeyword
(
alias
,
true
))
{
if
(
Parser
Util
.
isKeyword
(
alias
,
true
))
{
break
;
break
;
}
}
s
=
s
.
substring
(
alias
.
length
());
s
=
s
.
substring
(
alias
.
length
());
...
@@ -301,7 +301,7 @@ public class DbContextRule implements Rule {
...
@@ -301,7 +301,7 @@ public class DbContextRule implements Rule {
return
s
;
return
s
;
}
}
String
alias
=
up
.
substring
(
0
,
i
);
String
alias
=
up
.
substring
(
0
,
i
);
if
(
"SET"
.
equals
(
alias
)
||
Parser
.
isKeyword
(
alias
,
true
))
{
if
(
"SET"
.
equals
(
alias
)
||
Parser
Util
.
isKeyword
(
alias
,
true
))
{
return
s
;
return
s
;
}
}
if
(
newAlias
)
{
if
(
newAlias
)
{
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
9ca0e68e
...
@@ -148,6 +148,7 @@ import org.h2.table.TableFilter.TableFilterVisitor;
...
@@ -148,6 +148,7 @@ import org.h2.table.TableFilter.TableFilterVisitor;
import
org.h2.table.TableView
;
import
org.h2.table.TableView
;
import
org.h2.util.MathUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.New
;
import
org.h2.util.New
;
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.value.CompareMode
;
import
org.h2.value.CompareMode
;
...
@@ -186,15 +187,18 @@ public class Parser {
...
@@ -186,15 +187,18 @@ public class Parser {
CHAR_DOLLAR_QUOTED_STRING
=
9
;
CHAR_DOLLAR_QUOTED_STRING
=
9
;
// this are token types
// this are token types
private
static
final
int
KEYWORD
=
1
,
IDENTIFIER
=
2
,
PARAMETER
=
3
,
private
static
final
int
KEYWORD
=
ParserUtil
.
KEYWORD
;
END
=
4
,
VALUE
=
5
;
private
static
final
int
IDENTIFIER
=
ParserUtil
.
IDENTIFIER
;
private
static
final
int
EQUAL
=
6
,
BIGGER_EQUAL
=
7
,
BIGGER
=
8
;
private
static
final
int
NULL
=
ParserUtil
.
NULL
;
private
static
final
int
SMALLER
=
9
,
SMALLER_EQUAL
=
10
,
NOT_EQUAL
=
11
,
private
static
final
int
TRUE
=
ParserUtil
.
TRUE
;
AT
=
12
;
private
static
final
int
FALSE
=
ParserUtil
.
FALSE
;
private
static
final
int
MINUS
=
13
,
PLUS
=
14
,
STRING_CONCAT
=
15
;
private
static
final
int
ROWNUM
=
ParserUtil
.
ROWNUM
;
private
static
final
int
OPEN
=
16
,
CLOSE
=
17
,
NULL
=
18
,
TRUE
=
19
,
private
static
final
int
PARAMETER
=
10
,
END
=
11
,
VALUE
=
12
;
FALSE
=
20
;
private
static
final
int
EQUAL
=
13
,
BIGGER_EQUAL
=
14
,
BIGGER
=
15
;
private
static
final
int
ROWNUM
=
24
;
private
static
final
int
SMALLER
=
16
,
SMALLER_EQUAL
=
17
,
NOT_EQUAL
=
18
;
private
static
final
int
AT
=
19
;
private
static
final
int
MINUS
=
20
,
PLUS
=
21
,
STRING_CONCAT
=
22
;
private
static
final
int
OPEN
=
23
,
CLOSE
=
24
;
private
static
final
int
SPATIAL_INTERSECTS
=
25
;
private
static
final
int
SPATIAL_INTERSECTS
=
25
;
private
static
final
Comparator
<
TableFilter
>
TABLE_FILTER_COMPARATOR
=
private
static
final
Comparator
<
TableFilter
>
TABLE_FILTER_COMPARATOR
=
...
@@ -4170,140 +4174,11 @@ public class Parser {
...
@@ -4170,140 +4174,11 @@ public class Parser {
// if not yet converted to uppercase, do it now
// if not yet converted to uppercase, do it now
s
=
StringUtils
.
toUpperEnglish
(
s
);
s
=
StringUtils
.
toUpperEnglish
(
s
);
}
}
return
isKeyword
(
s
,
false
);
return
ParserUtil
.
isKeyword
(
s
,
false
);
}
/**
* Checks if this string is a SQL keyword.
*
* @param s the token to check
* @param supportOffsetFetch if OFFSET and FETCH are keywords
* @return true if it is a keyword
*/
public
static
boolean
isKeyword
(
String
s
,
boolean
supportOffsetFetch
)
{
if
(
s
==
null
||
s
.
length
()
==
0
)
{
return
false
;
}
return
getSaveTokenType
(
s
,
supportOffsetFetch
,
false
)
!=
IDENTIFIER
;
}
}
private
static
int
getSaveTokenType
(
String
s
,
boolean
supportOffsetFetch
,
boolean
functionsAsKeywords
)
{
private
static
int
getSaveTokenType
(
String
s
,
boolean
supportOffsetFetch
,
boolean
functionsAsKeywords
)
{
switch
(
s
.
charAt
(
0
))
{
return
ParserUtil
.
getSaveTokenType
(
s
,
supportOffsetFetch
,
functionsAsKeywords
);
case
'A'
:
return
getKeywordOrIdentifier
(
s
,
"ALL"
,
KEYWORD
);
case
'C'
:
if
(
"CHECK"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"CONSTRAINT"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"CROSS"
.
equals
(
s
))
{
return
KEYWORD
;
}
if
(
functionsAsKeywords
)
{
if
(
"CURRENT_DATE"
.
equals
(
s
)
||
"CURRENT_TIME"
.
equals
(
s
)
||
"CURRENT_TIMESTAMP"
.
equals
(
s
))
{
return
KEYWORD
;
}
}
return
IDENTIFIER
;
case
'D'
:
return
getKeywordOrIdentifier
(
s
,
"DISTINCT"
,
KEYWORD
);
case
'E'
:
if
(
"EXCEPT"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"EXISTS"
,
KEYWORD
);
case
'F'
:
if
(
"FROM"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"FOR"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"FOREIGN"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"FULL"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
supportOffsetFetch
&&
"FETCH"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"FALSE"
,
FALSE
);
case
'G'
:
return
getKeywordOrIdentifier
(
s
,
"GROUP"
,
KEYWORD
);
case
'H'
:
return
getKeywordOrIdentifier
(
s
,
"HAVING"
,
KEYWORD
);
case
'I'
:
if
(
"INNER"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"INTERSECT"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"IS"
,
KEYWORD
);
case
'J'
:
return
getKeywordOrIdentifier
(
s
,
"JOIN"
,
KEYWORD
);
case
'L'
:
if
(
"LIMIT"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"LIKE"
,
KEYWORD
);
case
'M'
:
return
getKeywordOrIdentifier
(
s
,
"MINUS"
,
KEYWORD
);
case
'N'
:
if
(
"NOT"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"NATURAL"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"NULL"
,
NULL
);
case
'O'
:
if
(
"ON"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
supportOffsetFetch
&&
"OFFSET"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"ORDER"
,
KEYWORD
);
case
'P'
:
return
getKeywordOrIdentifier
(
s
,
"PRIMARY"
,
KEYWORD
);
case
'R'
:
return
getKeywordOrIdentifier
(
s
,
"ROWNUM"
,
ROWNUM
);
case
'S'
:
if
(
"SELECT"
.
equals
(
s
))
{
return
KEYWORD
;
}
if
(
functionsAsKeywords
)
{
if
(
"SYSDATE"
.
equals
(
s
)
||
"SYSTIME"
.
equals
(
s
)
||
"SYSTIMESTAMP"
.
equals
(
s
))
{
return
KEYWORD
;
}
}
return
IDENTIFIER
;
case
'T'
:
if
(
"TRUE"
.
equals
(
s
))
{
return
TRUE
;
}
if
(
functionsAsKeywords
)
{
if
(
"TODAY"
.
equals
(
s
))
{
return
KEYWORD
;
}
}
return
IDENTIFIER
;
case
'U'
:
if
(
"UNIQUE"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"UNION"
,
KEYWORD
);
case
'W'
:
if
(
"WITH"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"WHERE"
,
KEYWORD
);
default
:
return
IDENTIFIER
;
}
}
private
static
int
getKeywordOrIdentifier
(
String
s1
,
String
s2
,
int
keywordType
)
{
if
(
s1
.
equals
(
s2
))
{
return
keywordType
;
}
return
IDENTIFIER
;
}
}
private
Column
parseColumnForTable
(
String
columnName
,
private
Column
parseColumnForTable
(
String
columnName
,
...
@@ -6890,8 +6765,9 @@ public class Parser {
...
@@ -6890,8 +6765,9 @@ public class Parser {
if
(
s
==
null
)
{
if
(
s
==
null
)
{
return
"\"\""
;
return
"\"\""
;
}
}
if
(
isSimpleIdentifier
(
s
,
false
))
if
(
isSimpleIdentifier
(
s
,
false
))
{
return
s
;
return
s
;
}
return
StringUtils
.
quoteIdentifier
(
s
);
return
StringUtils
.
quoteIdentifier
(
s
);
}
}
...
@@ -6904,22 +6780,7 @@ public class Parser {
...
@@ -6904,22 +6780,7 @@ public class Parser {
* @throws NullPointerException if s is {@code null}
* @throws NullPointerException if s is {@code null}
*/
*/
public
static
boolean
isSimpleIdentifier
(
String
s
,
boolean
functionsAsKeywords
)
{
public
static
boolean
isSimpleIdentifier
(
String
s
,
boolean
functionsAsKeywords
)
{
if
(
s
.
length
()
==
0
)
{
return
ParserUtil
.
isSimpleIdentifier
(
s
,
functionsAsKeywords
);
return
false
;
}
char
c
=
s
.
charAt
(
0
);
// lowercase a-z is quoted as well
if
((!
Character
.
isLetter
(
c
)
&&
c
!=
'_'
)
||
Character
.
isLowerCase
(
c
))
{
return
false
;
}
for
(
int
i
=
1
,
length
=
s
.
length
();
i
<
length
;
i
++)
{
c
=
s
.
charAt
(
i
);
if
((!
Character
.
isLetterOrDigit
(
c
)
&&
c
!=
'_'
)
||
Character
.
isLowerCase
(
c
))
{
return
false
;
}
}
return
getSaveTokenType
(
s
,
true
,
functionsAsKeywords
)
==
IDENTIFIER
;
}
}
public
void
setLiteralsChecked
(
boolean
literalsChecked
)
{
public
void
setLiteralsChecked
(
boolean
literalsChecked
)
{
...
...
h2/src/main/org/h2/expression/Aggregate.java
浏览文件 @
9ca0e68e
...
@@ -311,7 +311,7 @@ public class Aggregate extends Expression {
...
@@ -311,7 +311,7 @@ public class Aggregate extends Expression {
return
v
;
return
v
;
}
}
case
MEDIAN:
{
case
MEDIAN:
{
return
AggregateDataMedian
.
getFromIndex
(
session
,
on
,
dataType
);
return
AggregateDataMedian
.
get
Result
FromIndex
(
session
,
on
,
dataType
);
}
}
default
:
default
:
DbException
.
throwInternalError
(
"type="
+
type
);
DbException
.
throwInternalError
(
"type="
+
type
);
...
...
h2/src/main/org/h2/expression/AggregateDataMedian.java
浏览文件 @
9ca0e68e
...
@@ -49,6 +49,12 @@ class AggregateDataMedian extends AggregateData {
...
@@ -49,6 +49,12 @@ class AggregateDataMedian extends AggregateData {
||
(
sortType
&
SortOrder
.
DESCENDING
)
!=
0
&&
(
sortType
&
SortOrder
.
NULLS_FIRST
)
==
0
;
||
(
sortType
&
SortOrder
.
DESCENDING
)
!=
0
&&
(
sortType
&
SortOrder
.
NULLS_FIRST
)
==
0
;
}
}
/**
* Get the index (if any) for the column specified in the median aggregate.
*
* @param on the expression (usually a column expression)
* @return the index, or null
*/
static
Index
getMedianColumnIndex
(
Expression
on
)
{
static
Index
getMedianColumnIndex
(
Expression
on
)
{
if
(
on
instanceof
ExpressionColumn
)
{
if
(
on
instanceof
ExpressionColumn
)
{
ExpressionColumn
col
=
(
ExpressionColumn
)
on
;
ExpressionColumn
col
=
(
ExpressionColumn
)
on
;
...
@@ -68,8 +74,8 @@ class AggregateDataMedian extends AggregateData {
...
@@ -68,8 +74,8 @@ class AggregateDataMedian extends AggregateData {
if
(!
index
.
isFirstColumn
(
column
))
{
if
(!
index
.
isFirstColumn
(
column
))
{
continue
;
continue
;
}
}
if
(
result
==
null
||
result
.
getColumns
().
length
>
index
.
getColumns
().
length
// Prefer index without nulls last for nullable columns
// Prefer index without nulls last for nullable columns
if
(
result
==
null
||
result
.
getColumns
().
length
>
index
.
getColumns
().
length
||
nullable
&&
isNullsLast
(
result
)
&&
!
isNullsLast
(
index
))
{
||
nullable
&&
isNullsLast
(
result
)
&&
!
isNullsLast
(
index
))
{
result
=
index
;
result
=
index
;
}
}
...
@@ -81,7 +87,15 @@ class AggregateDataMedian extends AggregateData {
...
@@ -81,7 +87,15 @@ class AggregateDataMedian extends AggregateData {
return
null
;
return
null
;
}
}
static
Value
getFromIndex
(
Session
session
,
Expression
on
,
int
dataType
)
{
/**
* Get the result from the index.
*
* @param session the session
* @param on the expression
* @param dataType the data type
* @return the result
*/
static
Value
getResultFromIndex
(
Session
session
,
Expression
on
,
int
dataType
)
{
Index
index
=
getMedianColumnIndex
(
on
);
Index
index
=
getMedianColumnIndex
(
on
);
long
count
=
index
.
getRowCount
(
session
);
long
count
=
index
.
getRowCount
(
session
);
if
(
count
==
0
)
{
if
(
count
==
0
)
{
...
@@ -94,10 +108,8 @@ class AggregateDataMedian extends AggregateData {
...
@@ -94,10 +108,8 @@ class AggregateDataMedian extends AggregateData {
if
(
expr
.
getColumn
().
isNullable
())
{
if
(
expr
.
getColumn
().
isNullable
())
{
boolean
hasNulls
=
false
;
boolean
hasNulls
=
false
;
SearchRow
row
;
SearchRow
row
;
/*
// Try to skip nulls from the start first with the same cursor that
* Try to skip nulls from the start first with the same cursor that will be used
// will be used to read values.
* to read values.
*/
while
(
count
>
0
)
{
while
(
count
>
0
)
{
row
=
cursor
.
getSearchRow
();
row
=
cursor
.
getSearchRow
();
if
(
row
==
null
)
{
if
(
row
==
null
)
{
...
@@ -113,10 +125,8 @@ class AggregateDataMedian extends AggregateData {
...
@@ -113,10 +125,8 @@ class AggregateDataMedian extends AggregateData {
if
(
count
==
0
)
{
if
(
count
==
0
)
{
return
ValueNull
.
INSTANCE
;
return
ValueNull
.
INSTANCE
;
}
}
/*
// If no nulls found and if index orders nulls last create a second
* If no nulls found and if index orders nulls last create a second cursor to
// cursor to count nulls at the end.
* count nulls at the end.
*/
if
(!
hasNulls
&&
isNullsLast
(
index
))
{
if
(!
hasNulls
&&
isNullsLast
(
index
))
{
TableFilter
tableFilter
=
expr
.
getTableFilter
();
TableFilter
tableFilter
=
expr
.
getTableFilter
();
SearchRow
check
=
tableFilter
.
getTable
().
getTemplateSimpleRow
(
true
);
SearchRow
check
=
tableFilter
.
getTable
().
getTemplateSimpleRow
(
true
);
...
@@ -196,7 +206,7 @@ class AggregateDataMedian extends AggregateData {
...
@@ -196,7 +206,7 @@ class AggregateDataMedian extends AggregateData {
return
getMedian
(
a
[
idx
-
1
],
v1
,
dataType
,
mode
);
return
getMedian
(
a
[
idx
-
1
],
v1
,
dataType
,
mode
);
}
}
static
Value
getMedian
(
Value
v0
,
Value
v1
,
int
dataType
,
CompareMode
mode
)
{
private
static
Value
getMedian
(
Value
v0
,
Value
v1
,
int
dataType
,
CompareMode
mode
)
{
if
(
v0
.
compareTo
(
v1
,
mode
)
==
0
)
{
if
(
v0
.
compareTo
(
v1
,
mode
)
==
0
)
{
return
v0
.
convertTo
(
dataType
);
return
v0
.
convertTo
(
dataType
);
}
}
...
...
h2/src/main/org/h2/expression/Comparison.java
浏览文件 @
9ca0e68e
...
@@ -12,6 +12,7 @@ import org.h2.engine.Session;
...
@@ -12,6 +12,7 @@ import org.h2.engine.Session;
import
org.h2.engine.SysProperties
;
import
org.h2.engine.SysProperties
;
import
org.h2.index.IndexCondition
;
import
org.h2.index.IndexCondition
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.table.Column
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.table.TableFilter
;
import
org.h2.util.MathUtils
;
import
org.h2.util.MathUtils
;
...
@@ -202,9 +203,10 @@ public class Comparison extends Condition {
...
@@ -202,9 +203,10 @@ public class Comparison extends Condition {
// to constant type, but vise versa, then let's do this here
// to constant type, but vise versa, then let's do this here
// once.
// once.
if
(
constType
!=
resType
)
{
if
(
constType
!=
resType
)
{
Column
column
=
((
ExpressionColumn
)
left
).
getColumn
();
right
=
ValueExpression
.
get
(
r
.
convertTo
(
resType
,
right
=
ValueExpression
.
get
(
r
.
convertTo
(
resType
,
MathUtils
.
convertLongToInt
(
left
.
getPrecision
()),
MathUtils
.
convertLongToInt
(
left
.
getPrecision
()),
session
.
getDatabase
().
getMode
(),
((
ExpressionColumn
)
left
).
getColumn
()));
session
.
getDatabase
().
getMode
(),
column
,
column
.
getEnumerators
()));
}
}
}
else
if
(
right
instanceof
Parameter
)
{
}
else
if
(
right
instanceof
Parameter
)
{
((
Parameter
)
right
).
setColumn
(
((
Parameter
)
right
).
setColumn
(
...
...
h2/src/main/org/h2/expression/ConditionInParameter.java
浏览文件 @
9ca0e68e
...
@@ -57,7 +57,7 @@ public class ConditionInParameter extends Condition {
...
@@ -57,7 +57,7 @@ public class ConditionInParameter extends Condition {
private
Expression
left
;
private
Expression
left
;
final
Parameter
parameter
;
private
final
Parameter
parameter
;
/**
/**
* Create a new {@code = ANY(?)} condition.
* Create a new {@code = ANY(?)} condition.
...
...
h2/src/main/org/h2/expression/Function.java
浏览文件 @
9ca0e68e
...
@@ -15,10 +15,10 @@ import java.nio.charset.StandardCharsets;
...
@@ -15,10 +15,10 @@ import java.nio.charset.StandardCharsets;
import
java.sql.Connection
;
import
java.sql.Connection
;
import
java.sql.ResultSet
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
java.sql.Timestamp
;
import
java.text.SimpleDateFormat
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Calendar
;
import
java.util.Calendar
;
import
java.util.GregorianCalendar
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Locale
;
import
java.util.Locale
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
...
@@ -173,6 +173,7 @@ public class Function extends Expression implements FunctionCall {
...
@@ -173,6 +173,7 @@ public class Function extends Expression implements FunctionCall {
DATE_PART
.
put
(
"MONTH"
,
MONTH
);
DATE_PART
.
put
(
"MONTH"
,
MONTH
);
DATE_PART
.
put
(
"MM"
,
MONTH
);
DATE_PART
.
put
(
"MM"
,
MONTH
);
DATE_PART
.
put
(
"M"
,
MONTH
);
DATE_PART
.
put
(
"M"
,
MONTH
);
DATE_PART
.
put
(
"QUARTER"
,
QUARTER
);
DATE_PART
.
put
(
"SQL_TSI_WEEK"
,
WEEK
);
DATE_PART
.
put
(
"SQL_TSI_WEEK"
,
WEEK
);
DATE_PART
.
put
(
"WW"
,
WEEK
);
DATE_PART
.
put
(
"WW"
,
WEEK
);
DATE_PART
.
put
(
"WK"
,
WEEK
);
DATE_PART
.
put
(
"WK"
,
WEEK
);
...
@@ -351,7 +352,7 @@ public class Function extends Expression implements FunctionCall {
...
@@ -351,7 +352,7 @@ public class Function extends Expression implements FunctionCall {
addFunction
(
"DATEADD"
,
DATE_ADD
,
addFunction
(
"DATEADD"
,
DATE_ADD
,
3
,
Value
.
TIMESTAMP
);
3
,
Value
.
TIMESTAMP
);
addFunction
(
"TIMESTAMPADD"
,
DATE_ADD
,
addFunction
(
"TIMESTAMPADD"
,
DATE_ADD
,
3
,
Value
.
LONG
);
3
,
Value
.
TIMESTAMP
);
addFunction
(
"DATEDIFF"
,
DATE_DIFF
,
addFunction
(
"DATEDIFF"
,
DATE_DIFF
,
3
,
Value
.
LONG
);
3
,
Value
.
LONG
);
addFunction
(
"TIMESTAMPDIFF"
,
DATE_DIFF
,
addFunction
(
"TIMESTAMPDIFF"
,
DATE_DIFF
,
...
@@ -858,7 +859,7 @@ public class Function extends Expression implements FunctionCall {
...
@@ -858,7 +859,7 @@ public class Function extends Expression implements FunctionCall {
case
SECOND:
case
SECOND:
case
WEEK:
case
WEEK:
case
YEAR:
case
YEAR:
result
=
ValueInt
.
get
(
DateTimeUtils
.
getDatePart
(
v0
,
info
.
type
));
result
=
ValueInt
.
get
(
getDatePart
(
v0
,
info
.
type
));
break
;
break
;
case
MONTH_NAME:
{
case
MONTH_NAME:
{
SimpleDateFormat
monthName
=
new
SimpleDateFormat
(
"MMMM"
,
SimpleDateFormat
monthName
=
new
SimpleDateFormat
(
"MMMM"
,
...
@@ -1489,8 +1490,7 @@ public class Function extends Expression implements FunctionCall {
...
@@ -1489,8 +1490,7 @@ public class Function extends Expression implements FunctionCall {
database
.
getMode
().
treatEmptyStringsAsNull
);
database
.
getMode
().
treatEmptyStringsAsNull
);
break
;
break
;
case
DATE_ADD:
case
DATE_ADD:
result
=
ValueTimestamp
.
get
(
dateadd
(
result
=
dateadd
(
v0
.
getString
(),
v1
.
getLong
(),
v2
);
v0
.
getString
(),
v1
.
getLong
(),
v2
.
getTimestamp
()));
break
;
break
;
case
DATE_DIFF:
case
DATE_DIFF:
result
=
ValueLong
.
get
(
datediff
(
v0
.
getString
(),
v1
,
v2
));
result
=
ValueLong
.
get
(
datediff
(
v0
.
getString
(),
v1
,
v2
));
...
@@ -1848,53 +1848,85 @@ public class Function extends Expression implements FunctionCall {
...
@@ -1848,53 +1848,85 @@ public class Function extends Expression implements FunctionCall {
return
p
.
intValue
();
return
p
.
intValue
();
}
}
private
static
Timestamp
dateadd
(
String
part
,
long
count
,
Timestamp
d
)
{
private
static
Value
dateadd
(
String
part
,
long
count
,
Value
v
)
{
int
field
=
getDatePart
(
part
);
int
field
=
getDatePart
(
part
);
//v = v.convertTo(Value.TIMESTAMP);
if
(
field
!=
MILLISECOND
&&
(
count
>
Integer
.
MAX_VALUE
||
count
<
Integer
.
MIN_VALUE
))
{
throw
DbException
.
getInvalidValueException
(
"DATEADD count"
,
count
);
}
boolean
withDate
=
!(
v
instanceof
ValueTime
);
boolean
withTime
=
!(
v
instanceof
ValueDate
);
boolean
forceTimestamp
=
false
;
long
[]
a
=
DateTimeUtils
.
dateAndTimeFromValue
(
v
);
long
dateValue
=
a
[
0
];
long
timeNanos
=
a
[
1
];
switch
(
field
)
{
switch
(
field
)
{
case
QUARTER:
count
*=
3
;
//$FALL-THROUGH$
case
YEAR:
case
YEAR:
field
=
Calendar
.
YEAR
;
case
MONTH:
{
break
;
if
(!
withDate
)
{
case
MONTH:
throw
DbException
.
getInvalidValueException
(
"DATEADD time part"
,
part
);
field
=
Calendar
.
MONTH
;
}
break
;
long
year
=
DateTimeUtils
.
yearFromDateValue
(
dateValue
);
long
month
=
DateTimeUtils
.
monthFromDateValue
(
dateValue
);
int
day
=
DateTimeUtils
.
dayFromDateValue
(
dateValue
);
if
(
field
==
YEAR
)
{
year
+=
count
;
}
else
{
month
+=
count
;
}
dateValue
=
DateTimeUtils
.
dateValueFromDenormalizedDate
(
year
,
month
,
day
);
return
DateTimeUtils
.
dateTimeToValue
(
v
,
dateValue
,
timeNanos
,
forceTimestamp
);
}
case
WEEK:
case
ISO_WEEK:
count
*=
7
;
//$FALL-THROUGH$
case
DAY_OF_WEEK:
case
DAY_OF_MONTH:
case
DAY_OF_MONTH:
field
=
Calendar
.
DAY_OF_MONTH
;
break
;
case
DAY_OF_YEAR:
case
DAY_OF_YEAR:
field
=
Calendar
.
DAY_OF_YEAR
;
if
(!
withDate
)
{
break
;
throw
DbException
.
getInvalidValueException
(
"DATEADD time part"
,
part
);
case
WEEK:
}
field
=
Calendar
.
WEEK_OF_YEAR
;
dateValue
=
DateTimeUtils
.
dateValueFromAbsoluteDay
(
break
;
DateTimeUtils
.
absoluteDayFromDateValue
(
dateValue
)
+
count
);
return
DateTimeUtils
.
dateTimeToValue
(
v
,
dateValue
,
timeNanos
,
forceTimestamp
);
case
HOUR:
case
HOUR:
field
=
Calendar
.
HOUR_OF_DAY
;
count
*=
3_600_000_000_000L
;
break
;
break
;
case
MINUTE:
case
MINUTE:
field
=
Calendar
.
MINUTE
;
count
*=
60_000_000_000L
;
break
;
break
;
case
SECOND:
case
SECOND:
field
=
Calendar
.
SECOND
;
count
*=
1_000_000_000
;
break
;
case
MILLISECOND:
count
*=
1_000_000
;
break
;
break
;
case
MILLISECOND:
{
Timestamp
ts
=
new
Timestamp
(
d
.
getTime
()
+
count
);
ts
.
setNanos
(
ts
.
getNanos
()
+
(
d
.
getNanos
()
%
1000000
));
return
ts
;
}
default
:
default
:
throw
DbException
.
getUnsupportedException
(
"DATEADD "
+
part
);
throw
DbException
.
getUnsupportedException
(
"DATEADD "
+
part
);
}
}
// We allow long for manipulating the millisecond component,
if
(!
withTime
)
{
// for the rest we only allow int.
// Treat date as timestamp at the start of this date
if
(
count
>
Integer
.
MAX_VALUE
)
{
forceTimestamp
=
true
;
throw
DbException
.
getInvalidValueException
(
"DATEADD count"
,
count
);
}
}
Calendar
calendar
=
DateTimeUtils
.
createGregorianCalendar
();
timeNanos
+=
count
;
int
nanos
=
d
.
getNanos
()
%
1000000
;
if
(
timeNanos
>
DateTimeUtils
.
NANOS_PER_DAY
||
timeNanos
<
0
)
{
calendar
.
setTime
(
d
);
long
d
;
calendar
.
add
(
field
,
(
int
)
count
);
if
(
timeNanos
>
DateTimeUtils
.
NANOS_PER_DAY
)
{
Timestamp
ts
=
new
Timestamp
(
calendar
.
getTimeInMillis
());
d
=
timeNanos
/
DateTimeUtils
.
NANOS_PER_DAY
;
ts
.
setNanos
(
ts
.
getNanos
()
+
nanos
);
}
else
{
return
ts
;
d
=
(
timeNanos
-
DateTimeUtils
.
NANOS_PER_DAY
+
1
)
/
DateTimeUtils
.
NANOS_PER_DAY
;
}
timeNanos
-=
d
*
DateTimeUtils
.
NANOS_PER_DAY
;
return
DateTimeUtils
.
dateTimeToValue
(
v
,
DateTimeUtils
.
dateValueFromAbsoluteDay
(
DateTimeUtils
.
absoluteDayFromDateValue
(
dateValue
)
+
d
),
timeNanos
,
forceTimestamp
);
}
return
DateTimeUtils
.
dateTimeToValue
(
v
,
dateValue
,
timeNanos
,
forceTimestamp
);
}
}
/**
/**
...
@@ -1950,6 +1982,10 @@ public class Function extends Expression implements FunctionCall {
...
@@ -1950,6 +1982,10 @@ public class Function extends Expression implements FunctionCall {
case
MONTH:
case
MONTH:
return
(
DateTimeUtils
.
yearFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
yearFromDateValue
(
dateValue1
))
*
12
return
(
DateTimeUtils
.
yearFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
yearFromDateValue
(
dateValue1
))
*
12
+
DateTimeUtils
.
monthFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
monthFromDateValue
(
dateValue1
);
+
DateTimeUtils
.
monthFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
monthFromDateValue
(
dateValue1
);
case
QUARTER:
return
(
DateTimeUtils
.
yearFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
yearFromDateValue
(
dateValue1
))
*
4
+
(
DateTimeUtils
.
monthFromDateValue
(
dateValue2
)
-
1
)
/
3
-
(
DateTimeUtils
.
monthFromDateValue
(
dateValue1
)
-
1
)
/
3
;
case
YEAR:
case
YEAR:
return
DateTimeUtils
.
yearFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
yearFromDateValue
(
dateValue1
);
return
DateTimeUtils
.
yearFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
yearFromDateValue
(
dateValue1
);
default
:
default
:
...
@@ -2806,6 +2842,52 @@ public class Function extends Expression implements FunctionCall {
...
@@ -2806,6 +2842,52 @@ public class Function extends Expression implements FunctionCall {
}
}
}
}
/**
* Get the specified field of a date, however with years normalized to
* positive or negative, and month starting with 1.
*
* @param date the date value
* @param field the field type, see {@link Function} for constants
* @return the value
*/
public
static
int
getDatePart
(
Value
date
,
int
field
)
{
long
[]
a
=
DateTimeUtils
.
dateAndTimeFromValue
(
date
);
long
dateValue
=
a
[
0
];
long
timeNanos
=
a
[
1
];
switch
(
field
)
{
case
Function
.
YEAR
:
return
DateTimeUtils
.
yearFromDateValue
(
dateValue
);
case
Function
.
MONTH
:
return
DateTimeUtils
.
monthFromDateValue
(
dateValue
);
case
Function
.
DAY_OF_MONTH
:
return
DateTimeUtils
.
dayFromDateValue
(
dateValue
);
case
Function
.
HOUR
:
return
(
int
)
(
timeNanos
/
3_600_000_000_000L
%
24
);
case
Function
.
MINUTE
:
return
(
int
)
(
timeNanos
/
60_000_000_000L
%
60
);
case
Function
.
SECOND
:
return
(
int
)
(
timeNanos
/
1_000_000_000
%
60
);
case
Function
.
MILLISECOND
:
return
(
int
)
(
timeNanos
/
1_000_000
%
1_000
);
case
Function
.
DAY_OF_YEAR
:
return
DateTimeUtils
.
getDayOfYear
(
dateValue
);
case
Function
.
DAY_OF_WEEK
:
return
DateTimeUtils
.
getSundayDayOfWeek
(
dateValue
);
case
Function
.
WEEK
:
GregorianCalendar
gc
=
DateTimeUtils
.
getCalendar
();
return
DateTimeUtils
.
getWeekOfYear
(
dateValue
,
gc
.
getFirstDayOfWeek
()
-
1
,
gc
.
getMinimalDaysInFirstWeek
());
case
Function
.
QUARTER
:
return
(
DateTimeUtils
.
monthFromDateValue
(
dateValue
)
-
1
)
/
3
+
1
;
case
Function
.
ISO_YEAR
:
return
DateTimeUtils
.
getIsoWeekYear
(
dateValue
);
case
Function
.
ISO_WEEK
:
return
DateTimeUtils
.
getIsoWeekOfYear
(
dateValue
);
case
Function
.
ISO_DAY_OF_WEEK
:
return
DateTimeUtils
.
getIsoDayOfWeek
(
dateValue
);
}
throw
DbException
.
getUnsupportedException
(
"getDatePart("
+
date
+
", "
+
field
+
')'
);
}
@Override
@Override
public
Expression
[]
getArgs
()
{
public
Expression
[]
getArgs
()
{
return
args
;
return
args
;
...
...
h2/src/main/org/h2/jdbc/JdbcStatement.java
浏览文件 @
9ca0e68e
...
@@ -13,13 +13,13 @@ import java.sql.Statement;
...
@@ -13,13 +13,13 @@ import java.sql.Statement;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.CommandInterface
;
import
org.h2.command.CommandInterface
;
import
org.h2.command.Parser
;
import
org.h2.engine.SessionInterface
;
import
org.h2.engine.SessionInterface
;
import
org.h2.engine.SysProperties
;
import
org.h2.engine.SysProperties
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.message.TraceObject
;
import
org.h2.message.TraceObject
;
import
org.h2.result.ResultInterface
;
import
org.h2.result.ResultInterface
;
import
org.h2.util.New
;
import
org.h2.util.New
;
import
org.h2.util.ParserUtil
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
/**
/**
...
@@ -1333,7 +1333,7 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
...
@@ -1333,7 +1333,7 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
*/
*/
@Override
@Override
public
boolean
isSimpleIdentifier
(
String
identifier
)
throws
SQLException
{
public
boolean
isSimpleIdentifier
(
String
identifier
)
throws
SQLException
{
return
Parser
.
isSimpleIdentifier
(
identifier
,
true
);
return
Parser
Util
.
isSimpleIdentifier
(
identifier
,
true
);
}
}
/**
/**
...
...
h2/src/main/org/h2/result/LazyResult.java
浏览文件 @
9ca0e68e
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
*/
*/
package
org
.
h2
.
result
;
package
org
.
h2
.
result
;
import
org.h2.engine.Session
;
import
org.h2.engine.Session
Interface
;
import
org.h2.expression.Expression
;
import
org.h2.expression.Expression
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
...
@@ -180,7 +180,7 @@ public abstract class LazyResult implements ResultInterface {
...
@@ -180,7 +180,7 @@ public abstract class LazyResult implements ResultInterface {
}
}
@Override
@Override
public
ResultInterface
createShallowCopy
(
Session
targetSession
)
{
public
ResultInterface
createShallowCopy
(
Session
Interface
targetSession
)
{
// Copying is impossible with lazy result.
// Copying is impossible with lazy result.
return
null
;
return
null
;
}
}
...
...
h2/src/main/org/h2/result/LocalResult.java
浏览文件 @
9ca0e68e
...
@@ -12,6 +12,7 @@ import java.util.Arrays;
...
@@ -12,6 +12,7 @@ import java.util.Arrays;
import
org.h2.engine.Database
;
import
org.h2.engine.Database
;
import
org.h2.engine.Session
;
import
org.h2.engine.Session
;
import
org.h2.engine.SessionInterface
;
import
org.h2.expression.Expression
;
import
org.h2.expression.Expression
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.util.New
;
import
org.h2.util.New
;
...
@@ -125,7 +126,7 @@ public class LocalResult implements ResultInterface, ResultTarget {
...
@@ -125,7 +126,7 @@ public class LocalResult implements ResultInterface, ResultTarget {
* @return the copy if possible, or null if copying is not possible
* @return the copy if possible, or null if copying is not possible
*/
*/
@Override
@Override
public
LocalResult
createShallowCopy
(
Session
targetSession
)
{
public
LocalResult
createShallowCopy
(
Session
Interface
targetSession
)
{
if
(
external
==
null
&&
(
rows
==
null
||
rows
.
size
()
<
rowCount
))
{
if
(
external
==
null
&&
(
rows
==
null
||
rows
.
size
()
<
rowCount
))
{
return
null
;
return
null
;
}
}
...
@@ -141,7 +142,7 @@ public class LocalResult implements ResultInterface, ResultTarget {
...
@@ -141,7 +142,7 @@ public class LocalResult implements ResultInterface, ResultTarget {
}
}
LocalResult
copy
=
new
LocalResult
();
LocalResult
copy
=
new
LocalResult
();
copy
.
maxMemoryRows
=
this
.
maxMemoryRows
;
copy
.
maxMemoryRows
=
this
.
maxMemoryRows
;
copy
.
session
=
targetSession
;
copy
.
session
=
(
Session
)
targetSession
;
copy
.
visibleColumnCount
=
this
.
visibleColumnCount
;
copy
.
visibleColumnCount
=
this
.
visibleColumnCount
;
copy
.
expressions
=
this
.
expressions
;
copy
.
expressions
=
this
.
expressions
;
copy
.
rowId
=
-
1
;
copy
.
rowId
=
-
1
;
...
...
h2/src/main/org/h2/result/ResultInterface.java
浏览文件 @
9ca0e68e
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
*/
*/
package
org
.
h2
.
result
;
package
org
.
h2
.
result
;
import
org.h2.engine.Session
;
import
org.h2.engine.Session
Interface
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
/**
/**
...
@@ -200,7 +200,7 @@ public interface ResultInterface extends AutoCloseable {
...
@@ -200,7 +200,7 @@ public interface ResultInterface extends AutoCloseable {
* @param targetSession the session of the copy
* @param targetSession the session of the copy
* @return the copy if possible, or null if copying is not possible
* @return the copy if possible, or null if copying is not possible
*/
*/
ResultInterface
createShallowCopy
(
Session
targetSession
);
ResultInterface
createShallowCopy
(
Session
Interface
targetSession
);
/**
/**
* Check if this result set contains the given row.
* Check if this result set contains the given row.
...
...
h2/src/main/org/h2/result/ResultRemote.java
浏览文件 @
9ca0e68e
...
@@ -7,7 +7,7 @@ package org.h2.result;
...
@@ -7,7 +7,7 @@ package org.h2.result;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
org.h2.engine.Session
;
import
org.h2.engine.Session
Interface
;
import
org.h2.engine.SessionRemote
;
import
org.h2.engine.SessionRemote
;
import
org.h2.engine.SysProperties
;
import
org.h2.engine.SysProperties
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
...
@@ -271,7 +271,7 @@ public class ResultRemote implements ResultInterface {
...
@@ -271,7 +271,7 @@ public class ResultRemote implements ResultInterface {
}
}
@Override
@Override
public
ResultInterface
createShallowCopy
(
Session
targetSession
)
{
public
ResultInterface
createShallowCopy
(
Session
Interface
targetSession
)
{
// The operation is not supported on remote result.
// The operation is not supported on remote result.
return
null
;
return
null
;
}
}
...
...
h2/src/main/org/h2/table/Column.java
浏览文件 @
9ca0e68e
...
@@ -173,7 +173,7 @@ public class Column {
...
@@ -173,7 +173,7 @@ public class Column {
*/
*/
public
Value
convert
(
Value
v
,
Mode
mode
)
{
public
Value
convert
(
Value
v
,
Mode
mode
)
{
try
{
try
{
return
v
.
convertTo
(
type
,
MathUtils
.
convertLongToInt
(
precision
),
mode
,
this
);
return
v
.
convertTo
(
type
,
MathUtils
.
convertLongToInt
(
precision
),
mode
,
this
,
getEnumerators
()
);
}
catch
(
DbException
e
)
{
}
catch
(
DbException
e
)
{
if
(
e
.
getErrorCode
()
==
ErrorCode
.
DATA_CONVERSION_ERROR_1
)
{
if
(
e
.
getErrorCode
()
==
ErrorCode
.
DATA_CONVERSION_ERROR_1
)
{
String
target
=
(
table
==
null
?
""
:
table
.
getName
()
+
": "
)
+
String
target
=
(
table
==
null
?
""
:
table
.
getName
()
+
": "
)
+
...
...
h2/src/main/org/h2/util/DateTimeUtils.java
浏览文件 @
9ca0e68e
...
@@ -16,7 +16,6 @@ import java.util.Locale;
...
@@ -16,7 +16,6 @@ import java.util.Locale;
import
java.util.TimeZone
;
import
java.util.TimeZone
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.ErrorCode
;
import
org.h2.engine.Mode
;
import
org.h2.engine.Mode
;
import
org.h2.expression.Function
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
import
org.h2.value.ValueDate
;
import
org.h2.value.ValueDate
;
...
@@ -25,7 +24,6 @@ import org.h2.value.ValueTime;
...
@@ -25,7 +24,6 @@ import org.h2.value.ValueTime;
import
org.h2.value.ValueTimestamp
;
import
org.h2.value.ValueTimestamp
;
import
org.h2.value.ValueTimestampTimeZone
;
import
org.h2.value.ValueTimestampTimeZone
;
/**
/**
* This utility class contains time conversion functions.
* This utility class contains time conversion functions.
* <p>
* <p>
...
@@ -116,7 +114,7 @@ public class DateTimeUtils {
...
@@ -116,7 +114,7 @@ public class DateTimeUtils {
*
*
* @return a calendar instance. A cached instance is returned where possible
* @return a calendar instance. A cached instance is returned where possible
*/
*/
p
rivate
static
GregorianCalendar
getCalendar
()
{
p
ublic
static
GregorianCalendar
getCalendar
()
{
GregorianCalendar
c
=
CACHED_CALENDAR
.
get
();
GregorianCalendar
c
=
CACHED_CALENDAR
.
get
();
if
(
c
==
null
)
{
if
(
c
==
null
)
{
c
=
DateTimeUtils
.
createGregorianCalendar
();
c
=
DateTimeUtils
.
createGregorianCalendar
();
...
@@ -597,49 +595,37 @@ public class DateTimeUtils {
...
@@ -597,49 +595,37 @@ public class DateTimeUtils {
}
}
/**
/**
* Get the specified field of a date, however with years normalized to
* Creates a new date-time value with the same type as original value. If
* positive or negative, and month starting with 1.
* original value is a ValueTimestampTimeZone, returned value will have the same
* time zone offset as original value.
*
*
* @param date the date value
* @param original
* @param field the field type, see {@link Function} for constants
* original value
* @return the value
* @param dateValue
*/
* date value for the returned value
public
static
int
getDatePart
(
Value
date
,
int
field
)
{
* @param timeNanos
long
[]
a
=
dateAndTimeFromValue
(
date
);
* nanos of day for the returned value
long
dateValue
=
a
[
0
];
* @param forceTimestamp
long
timeNanos
=
a
[
1
];
* if {@code true} return ValueTimestamp if original argument is
switch
(
field
)
{
* ValueDate or ValueTime
case
Function
.
YEAR
:
* @return new value with specified date value and nanos of day
return
yearFromDateValue
(
dateValue
);
*/
case
Function
.
MONTH
:
public
static
Value
dateTimeToValue
(
Value
original
,
long
dateValue
,
long
timeNanos
,
boolean
forceTimestamp
)
{
return
monthFromDateValue
(
dateValue
);
if
(!(
original
instanceof
ValueTimestamp
))
{
case
Function
.
DAY_OF_MONTH
:
if
(!
forceTimestamp
)
{
return
dayFromDateValue
(
dateValue
);
if
(
original
instanceof
ValueDate
)
{
case
Function
.
HOUR
:
return
ValueDate
.
fromDateValue
(
dateValue
);
return
(
int
)
(
timeNanos
/
3_600_000_000_000L
%
24
);
}
case
Function
.
MINUTE
:
if
(
original
instanceof
ValueTime
)
{
return
(
int
)
(
timeNanos
/
60_000_000_000L
%
60
);
return
ValueTime
.
fromNanos
(
timeNanos
);
case
Function
.
SECOND
:
}
return
(
int
)
(
timeNanos
/
1_000_000_000
%
60
);
}
case
Function
.
MILLISECOND
:
if
(
original
instanceof
ValueTimestampTimeZone
)
{
return
(
int
)
(
timeNanos
/
1_000_000
%
1_000
);
return
ValueTimestampTimeZone
.
fromDateValueAndNanos
(
dateValue
,
timeNanos
,
case
Function
.
DAY_OF_YEAR
:
((
ValueTimestampTimeZone
)
original
).
getTimeZoneOffsetMins
());
return
getDayOfYear
(
dateValue
);
}
case
Function
.
DAY_OF_WEEK
:
return
getSundayDayOfWeek
(
dateValue
);
case
Function
.
WEEK
:
GregorianCalendar
gc
=
getCalendar
();
return
getWeekOfYear
(
dateValue
,
gc
.
getFirstDayOfWeek
()
-
1
,
gc
.
getMinimalDaysInFirstWeek
());
case
Function
.
QUARTER
:
return
(
monthFromDateValue
(
dateValue
)
-
1
)
/
3
+
1
;
case
Function
.
ISO_YEAR
:
return
getIsoWeekYear
(
dateValue
);
case
Function
.
ISO_WEEK
:
return
getIsoWeekOfYear
(
dateValue
);
case
Function
.
ISO_DAY_OF_WEEK
:
return
getIsoDayOfWeek
(
dateValue
);
}
}
throw
DbException
.
getUnsupportedException
(
"getDatePart("
+
date
+
", "
+
field
+
')'
);
return
ValueTimestamp
.
fromDateValueAndNanos
(
dateValue
,
timeNanos
);
}
}
/**
/**
...
@@ -882,6 +868,26 @@ public class DateTimeUtils {
...
@@ -882,6 +868,26 @@ public class DateTimeUtils {
}
}
}
}
/**
* Returns number of days in month.
*
* @param year the year
* @param month the month
* @return number of days in the specified month
*/
public
static
int
getDaysInMonth
(
int
year
,
int
month
)
{
if
(
month
!=
2
)
{
return
NORMAL_DAYS_PER_MONTH
[
month
];
}
// All leap years divisible by 4
return
(
year
&
3
)
==
0
// All such years before 1582 are Julian and leap
&&
(
year
<
1582
// Otherwise check Gregorian conditions
||
year
%
100
!=
0
||
year
%
400
==
0
)
?
29
:
28
;
}
/**
/**
* Verify if the specified date is valid.
* Verify if the specified date is valid.
*
*
...
@@ -894,24 +900,11 @@ public class DateTimeUtils {
...
@@ -894,24 +900,11 @@ public class DateTimeUtils {
if
(
month
<
1
||
month
>
12
||
day
<
1
)
{
if
(
month
<
1
||
month
>
12
||
day
<
1
)
{
return
false
;
return
false
;
}
}
if
(
year
>
1582
)
{
if
(
year
==
1582
&&
month
==
10
)
{
// Gregorian calendar
if
(
month
!=
2
)
{
return
day
<=
NORMAL_DAYS_PER_MONTH
[
month
];
}
// February
if
((
year
&
3
)
!=
0
)
{
return
day
<=
28
;
}
return
day
<=
((
year
%
100
!=
0
)
||
(
year
%
400
==
0
)
?
29
:
28
);
}
else
if
(
year
==
1582
&&
month
==
10
)
{
// special case: days 1582-10-05 .. 1582-10-14 don't exist
// special case: days 1582-10-05 .. 1582-10-14 don't exist
return
day
<=
31
&&
(
day
<
5
||
day
>
14
);
return
day
<
5
||
(
day
>
14
&&
day
<=
31
);
}
if
(
month
!=
2
&&
day
<=
NORMAL_DAYS_PER_MONTH
[
month
])
{
return
true
;
}
}
return
day
<=
((
year
&
3
)
!=
0
?
28
:
29
);
return
day
<=
getDaysInMonth
(
year
,
month
);
}
}
/**
/**
...
@@ -1037,6 +1030,38 @@ public class DateTimeUtils {
...
@@ -1037,6 +1030,38 @@ public class DateTimeUtils {
return
(
year
<<
SHIFT_YEAR
)
|
(
month
<<
SHIFT_MONTH
)
|
day
;
return
(
year
<<
SHIFT_YEAR
)
|
(
month
<<
SHIFT_MONTH
)
|
day
;
}
}
/**
* Get the date value from a given denormalized date with possible out of range
* values of month and/or day. Used after addition or subtraction month or years
* to (from) it to get a valid date.
*
* @param year
* the year
* @param month
* the month, if out of range month and year will be normalized
* @param day
* the day of the month, if out of range it will be saturated
* @return the date value
*/
public
static
long
dateValueFromDenormalizedDate
(
long
year
,
long
month
,
int
day
)
{
long
mm1
=
month
-
1
;
long
yd
=
mm1
/
12
;
if
(
mm1
<
0
&&
yd
*
12
!=
mm1
)
{
yd
--;
}
int
y
=
(
int
)
(
year
+
yd
);
int
m
=
(
int
)
(
month
-
yd
*
12
);
if
(
day
<
1
)
{
day
=
1
;
}
else
{
int
max
=
getDaysInMonth
(
y
,
m
);
if
(
day
>
max
)
{
day
=
max
;
}
}
return
dateValue
(
y
,
m
,
day
);
}
/**
/**
* Convert a UTC datetime in millis to an encoded date in the default
* Convert a UTC datetime in millis to an encoded date in the default
* timezone.
* timezone.
...
...
h2/src/main/org/h2/util/ParserUtil.java
0 → 100644
浏览文件 @
9ca0e68e
/*
* 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
.
util
;
public
class
ParserUtil
{
/**
* A keyword.
*/
public
static
final
int
KEYWORD
=
1
;
/**
* An identifier (table name, column name,...).
*/
public
static
final
int
IDENTIFIER
=
2
;
/**
* The token "null".
*/
public
static
final
int
NULL
=
3
;
/**
* The token "true".
*/
public
static
final
int
TRUE
=
4
;
/**
* The token "false".
*/
public
static
final
int
FALSE
=
5
;
/**
* The token "rownum".
*/
public
static
final
int
ROWNUM
=
6
;
private
ParserUtil
()
{
// utility class
}
/**
* Checks if this string is a SQL keyword.
*
* @param s the token to check
* @param supportOffsetFetch if OFFSET and FETCH are keywords
* @return true if it is a keyword
*/
public
static
boolean
isKeyword
(
String
s
,
boolean
supportOffsetFetch
)
{
if
(
s
==
null
||
s
.
length
()
==
0
)
{
return
false
;
}
return
getSaveTokenType
(
s
,
supportOffsetFetch
,
false
)
!=
IDENTIFIER
;
}
/**
* Is this a simple identifier (in the JDBC specification sense).
*
* @param s identifier to check
* @param functionsAsKeywords treat system functions as keywords
* @return is specified identifier may be used without quotes
* @throws NullPointerException if s is {@code null}
*/
public
static
boolean
isSimpleIdentifier
(
String
s
,
boolean
functionsAsKeywords
)
{
if
(
s
.
length
()
==
0
)
{
return
false
;
}
char
c
=
s
.
charAt
(
0
);
// lowercase a-z is quoted as well
if
((!
Character
.
isLetter
(
c
)
&&
c
!=
'_'
)
||
Character
.
isLowerCase
(
c
))
{
return
false
;
}
for
(
int
i
=
1
,
length
=
s
.
length
();
i
<
length
;
i
++)
{
c
=
s
.
charAt
(
i
);
if
((!
Character
.
isLetterOrDigit
(
c
)
&&
c
!=
'_'
)
||
Character
.
isLowerCase
(
c
))
{
return
false
;
}
}
return
getSaveTokenType
(
s
,
true
,
functionsAsKeywords
)
==
IDENTIFIER
;
}
/**
* Get the token type.
*
* @param s the token
* @param supportOffsetFetch whether offset / fetch are supported
* @param functionsAsKeywords whether "current data / time" functions are keywords
* @return the token type
*/
public
static
int
getSaveTokenType
(
String
s
,
boolean
supportOffsetFetch
,
boolean
functionsAsKeywords
)
{
switch
(
s
.
charAt
(
0
))
{
case
'A'
:
return
getKeywordOrIdentifier
(
s
,
"ALL"
,
KEYWORD
);
case
'C'
:
if
(
"CHECK"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"CONSTRAINT"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"CROSS"
.
equals
(
s
))
{
return
KEYWORD
;
}
if
(
functionsAsKeywords
)
{
if
(
"CURRENT_DATE"
.
equals
(
s
)
||
"CURRENT_TIME"
.
equals
(
s
)
||
"CURRENT_TIMESTAMP"
.
equals
(
s
))
{
return
KEYWORD
;
}
}
return
IDENTIFIER
;
case
'D'
:
return
getKeywordOrIdentifier
(
s
,
"DISTINCT"
,
KEYWORD
);
case
'E'
:
if
(
"EXCEPT"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"EXISTS"
,
KEYWORD
);
case
'F'
:
if
(
"FROM"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"FOR"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"FOREIGN"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"FULL"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
supportOffsetFetch
&&
"FETCH"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"FALSE"
,
FALSE
);
case
'G'
:
return
getKeywordOrIdentifier
(
s
,
"GROUP"
,
KEYWORD
);
case
'H'
:
return
getKeywordOrIdentifier
(
s
,
"HAVING"
,
KEYWORD
);
case
'I'
:
if
(
"INNER"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"INTERSECT"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"IS"
,
KEYWORD
);
case
'J'
:
return
getKeywordOrIdentifier
(
s
,
"JOIN"
,
KEYWORD
);
case
'L'
:
if
(
"LIMIT"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"LIKE"
,
KEYWORD
);
case
'M'
:
return
getKeywordOrIdentifier
(
s
,
"MINUS"
,
KEYWORD
);
case
'N'
:
if
(
"NOT"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
"NATURAL"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"NULL"
,
NULL
);
case
'O'
:
if
(
"ON"
.
equals
(
s
))
{
return
KEYWORD
;
}
else
if
(
supportOffsetFetch
&&
"OFFSET"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"ORDER"
,
KEYWORD
);
case
'P'
:
return
getKeywordOrIdentifier
(
s
,
"PRIMARY"
,
KEYWORD
);
case
'R'
:
return
getKeywordOrIdentifier
(
s
,
"ROWNUM"
,
ROWNUM
);
case
'S'
:
if
(
"SELECT"
.
equals
(
s
))
{
return
KEYWORD
;
}
if
(
functionsAsKeywords
)
{
if
(
"SYSDATE"
.
equals
(
s
)
||
"SYSTIME"
.
equals
(
s
)
||
"SYSTIMESTAMP"
.
equals
(
s
))
{
return
KEYWORD
;
}
}
return
IDENTIFIER
;
case
'T'
:
if
(
"TRUE"
.
equals
(
s
))
{
return
TRUE
;
}
if
(
functionsAsKeywords
)
{
if
(
"TODAY"
.
equals
(
s
))
{
return
KEYWORD
;
}
}
return
IDENTIFIER
;
case
'U'
:
if
(
"UNIQUE"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"UNION"
,
KEYWORD
);
case
'W'
:
if
(
"WITH"
.
equals
(
s
))
{
return
KEYWORD
;
}
return
getKeywordOrIdentifier
(
s
,
"WHERE"
,
KEYWORD
);
default
:
return
IDENTIFIER
;
}
}
private
static
int
getKeywordOrIdentifier
(
String
s1
,
String
s2
,
int
keywordType
)
{
if
(
s1
.
equals
(
s2
))
{
return
keywordType
;
}
return
IDENTIFIER
;
}
}
h2/src/main/org/h2/value/Value.java
浏览文件 @
9ca0e68e
...
@@ -24,7 +24,6 @@ import org.h2.engine.Mode;
...
@@ -24,7 +24,6 @@ import org.h2.engine.Mode;
import
org.h2.engine.SysProperties
;
import
org.h2.engine.SysProperties
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.store.DataHandler
;
import
org.h2.store.DataHandler
;
import
org.h2.table.Column
;
import
org.h2.tools.SimpleResultSet
;
import
org.h2.tools.SimpleResultSet
;
import
org.h2.util.Bits
;
import
org.h2.util.Bits
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.util.DateTimeUtils
;
...
@@ -604,7 +603,7 @@ public abstract class Value {
...
@@ -604,7 +603,7 @@ public abstract class Value {
* @return the converted value
* @return the converted value
*/
*/
public
final
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
)
{
public
final
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
)
{
return
convertTo
(
targetType
,
precision
,
mode
,
null
);
return
convertTo
(
targetType
,
precision
,
mode
,
null
,
null
);
}
}
/**
/**
...
@@ -615,11 +614,12 @@ public abstract class Value {
...
@@ -615,11 +614,12 @@ public abstract class Value {
* The special constant <code>-1</code> is used to indicate that
* The special constant <code>-1</code> is used to indicate that
* the precision plays no role when converting the value
* the precision plays no role when converting the value
* @param mode the conversion mode
* @param mode the conversion mode
* @param column the column that contains the ENUM datatype enumerators,
* @param column the column (if any), used for to improve the error message if conversion fails
* @param enumerators the ENUM datatype enumerators (if any),
* for dealing with ENUM conversions
* for dealing with ENUM conversions
* @return the converted value
* @return the converted value
*/
*/
public
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
,
Column
column
)
{
public
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
,
Object
column
,
String
[]
enumerators
)
{
// converting NULL is done in ValueNull
// converting NULL is done in ValueNull
// converting BLOB to CLOB and vice versa is done in ValueLob
// converting BLOB to CLOB and vice versa is done in ValueLob
if
(
getType
()
==
targetType
)
{
if
(
getType
()
==
targetType
)
{
...
@@ -938,11 +938,11 @@ public abstract class Value {
...
@@ -938,11 +938,11 @@ public abstract class Value {
case
INT:
case
INT:
case
LONG:
case
LONG:
case
DECIMAL:
case
DECIMAL:
return
ValueEnum
.
get
(
column
.
getEnumerators
()
,
getInt
());
return
ValueEnum
.
get
(
enumerators
,
getInt
());
case
STRING:
case
STRING:
case
STRING_IGNORECASE:
case
STRING_IGNORECASE:
case
STRING_FIXED:
case
STRING_FIXED:
return
ValueEnum
.
get
(
column
.
getEnumerators
()
,
getString
());
return
ValueEnum
.
get
(
enumerators
,
getString
());
default
:
default
:
throw
DbException
.
get
(
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
...
@@ -1154,51 +1154,51 @@ public abstract class Value {
...
@@ -1154,51 +1154,51 @@ public abstract class Value {
return
this
;
return
this
;
}
}
private
static
byte
convertToByte
(
long
x
,
Column
col
)
{
private
static
byte
convertToByte
(
long
x
,
Object
column
)
{
if
(
x
>
Byte
.
MAX_VALUE
||
x
<
Byte
.
MIN_VALUE
)
{
if
(
x
>
Byte
.
MAX_VALUE
||
x
<
Byte
.
MIN_VALUE
)
{
throw
DbException
.
get
(
throw
DbException
.
get
(
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
Long
.
toString
(
x
),
getColumnName
(
col
));
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
Long
.
toString
(
x
),
getColumnName
(
col
umn
));
}
}
return
(
byte
)
x
;
return
(
byte
)
x
;
}
}
private
static
short
convertToShort
(
long
x
,
Column
col
)
{
private
static
short
convertToShort
(
long
x
,
Object
column
)
{
if
(
x
>
Short
.
MAX_VALUE
||
x
<
Short
.
MIN_VALUE
)
{
if
(
x
>
Short
.
MAX_VALUE
||
x
<
Short
.
MIN_VALUE
)
{
throw
DbException
.
get
(
throw
DbException
.
get
(
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
Long
.
toString
(
x
),
getColumnName
(
col
));
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
Long
.
toString
(
x
),
getColumnName
(
col
umn
));
}
}
return
(
short
)
x
;
return
(
short
)
x
;
}
}
private
static
int
convertToInt
(
long
x
,
Column
col
)
{
private
static
int
convertToInt
(
long
x
,
Object
column
)
{
if
(
x
>
Integer
.
MAX_VALUE
||
x
<
Integer
.
MIN_VALUE
)
{
if
(
x
>
Integer
.
MAX_VALUE
||
x
<
Integer
.
MIN_VALUE
)
{
throw
DbException
.
get
(
throw
DbException
.
get
(
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
Long
.
toString
(
x
),
getColumnName
(
col
));
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
Long
.
toString
(
x
),
getColumnName
(
col
umn
));
}
}
return
(
int
)
x
;
return
(
int
)
x
;
}
}
private
static
long
convertToLong
(
double
x
,
Column
col
)
{
private
static
long
convertToLong
(
double
x
,
Object
column
)
{
if
(
x
>
Long
.
MAX_VALUE
||
x
<
Long
.
MIN_VALUE
)
{
if
(
x
>
Long
.
MAX_VALUE
||
x
<
Long
.
MIN_VALUE
)
{
// TODO document that +Infinity, -Infinity throw an exception and
// TODO document that +Infinity, -Infinity throw an exception and
// NaN returns 0
// NaN returns 0
throw
DbException
.
get
(
throw
DbException
.
get
(
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
Double
.
toString
(
x
),
getColumnName
(
col
));
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
Double
.
toString
(
x
),
getColumnName
(
col
umn
));
}
}
return
Math
.
round
(
x
);
return
Math
.
round
(
x
);
}
}
private
static
long
convertToLong
(
BigDecimal
x
,
Column
col
)
{
private
static
long
convertToLong
(
BigDecimal
x
,
Object
column
)
{
if
(
x
.
compareTo
(
MAX_LONG_DECIMAL
)
>
0
||
if
(
x
.
compareTo
(
MAX_LONG_DECIMAL
)
>
0
||
x
.
compareTo
(
Value
.
MIN_LONG_DECIMAL
)
<
0
)
{
x
.
compareTo
(
Value
.
MIN_LONG_DECIMAL
)
<
0
)
{
throw
DbException
.
get
(
throw
DbException
.
get
(
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
x
.
toString
(),
getColumnName
(
col
));
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
x
.
toString
(),
getColumnName
(
col
umn
));
}
}
return
x
.
setScale
(
0
,
BigDecimal
.
ROUND_HALF_UP
).
longValue
();
return
x
.
setScale
(
0
,
BigDecimal
.
ROUND_HALF_UP
).
longValue
();
}
}
private
static
String
getColumnName
(
Column
col
)
{
private
static
String
getColumnName
(
Object
column
)
{
return
col
==
null
?
""
:
col
.
getName
();
return
col
umn
==
null
?
""
:
column
.
toString
();
}
}
/**
/**
...
...
h2/src/main/org/h2/value/ValueGeometry.java
浏览文件 @
9ca0e68e
...
@@ -10,7 +10,6 @@ import java.sql.SQLException;
...
@@ -10,7 +10,6 @@ import java.sql.SQLException;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
org.h2.engine.Mode
;
import
org.h2.engine.Mode
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.table.Column
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
import
com.vividsolutions.jts.geom.CoordinateSequence
;
import
com.vividsolutions.jts.geom.CoordinateSequence
;
import
com.vividsolutions.jts.geom.CoordinateSequenceFilter
;
import
com.vividsolutions.jts.geom.CoordinateSequenceFilter
;
...
@@ -273,11 +272,11 @@ public class ValueGeometry extends Value {
...
@@ -273,11 +272,11 @@ public class ValueGeometry extends Value {
}
}
@Override
@Override
public
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
,
Column
column
)
{
public
Value
convertTo
(
int
targetType
,
int
precision
,
Mode
mode
,
Object
column
,
String
[]
enumerators
)
{
if
(
targetType
==
Value
.
JAVA_OBJECT
)
{
if
(
targetType
==
Value
.
JAVA_OBJECT
)
{
return
this
;
return
this
;
}
}
return
super
.
convertTo
(
targetType
,
precision
,
mode
,
column
);
return
super
.
convertTo
(
targetType
,
precision
,
mode
,
column
,
null
);
}
}
/**
/**
...
...
h2/src/main/org/h2/value/ValueLob.java
浏览文件 @
9ca0e68e
...
@@ -14,6 +14,7 @@ import java.io.Reader;
...
@@ -14,6 +14,7 @@ import java.io.Reader;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.StandardCharsets
;
import
java.sql.PreparedStatement
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Mode
;
import
org.h2.engine.Mode
;
import
org.h2.engine.SysProperties
;
import
org.h2.engine.SysProperties
;
...
@@ -26,7 +27,6 @@ import org.h2.store.FileStoreOutputStream;
...
@@ -26,7 +27,6 @@ import org.h2.store.FileStoreOutputStream;
import
org.h2.store.RangeInputStream
;
import
org.h2.store.RangeInputStream
;
import
org.h2.store.RangeReader
;
import
org.h2.store.RangeReader
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.table.Column
;
import
org.h2.util.IOUtils
;
import
org.h2.util.IOUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.SmallLRUCache
;
import
org.h2.util.SmallLRUCache
;
...
@@ -499,12 +499,13 @@ public class ValueLob extends Value {
...
@@ -499,12 +499,13 @@ public class ValueLob extends Value {
* The special constant <code>-1</code> is used to indicate that
* The special constant <code>-1</code> is used to indicate that
* the precision plays no role when converting the value
* the precision plays no role when converting the value
* @param mode the database mode
* @param mode the database mode
* @param column the column that contains the ENUM datatype enumerators,
* @param column the column (if any), used for to improve the error message if conversion fails
* @param enumerators the ENUM datatype enumerators (if any),
* for dealing with ENUM conversions
* for dealing with ENUM conversions
* @return the converted value
* @return the converted value
*/
*/
@Override
@Override
public
Value
convertTo
(
int
t
,
int
precision
,
Mode
mode
,
Column
column
)
{
public
Value
convertTo
(
int
t
,
int
precision
,
Mode
mode
,
Object
column
,
String
[]
enumerators
)
{
if
(
t
==
type
)
{
if
(
t
==
type
)
{
return
this
;
return
this
;
}
else
if
(
t
==
Value
.
CLOB
)
{
}
else
if
(
t
==
Value
.
CLOB
)
{
...
@@ -514,7 +515,7 @@ public class ValueLob extends Value {
...
@@ -514,7 +515,7 @@ public class ValueLob extends Value {
ValueLob
copy
=
ValueLob
.
createBlob
(
getInputStream
(),
-
1
,
handler
);
ValueLob
copy
=
ValueLob
.
createBlob
(
getInputStream
(),
-
1
,
handler
);
return
copy
;
return
copy
;
}
}
return
super
.
convertTo
(
t
,
precision
,
mode
,
column
);
return
super
.
convertTo
(
t
,
precision
,
mode
,
column
,
null
);
}
}
@Override
@Override
...
...
h2/src/main/org/h2/value/ValueLobDb.java
浏览文件 @
9ca0e68e
...
@@ -14,6 +14,7 @@ import java.io.Reader;
...
@@ -14,6 +14,7 @@ import java.io.Reader;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.StandardCharsets
;
import
java.sql.PreparedStatement
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Mode
;
import
org.h2.engine.Mode
;
import
org.h2.engine.SysProperties
;
import
org.h2.engine.SysProperties
;
...
@@ -26,7 +27,6 @@ import org.h2.store.FileStoreOutputStream;
...
@@ -26,7 +27,6 @@ import org.h2.store.FileStoreOutputStream;
import
org.h2.store.LobStorageFrontend
;
import
org.h2.store.LobStorageFrontend
;
import
org.h2.store.LobStorageInterface
;
import
org.h2.store.LobStorageInterface
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.table.Column
;
import
org.h2.util.IOUtils
;
import
org.h2.util.IOUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
...
@@ -186,11 +186,13 @@ public class ValueLobDb extends Value implements Value.ValueClob,
...
@@ -186,11 +186,13 @@ public class ValueLobDb extends Value implements Value.ValueClob,
* @param t the new type
* @param t the new type
* @param precision the precision
* @param precision the precision
* @param mode the mode
* @param mode the mode
* @param column the column
* @param column the column (if any), used for to improve the error message if conversion fails
* @param enumerators the ENUM datatype enumerators (if any),
* for dealing with ENUM conversions
* @return the converted value
* @return the converted value
*/
*/
@Override
@Override
public
Value
convertTo
(
int
t
,
int
precision
,
Mode
mode
,
Column
column
)
{
public
Value
convertTo
(
int
t
,
int
precision
,
Mode
mode
,
Object
column
,
String
[]
enumerators
)
{
if
(
t
==
type
)
{
if
(
t
==
type
)
{
return
this
;
return
this
;
}
else
if
(
t
==
Value
.
CLOB
)
{
}
else
if
(
t
==
Value
.
CLOB
)
{
...
@@ -210,7 +212,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
...
@@ -210,7 +212,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return
ValueLobDb
.
createSmallLob
(
t
,
small
);
return
ValueLobDb
.
createSmallLob
(
t
,
small
);
}
}
}
}
return
super
.
convertTo
(
t
,
precision
,
mode
,
column
);
return
super
.
convertTo
(
t
,
precision
,
mode
,
column
,
null
);
}
}
@Override
@Override
...
...
h2/src/main/org/h2/value/ValueNull.java
浏览文件 @
9ca0e68e
...
@@ -13,9 +13,9 @@ import java.sql.PreparedStatement;
...
@@ -13,9 +13,9 @@ import java.sql.PreparedStatement;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
java.sql.Time
;
import
java.sql.Time
;
import
java.sql.Timestamp
;
import
java.sql.Timestamp
;
import
org.h2.engine.Mode
;
import
org.h2.engine.Mode
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.table.Column
;
/**
/**
* Implementation of NULL. NULL is not a regular data type.
* Implementation of NULL. NULL is not a regular data type.
...
@@ -133,7 +133,7 @@ public class ValueNull extends Value {
...
@@ -133,7 +133,7 @@ public class ValueNull extends Value {
}
}
@Override
@Override
public
Value
convertTo
(
int
type
,
int
precision
,
Mode
mode
,
Column
column
)
{
public
Value
convertTo
(
int
type
,
int
precision
,
Mode
mode
,
Object
column
,
String
[]
enumerators
)
{
return
this
;
return
this
;
}
}
...
...
h2/src/test/org/h2/test/TestBase.java
浏览文件 @
9ca0e68e
...
@@ -464,6 +464,17 @@ public abstract class TestBase {
...
@@ -464,6 +464,17 @@ public abstract class TestBase {
throw
new
AssertionError
(
string
);
throw
new
AssertionError
(
string
);
}
}
/**
* Log an error message.
*
* @param s the message
*/
public
static
void
logErrorMessage
(
String
s
)
{
System
.
out
.
flush
();
System
.
err
.
println
(
"ERROR: "
+
s
+
"------------------------------"
);
logThrowable
(
s
,
null
);
}
/**
/**
* Log an error message.
* Log an error message.
*
*
...
@@ -478,6 +489,10 @@ public abstract class TestBase {
...
@@ -478,6 +489,10 @@ public abstract class TestBase {
System
.
err
.
println
(
"ERROR: "
+
s
+
" "
+
e
.
toString
()
System
.
err
.
println
(
"ERROR: "
+
s
+
" "
+
e
.
toString
()
+
" ------------------------------"
);
+
" ------------------------------"
);
e
.
printStackTrace
();
e
.
printStackTrace
();
logThrowable
(
null
,
e
);
}
private
static
void
logThrowable
(
String
s
,
Throwable
e
)
{
// synchronize on this class, because file locks are only visible to
// synchronize on this class, because file locks are only visible to
// other JVMs
// other JVMs
synchronized
(
TestBase
.
class
)
{
synchronized
(
TestBase
.
class
)
{
...
@@ -494,9 +509,14 @@ public abstract class TestBase {
...
@@ -494,9 +509,14 @@ public abstract class TestBase {
}
}
// append
// append
FileWriter
fw
=
new
FileWriter
(
"error.txt"
,
true
);
FileWriter
fw
=
new
FileWriter
(
"error.txt"
,
true
);
PrintWriter
pw
=
new
PrintWriter
(
fw
);
if
(
s
!=
null
)
{
e
.
printStackTrace
(
pw
);
fw
.
write
(
s
);
pw
.
close
();
}
if
(
e
!=
null
)
{
PrintWriter
pw
=
new
PrintWriter
(
fw
);
e
.
printStackTrace
(
pw
);
pw
.
close
();
}
fw
.
close
();
fw
.
close
();
// unlock
// unlock
lock
.
release
();
lock
.
release
();
...
...
h2/src/test/org/h2/test/db/AbstractBaseForCommonTableExpressions.java
浏览文件 @
9ca0e68e
...
@@ -17,7 +17,20 @@ import org.h2.test.TestBase;
...
@@ -17,7 +17,20 @@ import org.h2.test.TestBase;
*/
*/
public
abstract
class
AbstractBaseForCommonTableExpressions
extends
TestBase
{
public
abstract
class
AbstractBaseForCommonTableExpressions
extends
TestBase
{
protected
void
testRepeatedQueryWithSetup
(
int
maxRetries
,
String
[]
expectedRowData
,
String
[]
expectedColumnNames
,
/**
* Test a query.
*
* @param maxRetries the number of times the query is run
* @param expectedRowData the expected result data
* @param expectedColumnNames the expected columns of the result
* @param expectedNumberOfRows the expected number of rows
* @param setupSQL the SQL statement used for setup
* @param withQuery the query
* @param closeAndReopenDatabaseConnectionOnIteration whether the connection
* should be re-opened each time
* @param expectedColumnTypes the expected datatypes of the result
*/
void
testRepeatedQueryWithSetup
(
int
maxRetries
,
String
[]
expectedRowData
,
String
[]
expectedColumnNames
,
int
expectedNumberOfRows
,
String
setupSQL
,
String
withQuery
,
int
expectedNumberOfRows
,
String
setupSQL
,
String
withQuery
,
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
int
closeAndReopenDatabaseConnectionOnIteration
,
String
[]
expectedColumnTypes
)
throws
SQLException
{
...
...
h2/src/test/org/h2/test/db/TestOptimizations.java
浏览文件 @
9ca0e68e
...
@@ -68,7 +68,9 @@ public class TestOptimizations extends TestBase {
...
@@ -68,7 +68,9 @@ public class TestOptimizations extends TestBase {
testMultiColumnRangeQuery
();
testMultiColumnRangeQuery
();
testDistinctOptimization
();
testDistinctOptimization
();
testQueryCacheTimestamp
();
testQueryCacheTimestamp
();
testQueryCacheSpeed
();
if
(!
config
.
lazy
)
{
testQueryCacheSpeed
();
}
testQueryCache
(
true
);
testQueryCache
(
true
);
testQueryCache
(
false
);
testQueryCache
(
false
);
testIn
();
testIn
();
...
@@ -800,21 +802,28 @@ public class TestOptimizations extends TestBase {
...
@@ -800,21 +802,28 @@ public class TestOptimizations extends TestBase {
}
}
private
void
testQuerySpeed
(
Statement
stat
,
String
sql
)
throws
SQLException
{
private
void
testQuerySpeed
(
Statement
stat
,
String
sql
)
throws
SQLException
{
stat
.
execute
(
"set OPTIMIZE_REUSE_RESULTS 0"
);
long
totalTime
=
0
;
long
totalTimeOptimized
=
0
;
for
(
int
i
=
0
;
i
<
3
;
i
++)
{
totalTime
+=
measureQuerySpeed
(
stat
,
sql
,
false
);
totalTimeOptimized
+=
measureQuerySpeed
(
stat
,
sql
,
true
);
}
// System.out.println(
// TimeUnit.NANOSECONDS.toMillis(totalTime) + " " +
// TimeUnit.NANOSECONDS.toMillis(totalTimeOptimized));
if
(
totalTimeOptimized
>
totalTime
)
{
fail
(
"not optimized: "
+
TimeUnit
.
NANOSECONDS
.
toMillis
(
totalTime
)
+
" optimized: "
+
TimeUnit
.
NANOSECONDS
.
toMillis
(
totalTimeOptimized
)
+
" sql:"
+
sql
);
}
}
private
long
measureQuerySpeed
(
Statement
stat
,
String
sql
,
boolean
optimized
)
throws
SQLException
{
stat
.
execute
(
"set OPTIMIZE_REUSE_RESULTS "
+
(
optimized
?
"1"
:
"0"
));
stat
.
execute
(
sql
);
stat
.
execute
(
sql
);
long
time
=
System
.
nanoTime
();
long
time
=
System
.
nanoTime
();
stat
.
execute
(
sql
);
stat
.
execute
(
sql
);
time
=
System
.
nanoTime
()
-
time
;
return
System
.
nanoTime
()
-
time
;
stat
.
execute
(
"set OPTIMIZE_REUSE_RESULTS 1"
);
stat
.
execute
(
sql
);
long
time2
=
System
.
nanoTime
();
stat
.
execute
(
sql
);
time2
=
System
.
nanoTime
()
-
time2
;
if
(
time2
>
time
*
2
)
{
fail
(
"not optimized: "
+
TimeUnit
.
NANOSECONDS
.
toMillis
(
time
)
+
" optimized: "
+
TimeUnit
.
NANOSECONDS
.
toMillis
(
time2
)
+
" sql:"
+
sql
);
}
}
}
private
void
testQueryCache
(
boolean
optimize
)
throws
SQLException
{
private
void
testQueryCache
(
boolean
optimize
)
throws
SQLException
{
...
...
h2/src/test/org/h2/test/scripts/TestScript.java
浏览文件 @
9ca0e68e
...
@@ -41,6 +41,7 @@ public class TestScript extends TestBase {
...
@@ -41,6 +41,7 @@ public class TestScript extends TestBase {
private
boolean
reconnectOften
;
private
boolean
reconnectOften
;
private
Connection
conn
;
private
Connection
conn
;
private
Statement
stat
;
private
Statement
stat
;
private
String
fileName
;
private
LineNumberReader
in
;
private
LineNumberReader
in
;
private
int
outputLineNo
;
private
int
outputLineNo
;
private
PrintStream
out
;
private
PrintStream
out
;
...
@@ -156,6 +157,7 @@ public class TestScript extends TestBase {
...
@@ -156,6 +157,7 @@ public class TestScript extends TestBase {
// we processed.
// we processed.
conn
=
null
;
conn
=
null
;
stat
=
null
;
stat
=
null
;
fileName
=
null
;
in
=
null
;
in
=
null
;
outputLineNo
=
0
;
outputLineNo
=
0
;
out
=
null
;
out
=
null
;
...
@@ -173,7 +175,7 @@ public class TestScript extends TestBase {
...
@@ -173,7 +175,7 @@ public class TestScript extends TestBase {
conn
.
close
();
conn
.
close
();
out
.
close
();
out
.
close
();
if
(
errors
.
length
()
>
0
)
{
if
(
errors
.
length
()
>
0
)
{
throw
new
Exception
(
"errors
:\n"
+
errors
.
toString
()
);
throw
new
Exception
(
"errors
in "
+
scriptFileName
+
" found"
);
}
}
// new File(outFile).delete();
// new File(outFile).delete();
}
}
...
@@ -201,6 +203,7 @@ public class TestScript extends TestBase {
...
@@ -201,6 +203,7 @@ public class TestScript extends TestBase {
if
(
is
==
null
)
{
if
(
is
==
null
)
{
throw
new
IOException
(
"could not find "
+
inFile
);
throw
new
IOException
(
"could not find "
+
inFile
);
}
}
fileName
=
inFile
;
in
=
new
LineNumberReader
(
new
InputStreamReader
(
is
,
"Cp1252"
));
in
=
new
LineNumberReader
(
new
InputStreamReader
(
is
,
"Cp1252"
));
StringBuilder
buff
=
new
StringBuilder
();
StringBuilder
buff
=
new
StringBuilder
();
while
(
true
)
{
while
(
true
)
{
...
@@ -436,17 +439,14 @@ public class TestScript extends TestBase {
...
@@ -436,17 +439,14 @@ public class TestScript extends TestBase {
if
(
reconnectOften
&&
sql
.
toUpperCase
().
startsWith
(
"EXPLAIN"
))
{
if
(
reconnectOften
&&
sql
.
toUpperCase
().
startsWith
(
"EXPLAIN"
))
{
return
;
return
;
}
}
errors
.
append
(
"line: "
);
errors
.
append
(
fileName
).
append
(
'\n'
);
errors
.
append
(
outputLineNo
);
errors
.
append
(
"line: "
).
append
(
outputLineNo
).
append
(
'\n'
);
errors
.
append
(
"\n"
+
"exp: "
);
errors
.
append
(
"exp: "
).
append
(
compare
).
append
(
'\n'
);
errors
.
append
(
compare
);
errors
.
append
(
"got: "
).
append
(
s
).
append
(
'\n'
);
errors
.
append
(
"\n"
+
"got: "
);
errors
.
append
(
s
);
errors
.
append
(
"\n"
);
if
(
e
!=
null
)
{
if
(
e
!=
null
)
{
TestBase
.
logError
(
"script"
,
e
);
TestBase
.
logError
(
"script"
,
e
);
}
}
TestBase
.
logError
(
errors
.
toString
(),
null
);
TestBase
.
logError
Message
(
errors
.
toString
()
);
if
(
failFast
)
{
if
(
failFast
)
{
conn
.
close
();
conn
.
close
();
System
.
exit
(
1
);
System
.
exit
(
1
);
...
...
h2/src/test/org/h2/test/scripts/functions/timeanddate/dateadd.sql
浏览文件 @
9ca0e68e
...
@@ -81,7 +81,7 @@ select d + t, t + d - t x from test;
...
@@ -81,7 +81,7 @@ select d + t, t + d - t x from test;
select
1
+
d
+
1
,
d
-
1
,
2
+
ts
+
2
,
ts
-
2
from
test
;
select
1
+
d
+
1
,
d
-
1
,
2
+
ts
+
2
,
ts
-
2
from
test
;
>
DATEADD
(
'DAY'
,
1
,
DATEADD
(
'DAY'
,
1
,
D
))
DATEADD
(
'DAY'
,
-
1
,
D
)
DATEADD
(
'DAY'
,
2
,
DATEADD
(
'DAY'
,
2
,
TS
))
DATEADD
(
'DAY'
,
-
2
,
TS
)
>
DATEADD
(
'DAY'
,
1
,
DATEADD
(
'DAY'
,
1
,
D
))
DATEADD
(
'DAY'
,
-
1
,
D
)
DATEADD
(
'DAY'
,
2
,
DATEADD
(
'DAY'
,
2
,
TS
))
DATEADD
(
'DAY'
,
-
2
,
TS
)
>
--------------------------------------- --------------------- ---------------------------------------- ----------------------
>
--------------------------------------- --------------------- ---------------------------------------- ----------------------
>
2001
-
01
-
03
00
:
00
:
00
.
0
2000
-
12
-
31
00
:
00
:
00
.
0
2010
-
01
-
05
00
:
00
:
00
.
0
2009
-
12
-
30
00
:
00
:
00
.
0
>
2001
-
01
-
03
2000
-
12
-
31
2010
-
01
-
05
00
:
00
:
00
.
0
2009
-
12
-
30
00
:
00
:
00
.
0
>
rows
:
1
>
rows
:
1
select
1
+
d
+
t
+
1
from
test
;
select
1
+
d
+
t
+
1
from
test
;
...
@@ -104,3 +104,36 @@ call dateadd('MS', 1, TIMESTAMP '2001-02-03 04:05:06.789001');
...
@@ -104,3 +104,36 @@ call dateadd('MS', 1, TIMESTAMP '2001-02-03 04:05:06.789001');
>
--------------------------------------
>
--------------------------------------
>
2001
-
02
-
03
04
:
05
:
06
.
790001
>
2001
-
02
-
03
04
:
05
:
06
.
790001
>
rows
:
1
>
rows
:
1
SELECT
DATEADD
(
'HOUR'
,
1
,
DATE
'2010-01-20'
);
>
TIMESTAMP
'2010-01-20 01:00:00.0'
>
---------------------------------
>
2010
-
01
-
20
01
:
00
:
00
.
0
>
rows
:
1
SELECT
DATEADD
(
'MINUTE'
,
30
,
TIME
'12:30:55'
);
>
TIME
'13:00:55'
>
---------------
>
13
:
00
:
55
>
rows
:
1
SELECT
DATEADD
(
'DAY'
,
1
,
TIME
'12:30:55'
);
>
exception
SELECT
DATEADD
(
'QUARTER'
,
1
,
DATE
'2010-11-16'
);
>
DATE
'2011-02-16'
>
-----------------
>
2011
-
02
-
16
>
rows
:
1
SELECT
DATEADD
(
'DAY'
,
10
,
TIMESTAMP
WITH
TIME
ZONE
'2000-01-05 15:00:30.123456789-10'
);
>
TIMESTAMP
WITH
TIME
ZONE
'2000-01-15 15:00:30.123456789-10'
>
-----------------------------------------------------------
>
2000
-
01
-
15
15
:
00
:
30
.
123456789
-
10
>
rows
:
1
SELECT
TIMESTAMPADD
(
'DAY'
,
10
,
TIMESTAMP
'2000-01-05 15:00:30.123456789'
);
>
TIMESTAMP
'2000-01-15 15:00:30.123456789'
>
-----------------------------------------
>
2000
-
01
-
15
15
:
00
:
30
.
123456789
>
rows
:
1
h2/src/test/org/h2/test/scripts/functions/timeanddate/datediff.sql
浏览文件 @
9ca0e68e
...
@@ -194,3 +194,34 @@ SELECT DATEDIFF('WEEK', DATE '1969-12-28', DATE '1969-12-29'), DATEDIFF('ISO_WEE
...
@@ -194,3 +194,34 @@ SELECT DATEDIFF('WEEK', DATE '1969-12-28', DATE '1969-12-29'), DATEDIFF('ISO_WEE
>
-
-
>
-
-
>
0
1
>
0
1
>
rows
:
1
>
rows
:
1
SELECT
DATEDIFF
(
'QUARTER'
,
DATE
'2009-12-30'
,
DATE
'2009-12-31'
);
>
0
>
-
>
0
>
rows
:
1
SELECT
DATEDIFF
(
'QUARTER'
,
DATE
'2010-01-01'
,
DATE
'2009-12-31'
);
>
-
1
>
--
>
-
1
>
rows
:
1
SELECT
DATEDIFF
(
'QUARTER'
,
DATE
'2010-01-01'
,
DATE
'2010-01-02'
);
>
0
>
-
>
0
>
rows
:
1
SELECT
DATEDIFF
(
'QUARTER'
,
DATE
'2010-01-01'
,
DATE
'2010-03-31'
);
>
0
>
-
>
0
>
rows
:
1
SELECT
DATEDIFF
(
'QUARTER'
,
DATE
'-1000-01-01'
,
DATE
'2000-01-01'
);
>
12000
>
-----
>
12000
>
rows
:
1
h2/src/test/org/h2/test/scripts/testScript.sql
浏览文件 @
9ca0e68e
...
@@ -7586,9 +7586,9 @@ SELECT * FROM TEST;
...
@@ -7586,9 +7586,9 @@ SELECT * FROM TEST;
SELECT
XD
+
1
,
XD
-
1
,
XD
-
XD
FROM
TEST
;
SELECT
XD
+
1
,
XD
-
1
,
XD
-
XD
FROM
TEST
;
>
DATEADD
(
'DAY'
,
1
,
XD
)
DATEADD
(
'DAY'
,
-
1
,
XD
)
DATEDIFF
(
'DAY'
,
XD
,
XD
)
>
DATEADD
(
'DAY'
,
1
,
XD
)
DATEADD
(
'DAY'
,
-
1
,
XD
)
DATEDIFF
(
'DAY'
,
XD
,
XD
)
>
--------------------- ---------------------- -----------------------
>
--------------------- ---------------------- -----------------------
>
0001
-
02
-
04
00
:
00
:
00
.
0
0001
-
02
-
02
00
:
00
:
00
.
0
0
>
0001
-
02
-
04
0001
-
02
-
02
0
>
0004
-
05
-
07
00
:
00
:
00
.
0
0004
-
05
-
05
00
:
00
:
00
.
0
0
>
0004
-
05
-
07
0004
-
05
-
05
0
>
2000
-
01
-
01
00
:
00
:
00
.
0
1999
-
12
-
30
00
:
00
:
00
.
0
0
>
2000
-
01
-
01
1999
-
12
-
30
0
>
null
null
null
>
null
null
null
>
rows
:
4
>
rows
:
4
...
...
h2/src/test/org/h2/test/unit/TestDateTimeUtils.java
浏览文件 @
9ca0e68e
...
@@ -11,6 +11,8 @@ import java.util.GregorianCalendar;
...
@@ -11,6 +11,8 @@ import java.util.GregorianCalendar;
import
org.h2.test.TestBase
;
import
org.h2.test.TestBase
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.util.DateTimeUtils
;
import
static
org
.
h2
.
util
.
DateTimeUtils
.
dateValue
;
/**
/**
* Unit tests for the DateTimeUtils class
* Unit tests for the DateTimeUtils class
*/
*/
...
@@ -30,6 +32,7 @@ public class TestDateTimeUtils extends TestBase {
...
@@ -30,6 +32,7 @@ public class TestDateTimeUtils extends TestBase {
testParseTimeNanosDB2Format
();
testParseTimeNanosDB2Format
();
testDayOfWeek
();
testDayOfWeek
();
testWeekOfYear
();
testWeekOfYear
();
testDateValueFromDenormalizedDate
();
}
}
private
void
testParseTimeNanosDB2Format
()
{
private
void
testParseTimeNanosDB2Format
()
{
...
@@ -45,7 +48,7 @@ public class TestDateTimeUtils extends TestBase {
...
@@ -45,7 +48,7 @@ public class TestDateTimeUtils extends TestBase {
* {@link DateTimeUtils#getIsoDayOfWeek(long)}.
* {@link DateTimeUtils#getIsoDayOfWeek(long)}.
*/
*/
private
void
testDayOfWeek
()
{
private
void
testDayOfWeek
()
{
GregorianCalendar
gc
=
DateTimeUtils
.
createGregorianCalendar
();
GregorianCalendar
gc
=
DateTimeUtils
.
createGregorianCalendar
(
DateTimeUtils
.
UTC
);
for
(
int
i
=
-
1_000_000
;
i
<=
1_000_000
;
i
++)
{
for
(
int
i
=
-
1_000_000
;
i
<=
1_000_000
;
i
++)
{
gc
.
clear
();
gc
.
clear
();
gc
.
setTimeInMillis
(
i
*
86400000L
);
gc
.
setTimeInMillis
(
i
*
86400000L
);
...
@@ -53,7 +56,7 @@ public class TestDateTimeUtils extends TestBase {
...
@@ -53,7 +56,7 @@ public class TestDateTimeUtils extends TestBase {
if
(
gc
.
get
(
Calendar
.
ERA
)
==
GregorianCalendar
.
BC
)
{
if
(
gc
.
get
(
Calendar
.
ERA
)
==
GregorianCalendar
.
BC
)
{
year
=
1
-
year
;
year
=
1
-
year
;
}
}
long
expectedDateValue
=
DateTimeUtils
.
dateValue
(
year
,
gc
.
get
(
Calendar
.
MONTH
)
+
1
,
long
expectedDateValue
=
dateValue
(
year
,
gc
.
get
(
Calendar
.
MONTH
)
+
1
,
gc
.
get
(
Calendar
.
DAY_OF_MONTH
));
gc
.
get
(
Calendar
.
DAY_OF_MONTH
));
long
dateValue
=
DateTimeUtils
.
dateValueFromAbsoluteDay
(
i
);
long
dateValue
=
DateTimeUtils
.
dateValueFromAbsoluteDay
(
i
);
assertEquals
(
expectedDateValue
,
dateValue
);
assertEquals
(
expectedDateValue
,
dateValue
);
...
@@ -63,7 +66,8 @@ public class TestDateTimeUtils extends TestBase {
...
@@ -63,7 +66,8 @@ public class TestDateTimeUtils extends TestBase {
int
isoDow
=
(
dow
+
5
)
%
7
+
1
;
int
isoDow
=
(
dow
+
5
)
%
7
+
1
;
assertEquals
(
isoDow
,
DateTimeUtils
.
getIsoDayOfWeek
(
dateValue
));
assertEquals
(
isoDow
,
DateTimeUtils
.
getIsoDayOfWeek
(
dateValue
));
assertEquals
(
gc
.
get
(
Calendar
.
WEEK_OF_YEAR
),
assertEquals
(
gc
.
get
(
Calendar
.
WEEK_OF_YEAR
),
DateTimeUtils
.
getWeekOfYear
(
dateValue
,
gc
.
getFirstDayOfWeek
()
-
1
,
gc
.
getMinimalDaysInFirstWeek
()));
DateTimeUtils
.
getWeekOfYear
(
dateValue
,
gc
.
getFirstDayOfWeek
()
-
1
,
gc
.
getMinimalDaysInFirstWeek
()));
}
}
}
}
...
@@ -83,11 +87,23 @@ public class TestDateTimeUtils extends TestBase {
...
@@ -83,11 +87,23 @@ public class TestDateTimeUtils extends TestBase {
gc
.
clear
();
gc
.
clear
();
gc
.
setTimeInMillis
(
i
*
86400000L
);
gc
.
setTimeInMillis
(
i
*
86400000L
);
assertEquals
(
gc
.
get
(
Calendar
.
DAY_OF_YEAR
),
DateTimeUtils
.
getDayOfYear
(
dateValue
));
assertEquals
(
gc
.
get
(
Calendar
.
DAY_OF_YEAR
),
DateTimeUtils
.
getDayOfYear
(
dateValue
));
assertEquals
(
gc
.
get
(
Calendar
.
WEEK_OF_YEAR
),
DateTimeUtils
.
getWeekOfYear
(
dateValue
,
firstDay
-
1
,
minimalDays
));
assertEquals
(
gc
.
get
(
Calendar
.
WEEK_OF_YEAR
),
DateTimeUtils
.
getWeekOfYear
(
dateValue
,
firstDay
-
1
,
minimalDays
));
assertEquals
(
gc
.
getWeekYear
(),
DateTimeUtils
.
getWeekYear
(
dateValue
,
firstDay
-
1
,
minimalDays
));
assertEquals
(
gc
.
getWeekYear
(),
DateTimeUtils
.
getWeekYear
(
dateValue
,
firstDay
-
1
,
minimalDays
));
}
}
}
}
}
}
}
}
/**
* Test for {@link DateTimeUtils#dateValueFromDenormalizedDate(long, long, int)}.
*/
private
void
testDateValueFromDenormalizedDate
()
{
assertEquals
(
dateValue
(
2017
,
1
,
1
),
DateTimeUtils
.
dateValueFromDenormalizedDate
(
2018
,
-
11
,
0
));
assertEquals
(
dateValue
(
2001
,
2
,
28
),
DateTimeUtils
.
dateValueFromDenormalizedDate
(
2000
,
14
,
29
));
assertEquals
(
dateValue
(
1999
,
8
,
1
),
DateTimeUtils
.
dateValueFromDenormalizedDate
(
2000
,
-
4
,
-
100
));
assertEquals
(
dateValue
(
2100
,
12
,
31
),
DateTimeUtils
.
dateValueFromDenormalizedDate
(
2100
,
12
,
2000
));
assertEquals
(
dateValue
(-
100
,
2
,
29
),
DateTimeUtils
.
dateValueFromDenormalizedDate
(-
100
,
2
,
30
));
}
}
}
h2/src/tools/org/h2/build/Build.java
浏览文件 @
9ca0e68e
...
@@ -610,8 +610,8 @@ public class Build extends BuildBase {
...
@@ -610,8 +610,8 @@ public class Build extends BuildBase {
exclude
(
"*.DS_Store"
);
exclude
(
"*.DS_Store"
);
files
=
excludeTestMetaInfFiles
(
files
);
files
=
excludeTestMetaInfFiles
(
files
);
long
kb
=
jar
(
"bin/h2-client"
+
getJarSuffix
(),
files
,
"temp"
);
long
kb
=
jar
(
"bin/h2-client"
+
getJarSuffix
(),
files
,
"temp"
);
if
(
kb
<
350
||
kb
>
45
0
)
{
if
(
kb
<
400
||
kb
>
50
0
)
{
throw
new
RuntimeException
(
"Expected file size
350 - 45
0 KB, got: "
+
kb
);
throw
new
RuntimeException
(
"Expected file size
400 - 50
0 KB, got: "
+
kb
);
}
}
}
}
...
...
h2/src/tools/org/h2/build/doc/dictionary.txt
浏览文件 @
9ca0e68e
...
@@ -763,3 +763,6 @@ assorted reimplemented hangups confirmation predefined
...
@@ -763,3 +763,6 @@ assorted reimplemented hangups confirmation predefined
mdy destfile hclf forbids spellchecking selfdestruct expects accident jacocoagent cli historic mitigate
mdy destfile hclf forbids spellchecking selfdestruct expects accident jacocoagent cli historic mitigate
jacoco xdata invokes sourcefiles classfiles duplication crypto stacktraces prt directions handled overly asm hardcoded
jacoco xdata invokes sourcefiles classfiles duplication crypto stacktraces prt directions handled overly asm hardcoded
interpolated thead
interpolated thead
die weekdiff osx subprocess dow proleptic
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论