Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
158b3d44
提交
158b3d44
authored
4月 07, 2008
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
--no commit message
--no commit message
上级
26414c8e
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
40 个修改的文件
包含
862 行增加
和
337 行删除
+862
-337
tutorial.html
h2/src/docsrc/html/tutorial.html
+8
-6
classes.html
h2/src/docsrc/javadoc/classes.html
+5
-5
index.html
h2/src/docsrc/javadoc/index.html
+1
-1
Driver.java
h2/src/main/org/h2/Driver.java
+1
-3
Bnf.java
h2/src/main/org/h2/bnf/Bnf.java
+2
-1
Rule.java
h2/src/main/org/h2/bnf/Rule.java
+5
-7
RuleElement.java
h2/src/main/org/h2/bnf/RuleElement.java
+23
-12
RuleFixed.java
h2/src/main/org/h2/bnf/RuleFixed.java
+41
-11
RuleList.java
h2/src/main/org/h2/bnf/RuleList.java
+39
-18
RuleOptional.java
h2/src/main/org/h2/bnf/RuleOptional.java
+13
-9
RuleRepeat.java
h2/src/main/org/h2/bnf/RuleRepeat.java
+18
-14
Sentence.java
h2/src/main/org/h2/bnf/Sentence.java
+51
-0
CommandContainer.java
h2/src/main/org/h2/command/CommandContainer.java
+6
-4
Parser.java
h2/src/main/org/h2/command/Parser.java
+17
-18
Prepared.java
h2/src/main/org/h2/command/Prepared.java
+8
-6
Query.java
h2/src/main/org/h2/command/dml/Query.java
+1
-1
Set.java
h2/src/main/org/h2/command/dml/Set.java
+1
-1
Database.java
h2/src/main/org/h2/engine/Database.java
+11
-3
Engine.java
h2/src/main/org/h2/engine/Engine.java
+53
-38
Session.java
h2/src/main/org/h2/engine/Session.java
+11
-1
SequenceValue.java
h2/src/main/org/h2/expression/SequenceValue.java
+1
-1
JdbcConnectionPool.java
h2/src/main/org/h2/jdbcx/JdbcConnectionPool.java
+119
-66
JdbcDataSource.java
h2/src/main/org/h2/jdbcx/JdbcDataSource.java
+2
-2
Trace.java
h2/src/main/org/h2/message/Trace.java
+22
-3
help.csv
h2/src/main/org/h2/res/help.csv
+4
-3
LocalResult.java
h2/src/main/org/h2/result/LocalResult.java
+10
-0
Sequence.java
h2/src/main/org/h2/schema/Sequence.java
+17
-9
DbContextRule.java
h2/src/main/org/h2/server/web/DbContextRule.java
+133
-37
WebSession.java
h2/src/main/org/h2/server/web/WebSession.java
+3
-0
FileSystemMemory.java
h2/src/main/org/h2/store/fs/FileSystemMemory.java
+21
-4
Column.java
h2/src/main/org/h2/table/Column.java
+1
-1
ConvertTraceFile.java
h2/src/main/org/h2/tools/ConvertTraceFile.java
+76
-3
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+41
-41
TestSequence.java
h2/src/test/org/h2/test/db/TestSequence.java
+13
-0
TestCancel.java
h2/src/test/org/h2/test/jdbc/TestCancel.java
+17
-0
TestConnectionPool.java
h2/src/test/org/h2/test/jdbcx/TestConnectionPool.java
+7
-5
TestWeb.java
h2/src/test/org/h2/test/server/TestWeb.java
+8
-0
todo.txt
h2/src/test/org/h2/test/todo/todo.txt
+33
-0
TestFileSystem.java
h2/src/test/org/h2/test/unit/TestFileSystem.java
+15
-0
Doclet.java
h2/src/tools/org/h2/build/doclet/Doclet.java
+4
-3
没有找到文件。
h2/src/docsrc/html/tutorial.html
浏览文件 @
158b3d44
...
...
@@ -588,28 +588,30 @@ Example permission tags:
<p>
For many databases, opening a connection is slow, and it is a good idea to use a connection pool
to re-use connections. For H2 however opening a connection usually is fast if the database is already
open. Using a connection pool
manager
for H2 actually slows down the process a bit, except if
open. Using a connection pool for H2 actually slows down the process a bit, except if
file encryption is used (in this case opening a connection is about half as fast as using
a connection pool). A simple connection pool
manager
is included in H2. It is based on the
a connection pool). A simple connection pool is included in H2. It is based on the
<a
href=
"http://www.source-code.biz/snippets/java/8.htm"
>
Mini Connection Pool Manager
</a>
from Christian d'Heureuse. There are other, more complex connection pools available, for example
<a
href=
"http://jakarta.apache.org/commons/dbcp/"
>
DBCP
</a>
. The build-in
connection pool
manager
is used as follows:
connection pool is used as follows:
<pre>
// init
import org.h2.jdbcx.*;
...
JdbcDataSource ds = new JdbcDataSource();
ds.setURL("jdbc:h2:~/test");
ds.setUser("sa");
ds.setPassword("sa");
JdbcConnectionPool
Manager man = new JdbcConnectionPoolManager
(ds);
JdbcConnectionPool
cp = JdbcConnectionPool.create
(ds);
// use
Connection conn =
man
.getConnection();
Connection conn =
cp
.getConnection();
...
conn.close();
// dispose
man
.dispose();
cp
.dispose();
</pre>
</p>
...
...
h2/src/docsrc/javadoc/classes.html
浏览文件 @
158b3d44
...
...
@@ -37,11 +37,11 @@ org.h2.jdbc<br />
<a
href=
"org/h2/jdbc/JdbcSQLException.html"
target=
"javadoc"
>
SQLException
</a><br
/>
<a
href=
"org/h2/jdbc/JdbcStatement.html"
target=
"javadoc"
>
Statement
</a><br
/>
org.h2.jdbcx
<br
/>
<a
href=
"org/h2/jdbcx/JdbcConnectionPool
Manager.html"
target=
"javadoc"
>
ConnectionPoolManager
</a><br
/>
<a
href=
"org/h2/jdbcx/JdbcDataSource.html"
target=
"javadoc"
>
DataSource
</a><br
/>
<a
href=
"org/h2/jdbcx/JdbcDataSourceFactory.html"
target=
"javadoc"
>
DataSourceFactory
</a><br
/>
<a
href=
"org/h2/jdbcx/JdbcXAConnection.html"
target=
"javadoc"
>
XAConnection
</a><br
/>
<a
href=
"org/h2/jdbcx/JdbcXid.html"
target=
"javadoc"
>
Xid
</a><br
/>
<a
href=
"org/h2/jdbcx/JdbcConnectionPool
.html"
target=
"javadoc"
>
JdbcConnectionPool
</a><br
/>
<a
href=
"org/h2/jdbcx/JdbcDataSource.html"
target=
"javadoc"
>
Jdbc
DataSource
</a><br
/>
<a
href=
"org/h2/jdbcx/JdbcDataSourceFactory.html"
target=
"javadoc"
>
Jdbc
DataSourceFactory
</a><br
/>
<a
href=
"org/h2/jdbcx/JdbcXAConnection.html"
target=
"javadoc"
>
Jdbc
XAConnection
</a><br
/>
<a
href=
"org/h2/jdbcx/JdbcXid.html"
target=
"javadoc"
>
Jdbc
Xid
</a><br
/>
<br
/>
<b>
Tools
</b><br
/>
...
...
h2/src/docsrc/javadoc/index.html
浏览文件 @
158b3d44
...
...
@@ -9,7 +9,7 @@ Initial Developer: H2 Group
<title>
H2 Documentation
</title>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"stylesheet.css"
/>
</head>
<frameset
cols=
"1
94
,*"
rows=
"*"
frameborder=
"2"
framespacing=
"4"
border=
"4"
>
<frameset
cols=
"1
88
,*"
rows=
"*"
frameborder=
"2"
framespacing=
"4"
border=
"4"
>
<frame
frameborder=
"0"
marginheight=
"0"
marginwidth=
"0"
src=
"classes.html"
name=
"classes"
/>
<frame
frameborder=
"0"
marginheight=
"0"
marginwidth=
"0"
src=
"overview.html"
name=
"javadoc"
/>
</frameset>
...
...
h2/src/main/org/h2/Driver.java
浏览文件 @
158b3d44
...
...
@@ -53,9 +53,7 @@ public class Driver implements java.sql.Driver {
if
(!
acceptsURL
(
url
))
{
return
null
;
}
synchronized
(
this
)
{
return
new
JdbcConnection
(
url
,
info
);
}
return
new
JdbcConnection
(
url
,
info
);
}
catch
(
Throwable
e
)
{
throw
Message
.
convert
(
e
);
}
...
...
h2/src/main/org/h2/bnf/Bnf.java
浏览文件 @
158b3d44
...
...
@@ -299,7 +299,8 @@ public class Bnf {
continue
;
}
sentence
.
max
=
System
.
currentTimeMillis
()
+
MAX_PARSE_TIME
;
head
.
getRule
().
addNextTokenList
(
query
,
sentence
);
sentence
.
setQuery
(
query
);
head
.
getRule
().
addNextTokenList
(
sentence
);
}
return
next
;
}
...
...
h2/src/main/org/h2/bnf/Rule.java
浏览文件 @
158b3d44
...
...
@@ -46,21 +46,19 @@ public interface Rule {
* Add the next possible token for a query.
* Used for autocomplete support.
*
* @param query the query
* @param sentence the sentence context
*/
void
addNextTokenList
(
S
tring
query
,
S
entence
sentence
);
void
addNextTokenList
(
Sentence
sentence
);
/**
* Remove a token from a sentence. Used for autocomplete support.
* If there was a match, the query in the sentence is updated
* (the matched token is removed).
*
* @param query
* the query
* @param sentence
* the sentence context
* @return null if not a match or a partial match, query.substring... if a
* full match
* @return false if not a match or a partial match, true if a full match
*/
String
matchRemove
(
String
query
,
Sentence
sentence
);
boolean
matchRemove
(
Sentence
sentence
);
}
h2/src/main/org/h2/bnf/RuleElement.java
浏览文件 @
158b3d44
...
...
@@ -29,6 +29,10 @@ public class RuleElement implements Rule {
topic
=
StringUtils
.
toLowerEnglish
(
topic
);
this
.
type
=
topic
.
startsWith
(
"function"
)
?
Sentence
.
FUNCTION
:
Sentence
.
KEYWORD
;
}
public
String
toString
()
{
return
name
;
}
RuleElement
merge
(
RuleElement
rule
)
{
return
new
RuleElement
(
name
+
" "
+
rule
.
name
,
topic
);
...
...
@@ -72,41 +76,48 @@ public class RuleElement implements Rule {
}
}
public
String
matchRemove
(
String
query
,
Sentence
sentence
)
{
public
boolean
matchRemove
(
Sentence
sentence
)
{
if
(
sentence
.
stop
())
{
return
null
;
return
false
;
}
String
query
=
sentence
.
query
;
if
(
query
.
length
()
==
0
)
{
return
null
;
return
false
;
}
if
(
keyword
)
{
String
up
=
StringUtils
.
toUpperEnglish
(
query
)
;
String
up
=
sentence
.
queryUpper
;
if
(
up
.
startsWith
(
name
))
{
query
=
query
.
substring
(
name
.
length
());
while
(!
"_"
.
equals
(
name
)
&&
query
.
length
()
>
0
&&
Character
.
isWhitespace
(
query
.
charAt
(
0
)))
{
query
=
query
.
substring
(
1
);
}
return
query
;
sentence
.
setQuery
(
query
);
return
true
;
}
return
null
;
return
false
;
}
else
{
query
=
link
.
matchRemove
(
query
,
sentence
);
if
(
query
!=
null
&&
name
!=
null
&&
!
name
.
startsWith
(
"@"
)
&&
(
link
.
name
()
==
null
||
!
link
.
name
().
startsWith
(
"@"
)))
{
if
(!
link
.
matchRemove
(
sentence
))
{
return
false
;
}
if
(
name
!=
null
&&
!
name
.
startsWith
(
"@"
)
&&
(
link
.
name
()
==
null
||
!
link
.
name
().
startsWith
(
"@"
)))
{
query
=
sentence
.
query
;
while
(
query
.
length
()
>
0
&&
Character
.
isWhitespace
(
query
.
charAt
(
0
)))
{
query
=
query
.
substring
(
1
);
}
sentence
.
setQuery
(
query
);
}
return
query
;
return
true
;
}
}
public
void
addNextTokenList
(
S
tring
query
,
S
entence
sentence
)
{
public
void
addNextTokenList
(
Sentence
sentence
)
{
if
(
sentence
.
stop
())
{
return
;
}
if
(
keyword
)
{
String
query
=
sentence
.
query
;
String
q
=
query
.
trim
();
String
up
=
StringUtils
.
toUpperEnglish
(
q
);
String
up
=
sentence
.
queryUpper
.
trim
(
);
if
(
q
.
length
()
==
0
||
name
.
startsWith
(
up
))
{
if
(
q
.
length
()
<
name
.
length
())
{
sentence
.
add
(
name
,
name
.
substring
(
q
.
length
()),
type
);
...
...
@@ -114,7 +125,7 @@ public class RuleElement implements Rule {
}
return
;
}
link
.
addNextTokenList
(
query
,
sentence
);
link
.
addNextTokenList
(
sentence
);
}
boolean
isKeyword
()
{
...
...
h2/src/main/org/h2/bnf/RuleFixed.java
浏览文件 @
158b3d44
...
...
@@ -8,8 +8,6 @@ package org.h2.bnf;
import
java.util.HashMap
;
import
java.util.Random
;
import
org.h2.util.StringUtils
;
/**
* Represents a hard coded terminal rule in a BNF object.
*/
...
...
@@ -27,6 +25,36 @@ public class RuleFixed implements Rule {
RuleFixed
(
int
type
)
{
this
.
type
=
type
;
}
public
String
toString
()
{
switch
(
type
)
{
case
YMD:
return
"2000-01-01"
;
case
HMS:
return
"12:00"
;
case
NANOS:
return
"0"
;
case
ANY_UNTIL_EOL:
case
ANY_EXCEPT_SINGLE_QUOTE:
case
ANY_EXCEPT_DOUBLE_QUOTE:
case
ANY_WORD:
case
ANY_UNTIL_END:
{
return
"XYZ"
;
}
case
HEX_START:
return
"0x"
;
case
CONCAT:
return
"||"
;
case
AZ_UNDERLINE:
return
"A"
;
case
AF:
return
"F"
;
case
DIGIT:
return
"0"
;
default
:
throw
new
Error
(
"type="
+
type
);
}
}
public
String
random
(
Bnf
config
,
int
level
)
{
Random
r
=
config
.
getRandom
();
...
...
@@ -75,12 +103,13 @@ public class RuleFixed implements Rule {
public
void
setLinks
(
HashMap
ruleMap
)
{
}
public
String
matchRemove
(
String
query
,
Sentence
sentence
)
{
public
boolean
matchRemove
(
Sentence
sentence
)
{
if
(
sentence
.
stop
())
{
return
null
;
return
false
;
}
String
query
=
sentence
.
query
;
if
(
query
.
length
()
==
0
)
{
return
null
;
return
false
;
}
String
s
=
query
;
switch
(
type
)
{
...
...
@@ -139,9 +168,9 @@ public class RuleFixed implements Rule {
}
break
;
case
HEX_START:
if
(
StringUtils
.
toUpperEnglish
(
s
).
startsWith
(
"0X
"
))
{
if
(
s
.
startsWith
(
"0X"
)
||
s
.
startsWith
(
"0x
"
))
{
s
=
s
.
substring
(
2
);
}
else
if
(
StringUtils
.
toUpperEnglish
(
s
)
.
startsWith
(
"0"
))
{
}
else
if
(
s
.
startsWith
(
"0"
))
{
s
=
s
.
substring
(
1
);
}
break
;
...
...
@@ -174,16 +203,17 @@ public class RuleFixed implements Rule {
throw
new
Error
(
"type="
+
type
);
}
if
(
s
==
query
)
{
return
null
;
return
false
;
}
return
s
;
sentence
.
setQuery
(
s
);
return
true
;
}
public
void
addNextTokenList
(
S
tring
query
,
S
entence
sentence
)
{
public
void
addNextTokenList
(
Sentence
sentence
)
{
if
(
sentence
.
stop
())
{
return
;
}
// String s = matchRemove(query, iteration)
;
String
query
=
sentence
.
query
;
switch
(
type
)
{
case
YMD:
if
(
query
.
length
()
==
0
)
{
...
...
h2/src/main/org/h2/bnf/RuleList.java
浏览文件 @
158b3d44
...
...
@@ -16,6 +16,28 @@ public class RuleList implements Rule {
private
boolean
or
;
private
ArrayList
list
;
private
boolean
mapSet
;
public
String
toString
()
{
StringBuffer
buff
=
new
StringBuffer
();
if
(
or
)
{
buff
.
append
(
"{"
);
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
"|"
);
}
buff
.
append
(
list
.
get
(
i
).
toString
());
}
buff
.
append
(
"}"
);
}
else
{
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
if
(
i
>
0
)
{
buff
.
append
(
" "
);
}
buff
.
append
(
list
.
get
(
i
).
toString
());
}
}
return
buff
.
toString
();
}
RuleList
(
Rule
first
,
Rule
next
,
boolean
or
)
{
list
=
new
ArrayList
();
...
...
@@ -91,48 +113,47 @@ public class RuleList implements Rule {
}
}
public
String
matchRemove
(
String
query
,
Sentence
sentence
)
{
public
boolean
matchRemove
(
Sentence
sentence
)
{
String
query
=
sentence
.
query
;
if
(
query
.
length
()
==
0
)
{
return
null
;
return
false
;
}
if
(
or
)
{
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
String
s
=
get
(
i
).
matchRemove
(
query
,
sentence
);
if
(
s
!=
null
)
{
return
s
;
if
(
get
(
i
).
matchRemove
(
sentence
))
{
return
true
;
}
}
return
null
;
return
false
;
}
else
{
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
Rule
r
=
get
(
i
);
query
=
r
.
matchRemove
(
query
,
sentence
);
if
(
query
==
null
)
{
return
null
;
if
(!
r
.
matchRemove
(
sentence
))
{
return
false
;
}
}
return
query
;
return
true
;
}
}
public
void
addNextTokenList
(
String
query
,
Sentence
sentence
)
{
// if (sentence.stop()) {
//
// }
public
void
addNextTokenList
(
Sentence
sentence
)
{
String
old
=
sentence
.
query
;
if
(
or
)
{
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
get
(
i
).
addNextTokenList
(
query
,
sentence
);
sentence
.
setQuery
(
old
);
Rule
r
=
get
(
i
);
r
.
addNextTokenList
(
sentence
);
}
}
else
{
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
Rule
r
=
get
(
i
);
r
.
addNextTokenList
(
query
,
sentence
);
query
=
r
.
matchRemove
(
query
,
sentence
);
if
(
query
==
null
)
{
r
.
addNextTokenList
(
sentence
);
if
(!
r
.
matchRemove
(
sentence
))
{
break
;
}
}
}
sentence
.
setQuery
(
old
);
}
}
h2/src/main/org/h2/bnf/RuleOptional.java
浏览文件 @
158b3d44
...
...
@@ -17,6 +17,10 @@ public class RuleOptional implements Rule {
RuleOptional
(
Rule
rule
,
boolean
repeat
)
{
this
.
rule
=
rule
;
}
public
String
toString
()
{
return
"["
+
rule
.
toString
()
+
"]"
;
}
public
String
name
()
{
return
null
;
...
...
@@ -41,25 +45,25 @@ public class RuleOptional implements Rule {
}
}
public
String
matchRemove
(
String
query
,
Sentence
sentence
)
{
public
boolean
matchRemove
(
Sentence
sentence
)
{
if
(
sentence
.
stop
())
{
return
null
;
return
false
;
}
String
query
=
sentence
.
query
;
if
(
query
.
length
()
==
0
)
{
return
query
;
return
true
;
}
String
s
=
rule
.
matchRemove
(
query
,
sentence
);
if
(
s
==
null
)
{
return
query
;
if
(!
rule
.
matchRemove
(
sentence
))
{
return
true
;
}
return
s
;
return
true
;
}
public
void
addNextTokenList
(
S
tring
query
,
S
entence
sentence
)
{
public
void
addNextTokenList
(
Sentence
sentence
)
{
if
(
sentence
.
stop
())
{
return
;
}
rule
.
addNextTokenList
(
query
,
sentence
);
rule
.
addNextTokenList
(
sentence
);
}
}
h2/src/main/org/h2/bnf/RuleRepeat.java
浏览文件 @
158b3d44
...
...
@@ -17,6 +17,10 @@ public class RuleRepeat implements Rule {
RuleRepeat
(
Rule
rule
)
{
this
.
rule
=
rule
;
}
public
String
toString
()
{
return
"..."
;
}
public
String
name
()
{
return
rule
.
name
();
...
...
@@ -34,36 +38,36 @@ public class RuleRepeat implements Rule {
return
rule
.
random
(
config
,
level
);
}
public
String
matchRemove
(
String
query
,
Sentence
sentence
)
{
public
boolean
matchRemove
(
Sentence
sentence
)
{
if
(
sentence
.
stop
())
{
return
null
;
return
false
;
}
String
query
=
sentence
.
query
;
if
(
query
.
length
()
==
0
)
{
return
null
;
return
false
;
}
while
(
true
)
{
String
s
=
rule
.
matchRemove
(
query
,
sentence
);
if
(
s
==
null
)
{
return
query
;
}
else
if
(
s
.
length
()
==
0
)
{
return
s
;
if
(!
rule
.
matchRemove
(
sentence
))
{
return
true
;
}
if
(
sentence
.
query
.
length
()
==
0
)
{
return
true
;
}
query
=
s
;
}
}
public
void
addNextTokenList
(
S
tring
query
,
S
entence
sentence
)
{
public
void
addNextTokenList
(
Sentence
sentence
)
{
if
(
sentence
.
stop
())
{
return
;
}
String
old
=
sentence
.
query
;
while
(
true
)
{
rule
.
addNextTokenList
(
query
,
sentence
);
String
s
=
rule
.
matchRemove
(
query
,
sentence
);
if
(
s
==
null
||
s
==
query
)
{
rule
.
addNextTokenList
(
sentence
);
if
(!
rule
.
matchRemove
(
sentence
)
||
old
==
sentence
.
query
)
{
break
;
}
query
=
s
;
}
sentence
.
setQuery
(
old
);
}
}
h2/src/main/org/h2/bnf/Sentence.java
浏览文件 @
158b3d44
...
...
@@ -8,7 +8,9 @@ package org.h2.bnf;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
org.h2.server.web.DbSchema
;
import
org.h2.server.web.DbTableOrView
;
import
org.h2.util.StringUtils
;
/**
* A query context object. It contains the list of table and alias objects.
...
...
@@ -24,8 +26,12 @@ public class Sentence {
static
final
int
KEYWORD
=
1
;
static
final
int
FUNCTION
=
2
;
public
String
text
;
public
String
query
;
public
String
queryUpper
;
HashMap
next
;
long
max
;
private
DbSchema
lastMatchedSchema
;
private
DbTableOrView
lastMatchedTable
;
private
DbTableOrView
lastTable
;
private
HashSet
tables
;
private
HashMap
aliases
;
...
...
@@ -97,4 +103,49 @@ public class Sentence {
public
DbTableOrView
getLastTable
()
{
return
lastTable
;
}
/**
* Get the last matched schema if the last match was a schema.
*
* @return the last schema or null
*/
public
DbSchema
getLastMatchedSchema
()
{
return
lastMatchedSchema
;
}
/**
* Set the last matched schema if the last match was a schema,
* or null if it was not.
*
* @param schema the last matched schema or null
*/
public
void
setLastMatchedSchema
(
DbSchema
schema
)
{
this
.
lastMatchedSchema
=
schema
;
}
/**
* Set the last matched table if the last match was a table.
*
* @param table the last matched table or null
*/
public
void
setLastMatchedTable
(
DbTableOrView
table
)
{
this
.
lastMatchedTable
=
table
;
}
/**
* Get the last matched table if the last match was a table.
*
* @return the last table or null
*/
public
DbTableOrView
getLastMatchedTable
()
{
return
lastMatchedTable
;
}
public
void
setQuery
(
String
query
)
{
if
(
this
.
query
!=
query
)
{
this
.
query
=
query
;
this
.
queryUpper
=
StringUtils
.
toUpperEnglish
(
query
);
}
}
}
h2/src/main/org/h2/command/CommandContainer.java
浏览文件 @
158b3d44
...
...
@@ -65,8 +65,9 @@ public class CommandContainer extends Command {
// TODO query time: should keep lock time separate from running time
start
();
prepared
.
checkParameters
();
prepared
.
trace
();
return
prepared
.
update
();
int
updateCount
=
prepared
.
update
();
prepared
.
trace
(
startTime
,
updateCount
);
return
updateCount
;
}
public
LocalResult
query
(
int
maxrows
)
throws
SQLException
{
...
...
@@ -74,8 +75,9 @@ public class CommandContainer extends Command {
// TODO query time: should keep lock time separate from running time
start
();
prepared
.
checkParameters
();
prepared
.
trace
();
return
prepared
.
query
(
maxrows
);
LocalResult
result
=
prepared
.
query
(
maxrows
);
prepared
.
trace
(
startTime
,
result
.
getRowCount
());
return
result
;
}
public
boolean
isReadOnly
()
{
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
158b3d44
...
...
@@ -3012,15 +3012,7 @@ public class Parser {
if
(
readIf
(
"IDENTITY"
)
||
readIf
(
"SERIAL"
))
{
column
=
new
Column
(
columnName
,
Value
.
LONG
);
column
.
setOriginalSQL
(
"IDENTITY"
);
long
start
=
1
,
increment
=
1
;
if
(
readIf
(
"("
))
{
start
=
readLong
();
if
(
readIf
(
","
))
{
increment
=
readLong
();
}
read
(
")"
);
}
column
.
setAutoIncrement
(
true
,
start
,
increment
);
parseAutoIncrement
(
column
);
}
else
{
column
=
parseColumn
(
columnName
);
}
...
...
@@ -3063,15 +3055,7 @@ public class Parser {
readIf
(
"NULL"
);
}
if
(
readIf
(
"AUTO_INCREMENT"
)
||
readIf
(
"IDENTITY"
))
{
long
start
=
1
,
increment
=
1
;
if
(
readIf
(
"("
))
{
start
=
readLong
();
if
(
readIf
(
","
))
{
increment
=
readLong
();
}
read
(
")"
);
}
column
.
setAutoIncrement
(
true
,
start
,
increment
);
parseAutoIncrement
(
column
);
if
(
readIf
(
"NOT"
))
{
read
(
"NULL"
);
}
...
...
@@ -3090,6 +3074,18 @@ public class Parser {
column
.
setComment
(
readCommentIf
());
return
column
;
}
private
void
parseAutoIncrement
(
Column
column
)
throws
SQLException
{
long
start
=
1
,
increment
=
1
;
if
(
readIf
(
"("
))
{
start
=
readLong
();
if
(
readIf
(
","
))
{
increment
=
readLong
();
}
read
(
")"
);
}
column
.
setAutoIncrement
(
true
,
start
,
increment
);
}
private
String
readCommentIf
()
throws
SQLException
{
if
(
readIf
(
"COMMENT"
))
{
...
...
@@ -4397,6 +4393,9 @@ public class Parser {
pk
.
setTableName
(
tableName
);
pk
.
setIndexColumns
(
cols
);
command
.
addConstraintCommand
(
pk
);
if
(
readIf
(
"AUTO_INCREMENT"
))
{
parseAutoIncrement
(
column
);
}
}
else
if
(
readIf
(
"UNIQUE"
))
{
AlterTableAddConstraint
unique
=
new
AlterTableAddConstraint
(
session
,
schema
);
unique
.
setConstraintName
(
constraintName
);
...
...
h2/src/main/org/h2/command/Prepared.java
浏览文件 @
158b3d44
...
...
@@ -274,11 +274,12 @@ public abstract class Prepared {
this
.
session
=
currentSession
;
}
void
trace
()
throws
SQLException
{
void
trace
(
long
startTime
,
int
count
)
throws
SQLException
{
if
(
session
.
getTrace
().
info
())
{
StringBuffer
buff
=
new
StringBuffer
()
;
buff
.
append
(
sql
)
;
long
time
=
System
.
currentTimeMillis
()
-
startTime
;
String
params
;
if
(
parameters
.
size
()
>
0
)
{
StringBuffer
buff
=
new
StringBuffer
(
parameters
.
size
()
*
10
);
buff
.
append
(
" {"
);
for
(
int
i
=
0
;
i
<
parameters
.
size
();
i
++)
{
if
(
i
>
0
)
{
...
...
@@ -289,11 +290,12 @@ public abstract class Prepared {
Expression
e
=
(
Expression
)
parameters
.
get
(
i
);
buff
.
append
(
e
.
getValue
(
session
).
getSQL
());
}
buff
.
append
(
"};"
);
buff
.
append
(
"}"
);
params
=
buff
.
toString
();
}
else
{
buff
.
append
(
';'
)
;
params
=
""
;
}
session
.
getTrace
().
infoSQL
(
buff
.
toString
()
);
session
.
getTrace
().
infoSQL
(
sql
,
params
,
count
,
time
);
}
}
...
...
h2/src/main/org/h2/command/dml/Query.java
浏览文件 @
158b3d44
...
...
@@ -217,7 +217,7 @@ public abstract class Query extends Prepared {
}
Value
[]
params
=
getParameterValues
();
long
now
=
session
.
getDatabase
().
getModificationDataId
();
if
(
lastResult
!=
null
&&
limit
==
lastLimit
)
{
if
(
lastResult
!=
null
&&
!
lastResult
.
isClosed
()
&&
limit
==
lastLimit
)
{
if
(
sameResultAsLast
(
session
,
params
,
lastParameters
,
lastEvaluated
))
{
lastResult
=
lastResult
.
createShallowCopy
(
session
);
if
(
lastResult
!=
null
)
{
...
...
h2/src/main/org/h2/command/dml/Set.java
浏览文件 @
158b3d44
...
...
@@ -168,7 +168,7 @@ public class Set extends Prepared {
}
case
SetTypes
.
DATABASE_EVENT_LISTENER
:
{
session
.
getUser
().
checkAdmin
();
database
.
setEventListener
(
stringValue
);
database
.
setEventListener
Class
(
stringValue
);
break
;
}
case
SetTypes
.
MAX_MEMORY_ROWS
:
{
...
...
h2/src/main/org/h2/engine/Database.java
浏览文件 @
158b3d44
...
...
@@ -182,7 +182,7 @@ public class Database implements DataHandler {
if
(
listener
.
endsWith
(
"'"
))
{
listener
=
listener
.
substring
(
0
,
listener
.
length
()
-
1
);
}
setEventListener
(
listener
);
setEventListener
Class
(
listener
);
}
}
String
log
=
ci
.
getProperty
(
SetTypes
.
LOG
,
null
);
...
...
@@ -396,7 +396,7 @@ public class Database implements DataHandler {
return
store
;
}
public
boolean
validateFilePasswordHash
(
String
c
,
byte
[]
hash
)
throws
SQLException
{
public
boolean
validateFilePasswordHash
(
String
c
,
byte
[]
hash
)
{
return
ByteUtils
.
compareSecure
(
hash
,
filePasswordHash
)
&&
StringUtils
.
equals
(
c
,
cipher
);
}
...
...
@@ -1405,8 +1405,12 @@ public class Database implements DataHandler {
throw
Message
.
getSQLException
(
ErrorCode
.
CLASS_NOT_FOUND_1
,
new
String
[]
{
className
},
e
);
}
}
public
void
setEventListener
(
DatabaseEventListener
eventListener
)
{
this
.
eventListener
=
eventListener
;
}
public
void
setEventListener
(
String
className
)
throws
SQLException
{
public
void
setEventListener
Class
(
String
className
)
throws
SQLException
{
if
(
className
==
null
||
className
.
length
()
==
0
)
{
eventListener
=
null
;
}
else
{
...
...
@@ -1778,4 +1782,8 @@ public class Database implements DataHandler {
return
lobFileListCache
;
}
public
boolean
isSysTableLocked
()
{
return
meta
.
isLockedExclusively
();
}
}
h2/src/main/org/h2/engine/Engine.java
浏览文件 @
158b3d44
...
...
@@ -26,7 +26,8 @@ import org.h2.util.StringUtils;
public
class
Engine
{
private
static
final
Engine
INSTANCE
=
new
Engine
();
private
static
long
delayWrongPassword
=
SysProperties
.
DELAY_WRONG_PASSWORD_MIN
;
private
static
volatile
long
wrongPasswordDelay
=
SysProperties
.
DELAY_WRONG_PASSWORD_MIN
;
private
static
Object
wrongPasswordSync
=
new
Object
();
private
final
HashMap
databases
=
new
HashMap
();
private
Engine
()
{
...
...
@@ -73,26 +74,23 @@ public class Engine {
return
null
;
}
if
(
user
==
null
)
{
try
{
boolean
correct
=
database
.
validateFilePasswordHash
(
cipher
,
ci
.
getFilePasswordHash
());
if
(
correct
)
{
user
=
database
.
findUser
(
ci
.
getUserName
());
if
(
user
==
null
)
{
correct
=
false
;
}
else
{
correct
=
user
.
validateUserPasswordHash
(
ci
.
getUserPasswordHash
());
if
(
database
.
validateFilePasswordHash
(
cipher
,
ci
.
getFilePasswordHash
()))
{
user
=
database
.
findUser
(
ci
.
getUserName
());
if
(
user
!=
null
)
{
if
(!
user
.
validateUserPasswordHash
(
ci
.
getUserPasswordHash
()))
{
user
=
null
;
}
}
validateUserAndPassword
(
correct
);
if
(
opened
&&
!
user
.
getAdmin
())
{
// reset - because the user is not an admin, and has no
// right to listen to exceptions
database
.
setEventListener
(
null
);
}
}
catch
(
SQLException
e
)
{
database
.
removeSession
(
null
);
throw
e
;
}
if
(
opened
&&
(
user
==
null
||
!
user
.
getAdmin
()))
{
// reset - because the user is not an admin, and has no
// right to listen to exceptions
database
.
setEventListener
(
null
);
}
}
if
(
user
==
null
)
{
database
.
removeSession
(
null
);
throw
Message
.
getSQLException
(
ErrorCode
.
WRONG_USER_OR_PASSWORD
);
}
checkClustering
(
ci
,
database
);
Session
session
=
database
.
createUserSession
(
user
);
...
...
@@ -100,7 +98,20 @@ public class Engine {
}
}
public
synchronized
Session
getSession
(
ConnectionInfo
ci
)
throws
SQLException
{
public
Session
getSession
(
ConnectionInfo
ci
)
throws
SQLException
{
try
{
Session
session
=
openSession
(
ci
);
validateUserAndPassword
(
true
);
return
session
;
}
catch
(
SQLException
e
)
{
if
(
e
.
getErrorCode
()
==
ErrorCode
.
WRONG_USER_OR_PASSWORD
)
{
validateUserAndPassword
(
false
);
}
throw
e
;
}
}
private
synchronized
Session
openSession
(
ConnectionInfo
ci
)
throws
SQLException
{
boolean
ifExists
=
ci
.
removeProperty
(
"IFEXISTS"
,
false
);
boolean
ignoreUnknownSetting
=
ci
.
removeProperty
(
"IGNORE_UNKNOWN_SETTINGS"
,
false
);
String
cipher
=
ci
.
removeProperty
(
"CIPHER"
,
null
);
...
...
@@ -179,30 +190,34 @@ public class Engine {
* @param correct if the user name or the password was correct
* @throws SQLException the exception 'wrong user or password'
*/
p
ublic
static
synchronized
void
validateUserAndPassword
(
boolean
correct
)
throws
SQLException
{
p
rivate
static
void
validateUserAndPassword
(
boolean
correct
)
throws
SQLException
{
int
min
=
SysProperties
.
DELAY_WRONG_PASSWORD_MIN
;
if
(
correct
)
{
delayWrongPassword
=
min
;
wrongPasswordDelay
=
min
;
}
else
{
long
delay
=
delayWrongPassword
;
if
(
min
>
0
)
{
// a bit more to protect against timing attacks
delay
+=
Math
.
abs
(
RandomUtils
.
getSecureLong
()
%
100
);
try
{
Thread
.
sleep
(
delay
);
}
catch
(
InterruptedException
e
)
{
// ignore
// this method is not synchronized on the Engine, so that
// successful attempts are not blocked
synchronized
(
wrongPasswordSync
)
{
long
delay
=
wrongPasswordDelay
;
int
max
=
SysProperties
.
DELAY_WRONG_PASSWORD_MAX
;
if
(
max
<=
0
)
{
max
=
Integer
.
MAX_VALUE
;
}
wrongPasswordDelay
+=
wrongPasswordDelay
;
if
(
wrongPasswordDelay
>
max
||
wrongPasswordDelay
<
0
)
{
wrongPasswordDelay
=
max
;
}
if
(
min
>
0
)
{
// a bit more to protect against timing attacks
delay
+=
Math
.
abs
(
RandomUtils
.
getSecureLong
()
%
100
);
try
{
Thread
.
sleep
(
delay
);
}
catch
(
InterruptedException
e
)
{
// ignore
}
}
throw
Message
.
getSQLException
(
ErrorCode
.
WRONG_USER_OR_PASSWORD
);
}
int
max
=
SysProperties
.
DELAY_WRONG_PASSWORD_MAX
;
if
(
max
<=
0
)
{
max
=
Integer
.
MAX_VALUE
;
}
delayWrongPassword
+=
delayWrongPassword
;
if
(
delayWrongPassword
>
max
||
delayWrongPassword
<
0
)
{
delayWrongPassword
=
max
;
}
throw
Message
.
getSQLException
(
ErrorCode
.
WRONG_USER_OR_PASSWORD
);
}
}
...
...
h2/src/main/org/h2/engine/Session.java
浏览文件 @
158b3d44
...
...
@@ -772,10 +772,16 @@ public class Session implements SessionInterface {
}
public
void
addTemporaryResult
(
LocalResult
result
)
{
if
(!
result
.
needToClose
())
{
return
;
}
if
(
temporaryResults
==
null
)
{
temporaryResults
=
new
HashSet
();
}
temporaryResults
.
add
(
result
);
if
(
temporaryResults
.
size
()
<
100
)
{
// reference at most 100 result sets to avoid memory problems
temporaryResults
.
add
(
result
);
}
}
public
void
closeTemporaryResults
()
{
...
...
@@ -784,6 +790,7 @@ public class Session implements SessionInterface {
LocalResult
result
=
(
LocalResult
)
it
.
next
();
result
.
close
();
}
temporaryResults
=
null
;
}
}
...
...
@@ -794,6 +801,9 @@ public class Session implements SessionInterface {
queryTimeout
=
max
;
}
this
.
queryTimeout
=
queryTimeout
;
// must reset the cancel at here,
// otherwise it is still used
this
.
cancelAt
=
0
;
}
public
int
getQueryTimeout
()
{
...
...
h2/src/main/org/h2/expression/SequenceValue.java
浏览文件 @
158b3d44
...
...
@@ -28,7 +28,7 @@ public class SequenceValue extends Expression {
}
public
Value
getValue
(
Session
session
)
throws
SQLException
{
long
value
=
sequence
.
getNext
();
long
value
=
sequence
.
getNext
(
session
);
session
.
setLastIdentity
(
ValueLong
.
get
(
value
));
return
ValueLong
.
get
(
value
);
}
...
...
h2/src/main/org/h2/jdbcx/JdbcConnectionPool
Manager
.java
→
h2/src/main/org/h2/jdbcx/JdbcConnectionPool.java
浏览文件 @
158b3d44
...
...
@@ -19,82 +19,116 @@
*/
package
org
.
h2
.
jdbcx
;
import
java.util.Stack
;
import
java.io.PrintWriter
;
import
java.sql.Connection
;
import
java.sql.SQLException
;
import
javax.sql.ConnectionPoolDataSource
;
import
java.util.Stack
;
import
javax.sql.ConnectionEvent
;
import
javax.sql.DataSource
;
import
javax.sql.ConnectionEventListener
;
import
javax.sql.ConnectionPoolDataSource
;
import
javax.sql.PooledConnection
;
/**
* A simple standalone JDBC connection pool
manager
.
* A simple standalone JDBC connection pool.
* It is based on the
* <a href="http://www.source-code.biz/snippets/java/8.htm">
* MiniConnectionPoolManager written by Christian d'Heureuse (JDK 1.5)
* </a>.
* MiniConnectionPoolManager written by Christian d'Heureuse (Java 1.5)
* </a>. It is used as follows:
* <pre>
* // init
* import org.h2.jdbcx.*;
* ...
* JdbcDataSource ds = new JdbcDataSource();
* ds.setURL("jdbc:h2:~/test");
* ds.setUser("sa");
* ds.setPassword("sa");
* JdbcConnectionPool cp = JdbcConnectionPool.create(ds);
* // use
* Connection conn = cp.getConnection();
* ...
* conn.close();
* // dispose
* cp.dispose();
* </pre>
*
* @author Christian d'Heureuse
* (<a href="http://www.source-code.biz">www.source-code.biz</a>)
* @author Thomas Mueller (ported to J
DK 1.4
)
* @author Thomas Mueller (ported to J
ava 1.4, some changes
)
*/
public
class
JdbcConnectionPool
Manager
{
public
class
JdbcConnectionPool
implements
DataSource
{
private
ConnectionPoolDataSource
dataSource
;
private
int
maxConnections
;
private
int
timeout
;
private
final
ConnectionPoolDataSource
dataSource
;
private
final
Stack
recycledConnections
=
new
Stack
()
;
private
final
PoolConnectionEventListener
poolConnectionEventListener
=
new
PoolConnectionEventListener
()
;
private
PrintWriter
logWriter
;
private
Stack
recycledConnections
;
private
int
maxConnections
=
10
;
private
int
timeout
=
60
;
private
int
activeConnections
;
private
PoolConnectionEventListener
poolConnectionEventListener
;
private
boolean
isDisposed
;
/**
* This inThrown in {@link #getConnection()} when no free connection becomes
* available within <code>timeout</code> seconds.
*/
public
static
class
TimeoutException
extends
RuntimeException
{
private
static
final
long
serialVersionUID
=
1
;
public
TimeoutException
()
{
super
(
"Timeout while waiting for a free database connection."
);
}
}
/**
* Constructs a JdbcConnectionPoolManager object with a timeout of 60
* seconds.
* Constructs a new connection pool.
*
* @param dataSource the data source
for the connections.
* @
param maxConnections the maximum number of connections.
* @param dataSource the data source
to create connections
* @
return the connection pool
*/
public
JdbcConnectionPoolManager
(
ConnectionPoolDataSource
dataSource
,
int
maxConnections
)
{
this
(
dataSource
,
maxConnections
,
60
);
public
static
JdbcConnectionPool
create
(
ConnectionPoolDataSource
dataSource
)
{
return
new
JdbcConnectionPool
(
dataSource
);
}
/**
* Constructs a JdbcConnectionPoolManager object.
*
* @param dataSource the data source for the connections.
* @param maxConnections the maximum number of connections.
* @param timeout the maximum time in seconds to wait for a free connection.
*/
public
JdbcConnectionPoolManager
(
ConnectionPoolDataSource
dataSource
,
int
maxConnections
,
int
timeout
)
{
private
JdbcConnectionPool
(
ConnectionPoolDataSource
dataSource
)
{
this
.
dataSource
=
dataSource
;
this
.
maxConnections
=
maxConnections
;
this
.
timeout
=
timeout
;
try
{
logWriter
=
dataSource
.
getLogWriter
();
}
catch
(
SQLException
e
)
{
}
}
/**
* Sets the maximum number of connections to use from now on.
* The default value is 10 connections.
*
* @param max the maximum number of connections
*/
public
synchronized
void
setMaxConnections
(
int
max
)
{
if
(
maxConnections
<
1
)
{
throw
new
IllegalArgumentException
(
"Invalid maxConnections value."
);
}
recycledConnections
=
new
Stack
();
poolConnectionEventListener
=
new
PoolConnectionEventListener
();
this
.
maxConnections
=
max
;
// notify waiting threads if the value was increased
notifyAll
();
}
/**
* Gets the maximum number of connections to use.
*
* @return the max the maximum number of connections
*/
public
synchronized
int
getMaxConnections
()
{
return
maxConnections
;
}
/**
* Gets the maximum time in seconds to wait for a free connection.
*
* @return the timeout in seconds
*/
public
synchronized
int
getLoginTimeout
()
{
return
timeout
;
}
/**
* Sets the maximum time in seconds to wait for a free connection.
* The default timeout is 60 seconds.
*
* @param seconds the maximum timeout
*/
public
synchronized
void
setLoginTimeout
(
int
seconds
)
throws
SQLException
{
this
.
timeout
=
seconds
;
}
/**
* Closes all unused pooled connections.
*/
...
...
@@ -125,10 +159,12 @@ public class JdbcConnectionPoolManager {
* waits until a connection becomes available or <code>timeout</code>
* seconds elapsed. When the application is finished using the connection,
* it must close it in order to return it to the pool.
* If no connection becomes available within the given timeout, an exception
* with SQL state 08001 and vendor code 8001 is thrown.
*
* @return a new Connection object.
* @throws
TimeoutException when no connection becomes available within
*
<code>timeout</code> seconds.
* @throws
SQLException when a new connection could not be established,
*
or a timeout occured
*/
public
Connection
getConnection
()
throws
SQLException
{
for
(
int
i
=
0
;;
i
++)
{
...
...
@@ -137,7 +173,7 @@ public class JdbcConnectionPoolManager {
return
getConnectionNow
();
}
if
(
i
>=
timeout
)
{
throw
new
TimeoutException
(
);
throw
new
SQLException
(
"Login timeout"
,
"08001"
,
8001
);
}
try
{
wait
(
1000
);
...
...
@@ -161,7 +197,6 @@ public class JdbcConnectionPoolManager {
Connection
conn
=
pc
.
getConnection
();
activeConnections
++;
pc
.
addConnectionEventListener
(
poolConnectionEventListener
);
assertInnerState
();
return
conn
;
}
...
...
@@ -174,9 +209,20 @@ public class JdbcConnectionPoolManager {
throw
new
AssertionError
();
}
activeConnections
--;
if
(
activeConnections
<
maxConnections
)
{
recycledConnections
.
push
(
pc
);
}
else
{
closeConnection
(
pc
);
}
notifyAll
();
recycledConnections
.
push
(
pc
);
assertInnerState
();
}
private
void
closeConnection
(
PooledConnection
pc
)
{
try
{
pc
.
close
();
}
catch
(
SQLException
e
)
{
log
(
"Error while closing database connection: "
+
e
.
toString
());
}
}
private
synchronized
void
disposeConnection
(
PooledConnection
pc
)
{
...
...
@@ -185,16 +231,11 @@ public class JdbcConnectionPoolManager {
}
activeConnections
--;
notifyAll
();
try
{
pc
.
close
();
}
catch
(
SQLException
e
)
{
log
(
"Error while closing database connection: "
+
e
.
toString
());
}
assertInnerState
();
closeConnection
(
pc
);
}
private
void
log
(
String
msg
)
{
String
s
=
"JdbcConnectionPoolManager
: "
+
msg
;
String
s
=
getClass
().
getName
()
+
"
: "
+
msg
;
try
{
if
(
logWriter
==
null
)
{
System
.
err
.
println
(
s
);
...
...
@@ -205,15 +246,6 @@ public class JdbcConnectionPoolManager {
}
}
private
void
assertInnerState
()
{
if
(
activeConnections
<
0
)
{
throw
new
AssertionError
();
}
if
(
activeConnections
+
recycledConnections
.
size
()
>
maxConnections
)
{
throw
new
AssertionError
();
}
}
private
class
PoolConnectionEventListener
implements
ConnectionEventListener
{
public
void
connectionClosed
(
ConnectionEvent
event
)
{
PooledConnection
pc
=
(
PooledConnection
)
event
.
getSource
();
...
...
@@ -240,4 +272,25 @@ public class JdbcConnectionPoolManager {
return
activeConnections
;
}
/**
* INTERNAL
*/
public
Connection
getConnection
(
String
username
,
String
password
)
throws
SQLException
{
throw
new
UnsupportedOperationException
();
}
/**
* INTERNAL
*/
public
PrintWriter
getLogWriter
()
throws
SQLException
{
return
logWriter
;
}
/**
* INTERNAL
*/
public
void
setLogWriter
(
PrintWriter
logWriter
)
throws
SQLException
{
this
.
logWriter
=
logWriter
;
}
}
h2/src/main/org/h2/jdbcx/JdbcDataSource.java
浏览文件 @
158b3d44
...
...
@@ -291,7 +291,7 @@ implements XADataSource, DataSource, ConnectionPoolDataSource, Serializable, Ref
//#endif
/**
* Open a new
XA
connection using the current URL, user name and password.
* Open a new
pooled
connection using the current URL, user name and password.
*
* @return the connection
*/
...
...
@@ -303,7 +303,7 @@ implements XADataSource, DataSource, ConnectionPoolDataSource, Serializable, Ref
//#endif
/**
* Open a new
XA
connection using the current URL and the specified user
* Open a new
pooled
connection using the current URL and the specified user
* name and password.
*
* @param user the user name
...
...
h2/src/main/org/h2/message/Trace.java
浏览文件 @
158b3d44
...
...
@@ -71,9 +71,28 @@ public class Trace {
traceSystem
.
write
(
TraceSystem
.
INFO
,
module
,
lineSeparator
+
"/**/"
+
java
,
null
);
}
public
void
infoSQL
(
String
sql
)
{
sql
=
StringUtils
.
javaEncode
(
sql
);
traceSystem
.
write
(
TraceSystem
.
INFO
,
module
,
lineSeparator
+
"/*SQL*/"
+
sql
,
null
);
public
void
infoSQL
(
String
sql
,
String
params
,
int
count
,
long
time
)
{
StringBuffer
buff
=
new
StringBuffer
(
sql
.
length
()
+
20
);
buff
.
append
(
lineSeparator
);
buff
.
append
(
"/*SQL "
);
if
(
params
.
length
()
>
0
)
{
buff
.
append
(
"l:"
);
buff
.
append
(
sql
.
length
());
}
if
(
count
>
0
)
{
buff
.
append
(
" #:"
);
buff
.
append
(
count
);
}
if
(
time
>
0
)
{
buff
.
append
(
" t:"
);
buff
.
append
(
time
);
}
buff
.
append
(
"*/"
);
buff
.
append
(
StringUtils
.
javaEncode
(
sql
));
buff
.
append
(
params
);
buff
.
append
(
';'
);
sql
=
buff
.
toString
();
traceSystem
.
write
(
TraceSystem
.
INFO
,
module
,
sql
,
null
);
}
public
void
debug
(
String
s
)
{
...
...
h2/src/main/org/h2/res/help.csv
浏览文件 @
158b3d44
...
...
@@ -1220,13 +1220,14 @@ If the table name is not specified, then the same table is referenced.
As this database does not support deferred checking,
RESTRICT and NO ACTION will both throw an exception if the constraint is violated.
If the referenced columns are not specified, then the primary key columns are used.
The required indexes are automatically created if required.
","
FOREIGN KEY(ID) REFERENCES TEST(ID)
"
"Other Grammar","Table Expression","
{tableName | (select)} [[AS] newTableAlias]
{
[schemaName.]
tableName | (select)} [[AS] newTableAlias]
[{{LEFT | RIGHT} [OUTER] | [INNER] | CROSS | NATURAL}
JOIN
{tableName | viewName}
[[AS] newTableAlias] [ON expression] ]
JOIN
tableExpression
[[AS] newTableAlias] [ON expression] ]
","
Joins a table. The join expression is not supported for cross and natural joins.
A natural join is an inner join, where the condition is automatically on the columns with the same name.
...
...
@@ -2628,7 +2629,7 @@ Returns true if the statement was cancelled, false if the session is closed
or no statement is currently executing.
Admin rights are required to execute this command.
","
CANCEL_S
TATEMENT
(3)
CANCEL_S
ESSION
(3)
"
"Functions (System)","CASEWHEN Function","
...
...
h2/src/main/org/h2/result/LocalResult.java
浏览文件 @
158b3d44
...
...
@@ -45,6 +45,7 @@ public class LocalResult implements ResultInterface {
private
boolean
isUpdateCount
;
private
int
updateCount
;
private
boolean
distinct
;
private
boolean
closed
;
public
static
LocalResult
read
(
Session
session
,
ResultSet
rs
,
int
maxrows
)
throws
SQLException
{
ObjectArray
cols
=
getExpressionColumns
(
session
,
rs
);
...
...
@@ -314,11 +315,16 @@ public class LocalResult implements ResultInterface {
}
}
}
public
boolean
needToClose
()
{
return
disk
!=
null
;
}
public
void
close
()
{
if
(
disk
!=
null
)
{
disk
.
close
();
disk
=
null
;
closed
=
true
;
}
}
...
...
@@ -394,4 +400,8 @@ public class LocalResult implements ResultInterface {
return
"columns: "
+
visibleColumnCount
+
" rows: "
+
rowCount
+
" pos: "
+
rowId
;
}
public
boolean
isClosed
()
{
return
closed
;
}
}
h2/src/main/org/h2/schema/Sequence.java
浏览文件 @
158b3d44
...
...
@@ -82,36 +82,44 @@ public class Sequence extends SchemaObjectBase {
return
buff
.
toString
();
}
public
synchronized
long
getNext
()
throws
SQLException
{
public
synchronized
long
getNext
(
Session
session
)
throws
SQLException
{
if
((
increment
>
0
&&
value
>=
valueWithMargin
)
||
(
increment
<
0
&&
value
<=
valueWithMargin
))
{
valueWithMargin
+=
increment
*
cacheSize
;
flush
();
flush
(
session
);
}
long
v
=
value
;
value
+=
increment
;
return
v
;
}
public
synchronized
void
flush
()
throws
SQLException
{
// can not use the session, because it must be committed immediately
// otherwise other threads can not access the sys table.
public
synchronized
void
flush
(
Session
session
)
throws
SQLException
{
Session
sysSession
=
database
.
getSystemSession
();
synchronized
(
sysSession
)
{
if
(
session
==
null
||
!
database
.
isSysTableLocked
())
{
// this session may not lock the sys table (except if it already has locked it)
// because it must be committed immediately
// otherwise other threads can not access the sys table.
session
=
sysSession
;
}
synchronized
(
session
)
{
// just for this case, use the value with the margin for the script
long
realValue
=
value
;
try
{
value
=
valueWithMargin
;
database
.
update
(
s
ysS
ession
,
this
);
database
.
update
(
session
,
this
);
}
finally
{
value
=
realValue
;
}
sysSession
.
commit
(
false
);
if
(
session
==
sysSession
)
{
// if the system session is used,
// the transaction must be committed immediately
sysSession
.
commit
(
false
);
}
}
}
public
void
close
()
throws
SQLException
{
valueWithMargin
=
value
;
flush
();
flush
(
null
);
}
public
int
getType
()
{
...
...
h2/src/main/org/h2/server/web/DbContextRule.java
浏览文件 @
158b3d44
差异被折叠。
点击展开。
h2/src/main/org/h2/server/web/WebSession.java
浏览文件 @
158b3d44
...
...
@@ -36,6 +36,7 @@ public class WebSession {
private
DbContents
contents
=
new
DbContents
();
private
DbContextRule
columnRule
;
private
DbContextRule
newAliasRule
;
private
DbContextRule
schemaRule
;
private
DbContextRule
tableRule
;
private
DbContextRule
aliasRule
;
private
DbContextRule
columnAliasRule
;
...
...
@@ -73,6 +74,7 @@ public class WebSession {
newAliasRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
NEW_TABLE_ALIAS
);
aliasRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
TABLE_ALIAS
);
tableRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
TABLE
);
schemaRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
SCHEMA
);
columnAliasRule
=
new
DbContextRule
(
contents
,
DbContextRule
.
COLUMN_ALIAS
);
// bnf.updateTopic("newTableName", new String[]{"TEST"});
// String[] schemas;
...
...
@@ -90,6 +92,7 @@ public class WebSession {
newBnf
.
updateTopic
(
"tableAlias"
,
aliasRule
);
newBnf
.
updateTopic
(
"columnAlias"
,
columnAliasRule
);
newBnf
.
updateTopic
(
"tableName"
,
tableRule
);
newBnf
.
updateTopic
(
"schemaName"
,
schemaRule
);
// bnf.updateTopic("name", new String[]{""});
newBnf
.
linkStatements
();
bnf
=
newBnf
;
...
...
h2/src/main/org/h2/store/fs/FileSystemMemory.java
浏览文件 @
158b3d44
...
...
@@ -36,6 +36,8 @@ public class FileSystemMemory extends FileSystem {
}
public
void
rename
(
String
oldName
,
String
newName
)
throws
SQLException
{
oldName
=
normalize
(
oldName
);
newName
=
normalize
(
newName
);
FileObjectMemory
f
=
getMemoryFile
(
oldName
);
f
.
setName
(
newName
);
synchronized
(
MEMORY_FILES
)
{
...
...
@@ -54,18 +56,21 @@ public class FileSystemMemory extends FileSystem {
}
public
boolean
exists
(
String
fileName
)
{
fileName
=
normalize
(
fileName
);
synchronized
(
MEMORY_FILES
)
{
return
MEMORY_FILES
.
get
(
fileName
)
!=
null
;
}
}
public
void
delete
(
String
fileName
)
throws
SQLException
{
fileName
=
normalize
(
fileName
);
synchronized
(
MEMORY_FILES
)
{
MEMORY_FILES
.
remove
(
fileName
);
}
}
public
boolean
tryDelete
(
String
fileName
)
{
public
boolean
tryDelete
(
String
fileName
)
{
fileName
=
normalize
(
fileName
);
synchronized
(
MEMORY_FILES
)
{
MEMORY_FILES
.
remove
(
fileName
);
}
...
...
@@ -104,12 +109,21 @@ public class FileSystemMemory extends FileSystem {
return
false
;
}
public
String
normalize
(
String
fileName
)
throws
SQLException
{
public
String
normalize
(
String
fileName
)
{
fileName
=
fileName
.
replace
(
'\\'
,
'/'
);
int
idx
=
fileName
.
indexOf
(
":/"
);
if
(
idx
>
0
)
{
fileName
=
fileName
.
substring
(
0
,
idx
+
1
)
+
fileName
.
substring
(
idx
+
2
);
}
return
fileName
;
}
public
String
getParent
(
String
fileName
)
{
int
idx
=
Math
.
max
(
fileName
.
indexOf
(
':'
),
fileName
.
lastIndexOf
(
'/'
));
fileName
=
normalize
(
fileName
);
int
idx
=
fileName
.
lastIndexOf
(
'/'
);
if
(
idx
<
0
)
{
idx
=
fileName
.
indexOf
(
':'
)
+
1
;
}
return
fileName
.
substring
(
0
,
idx
);
}
...
...
@@ -125,7 +139,7 @@ public class FileSystemMemory extends FileSystem {
public
String
getAbsolutePath
(
String
fileName
)
{
// TODO relative files are not supported
return
fileName
;
return
normalize
(
fileName
)
;
}
public
long
getLastModified
(
String
fileName
)
{
...
...
@@ -156,6 +170,8 @@ public class FileSystemMemory extends FileSystem {
}
public
boolean
fileStartsWith
(
String
fileName
,
String
prefix
)
{
fileName
=
normalize
(
fileName
);
prefix
=
normalize
(
prefix
);
return
fileName
.
startsWith
(
prefix
);
}
...
...
@@ -182,6 +198,7 @@ public class FileSystemMemory extends FileSystem {
}
private
FileObjectMemory
getMemoryFile
(
String
fileName
)
{
fileName
=
normalize
(
fileName
);
synchronized
(
MEMORY_FILES
)
{
FileObjectMemory
m
=
(
FileObjectMemory
)
MEMORY_FILES
.
get
(
fileName
);
if
(
m
==
null
)
{
...
...
h2/src/main/org/h2/table/Column.java
浏览文件 @
158b3d44
...
...
@@ -266,7 +266,7 @@ public class Column {
if
(
update
)
{
sequence
.
setStartValue
(
now
+
increment
);
session
.
setLastIdentity
(
ValueLong
.
get
(
now
));
sequence
.
flush
();
sequence
.
flush
(
session
);
}
}
}
...
...
h2/src/main/org/h2/tools/ConvertTraceFile.java
浏览文件 @
158b3d44
...
...
@@ -8,6 +8,10 @@ import java.io.IOException;
import
java.io.LineNumberReader
;
import
java.io.PrintWriter
;
import
java.sql.SQLException
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.StringTokenizer
;
import
org.h2.message.Message
;
import
org.h2.util.FileUtils
;
...
...
@@ -20,6 +24,31 @@ import org.h2.util.Tool;
* This is required because the find command truncates lines.
*/
public
class
ConvertTraceFile
extends
Tool
{
private
HashMap
stats
=
new
HashMap
();
private
long
timeTotal
;
private
static
class
Stat
implements
Comparable
{
String
sql
;
int
executeCount
;
long
time
;
long
resultCountTotal
;
public
int
compareTo
(
Object
o
)
{
Stat
other
=
(
Stat
)
o
;
if
(
other
==
this
)
{
return
0
;
}
int
c
=
other
.
time
>
time
?
1
:
other
.
time
<
time
?
-
1
:
0
;
if
(
c
==
0
)
{
c
=
other
.
executeCount
>
executeCount
?
1
:
other
.
executeCount
<
executeCount
?
-
1
:
0
;
if
(
c
==
0
)
{
c
=
sql
.
compareTo
(
other
.
sql
);
}
}
return
c
;
}
}
private
void
showUsage
()
{
out
.
println
(
"Converts a .trace.db file to a SQL script and Java source code."
);
...
...
@@ -107,16 +136,60 @@ public class ConvertTraceFile extends Tool {
if
(
line
.
startsWith
(
"/**/"
))
{
line
=
" "
+
line
.
substring
(
4
);
javaWriter
.
println
(
line
);
}
else
if
(
line
.
startsWith
(
"/*SQL*/"
))
{
line
=
line
.
substring
(
"/*SQL*/"
.
length
());
scriptWriter
.
println
(
StringUtils
.
javaDecode
(
line
));
}
else
if
(
line
.
startsWith
(
"/*SQL"
))
{
int
end
=
line
.
indexOf
(
"*/"
);
String
sql
=
line
.
substring
(
end
+
"*/"
.
length
());
line
=
line
.
substring
(
"/*SQL"
.
length
(),
end
);
if
(
line
.
length
()
>
0
)
{
int
len
=
sql
.
length
();
int
count
=
0
;
int
time
=
0
;
line
=
line
.
trim
();
if
(
line
.
length
()
>
0
)
{
StringTokenizer
tk
=
new
StringTokenizer
(
line
,
" :"
);
while
(
tk
.
hasMoreElements
())
{
String
token
=
tk
.
nextToken
();
if
(
"l"
.
equals
(
token
))
{
len
=
Integer
.
parseInt
(
tk
.
nextToken
());
}
else
if
(
"#"
.
equals
(
token
))
{
count
=
Integer
.
parseInt
(
tk
.
nextToken
());
}
else
if
(
"t"
.
equals
(
token
))
{
time
=
Integer
.
parseInt
(
tk
.
nextToken
());
}
}
}
String
statement
=
sql
.
substring
(
0
,
len
);
addToStats
(
statement
,
count
,
time
);
}
scriptWriter
.
println
(
StringUtils
.
javaDecode
(
sql
));
}
}
javaWriter
.
println
(
" }"
);
javaWriter
.
println
(
"}"
);
reader
.
close
();
javaWriter
.
close
();
if
(
stats
.
size
()
>
0
)
{
scriptWriter
.
println
(
"---------------------------------------------------------------"
);
ArrayList
list
=
new
ArrayList
(
stats
.
values
());
Collections
.
sort
(
list
);
int
todo
;
scriptWriter
.
println
(
"--"
);
}
scriptWriter
.
close
();
}
private
void
addToStats
(
String
sql
,
int
resultCount
,
int
time
)
{
Stat
stat
=
(
Stat
)
stats
.
get
(
sql
);
if
(
stat
==
null
)
{
stat
=
new
Stat
();
stat
.
sql
=
sql
;
stats
.
put
(
sql
,
stat
);
}
stat
.
executeCount
++;
stat
.
resultCountTotal
+=
resultCount
;
stat
.
time
+=
time
;
timeTotal
+=
time
;
}
}
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
158b3d44
...
...
@@ -159,11 +159,28 @@ java org.h2.test.TestAll timer
/*
delay on wrong password: double the time, randomized, reset on right password
1. get application here: http://krtonozka23.savana.cz/mismatch_error.zip
2. unpack and execute: java -jar executeh2script.jar
3. it will copy the prepared database from basedb into dbtest
directory and execute the crashScript.txt upon it.
4. connect to created dbtest database with h2 console and execute:
SELECT Data FROM FD_12_5001 WHERE TypeId=4 ORDER BY Ts DESC;
5. you should got something like: General error: java.lang.Error: File
ID mismatch got=1707400262 expected=41 pos=57219 true
org.h2.store.DiskFile:E:\WiMax\projects\Java\ExecuteH2Script\dbtest
\dbtest.data.db blockCount:-755423910 [50000-67] (Help)
File ID mismatch: 2008-03-21.trace.zip
test ConvertTraceFile
include in the execution times in the debug log.
(for each SQL statement ran)
SQL:checksum:1ms SELECT * FROM TEST
checksum: not including values, case insensitive
optimize where x not in (select):
SELECT c FROM color LEFT OUTER JOIN (SELECT c FROM TABLE(c
VARCHAR= ?)) p ON color.c = p.c WHERE p.c IS NULL;
better document system tables
.tar.bz2 instead of .zip
drop table test;
create table test(id int);
...
...
@@ -172,43 +189,9 @@ inner join test t3 on t3.id=t2.id on t1.id=t2.id;
-- supported by PostgreSQL, Derby,...;
not supported by MySQL,...
wrong password should be synchronized outside:
wrong password should delay other wrong password,
but not right password
javadocs: constructors are not listed (JdbcConnectionPoolManager)
JdbcConnectionPoolManager pm =
new JdbcConnectionPoolManager();
pm.setDataSource(ds);
pm.setMaxConnection(10);
pm.setTimeout(10);
pm.start();
or:
JdbcConnectionPoolManager pm =
new JdbcConnectionPoolManager();
pm.setDataSource(ds).
setMaxConnection(10).setTimeout(10).start();
include in the execution times in the debug log.
(for each SQL statement ran)
SQL:checksum:1ms SELECT * FROM TEST
checksum: not including values, case insensitive
Derby doesn't optimize it
drop table test;
create table test(id int, version int, idx int);
@LOOP 1000 insert into test values(1, 1, ?);
@LOOP 1000 insert into test values(1, 2, ?);
@LOOP 1000 insert into test values(2, 1, ?);
create index idx_test on test(id, version, idx);
@LOOP 1000 select max(id)+1 from test;
@LOOP 1000 select max(idx)+1 from test where id=1 and version=2;
@LOOP 1000 select max(id)+1 from test;
@LOOP 1000 select max(idx)+1 from test where id=1 and version=2;
@LOOP 1000 select max(id)+1 from test;
@LOOP 1000 select max(idx)+1 from test where id=1 and version=2;
-- should be direct query
optimize where x not in (select):
SELECT c FROM color LEFT OUTER JOIN (SELECT c FROM TABLE(c
VARCHAR= ?)) p ON color.c = p.c WHERE p.c IS NULL;
Browser problems:
There has been a reported incompatibility with the
...
...
@@ -258,14 +241,31 @@ Can sometimes not delete log file? need test case
Add where required // TODO: change in version 1.1
http://www.w3schools.com/sql/
History:
The autocomplete in the H2 Console has been improved a bit.
The tools in the H2 Console are now translatable.
Invalid inline views threw confusing SQL exceptions.
The Japanese translation of the error messages and the
H2 Console has been improved. Thanks a lot to Masahiro IKEMOTO.
Optimization for MIN() and MAX() when using MVCC.
To protect against remote brute force password attacks,
the delay after each unsuccessful login now gets double as long.
Use the system properties h2.delayWrongPasswordMin
and h2.delayWrongPasswordMax
After setting the query timeout and then resetting it, the next query
would still timeout. Fixed.
Adding a IDENTITY column to a table with data threw a lock timeout.
OutOfMemoryError could occur when using EXISTS or IN(SELECT ..).
The built-in connection pool is not called JdbcConnectionPool.
The API and documentation has been changed.
Roadmap:
Doclet (javadocs): constructors are not listed
Support direct lookup for MIN and MAX when using WHERE (see todo.txt / Direct Lookup)
*/
...
...
h2/src/test/org/h2/test/db/TestSequence.java
浏览文件 @
158b3d44
...
...
@@ -17,11 +17,24 @@ import org.h2.test.TestBase;
public
class
TestSequence
extends
TestBase
{
public
void
test
()
throws
Exception
{
testAlterSequenceColumn
();
testAlterSequence
();
testCache
();
testTwo
();
}
private
void
testAlterSequenceColumn
()
throws
Exception
{
deleteDb
(
"sequence"
);
Connection
conn
=
getConnection
(
"sequence"
);
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"CREATE TABLE TEST(ID INT , NAME VARCHAR(255))"
);
stat
.
execute
(
"INSERT INTO TEST VALUES(1, 'Hello')"
);
stat
.
execute
(
"ALTER TABLE TEST ALTER COLUMN ID INT IDENTITY"
);
stat
.
execute
(
"ALTER TABLE test ALTER COLUMN ID RESTART WITH 3"
);
stat
.
execute
(
"INSERT INTO TEST (name) VALUES('Other World')"
);
conn
.
close
();
}
private
void
testAlterSequence
()
throws
Exception
{
deleteDb
(
"sequence"
);
Connection
conn
=
getConnection
(
"sequence"
);
...
...
h2/src/test/org/h2/test/jdbc/TestCancel.java
浏览文件 @
158b3d44
...
...
@@ -44,11 +44,28 @@ public class TestCancel extends TestBase {
}
public
void
test
()
throws
Exception
{
testReset
();
testMaxQueryTimeout
();
testQueryTimeout
();
testJdbcQueryTimeout
();
testCancelStatement
();
}
private
void
testReset
()
throws
Exception
{
deleteDb
(
"cancel"
);
Connection
conn
=
getConnection
(
"cancel"
);
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"set query_timeout 1"
);
try
{
stat
.
execute
(
"select count(*) from system_range(1, 1000000), system_range(1, 1000000)"
);
error
();
}
catch
(
SQLException
e
)
{
checkNotGeneralException
(
e
);
}
stat
.
execute
(
"set query_timeout 0"
);
stat
.
execute
(
"select count(*) from system_range(1, 1000), system_range(1, 1000)"
);
conn
.
close
();
}
private
void
testJdbcQueryTimeout
()
throws
Exception
{
deleteDb
(
"cancel"
);
...
...
h2/src/test/org/h2/test/jdbcx/TestConnectionPool.java
浏览文件 @
158b3d44
...
...
@@ -8,7 +8,7 @@ package org.h2.test.jdbcx;
import
java.sql.Connection
;
import
java.sql.Statement
;
import
org.h2.jdbcx.JdbcConnectionPool
Manager
;
import
org.h2.jdbcx.JdbcConnectionPool
;
import
org.h2.jdbcx.JdbcDataSource
;
import
org.h2.test.TestBase
;
...
...
@@ -25,7 +25,7 @@ public class TestConnectionPool extends TestBase {
private
void
testThreads
()
throws
Exception
{
final
int
len
=
getSize
(
4
,
20
);
final
JdbcConnectionPool
Manager
man
=
getConnectionPool
(
len
-
2
);
final
JdbcConnectionPool
man
=
getConnectionPool
(
len
-
2
);
final
boolean
[]
stop
=
new
boolean
[
1
];
class
TestRunner
implements
Runnable
{
public
void
run
()
{
...
...
@@ -57,16 +57,18 @@ public class TestConnectionPool extends TestBase {
man
.
dispose
();
}
JdbcConnectionPool
Manager
getConnectionPool
(
int
poolSize
)
throws
Exception
{
JdbcConnectionPool
getConnectionPool
(
int
poolSize
)
throws
Exception
{
JdbcDataSource
ds
=
new
JdbcDataSource
();
ds
.
setURL
(
getURL
(
"connectionPool"
,
true
));
ds
.
setUser
(
getUser
());
ds
.
setPassword
(
getPassword
());
return
new
JdbcConnectionPoolManager
(
ds
,
poolSize
,
2
);
JdbcConnectionPool
pool
=
JdbcConnectionPool
.
create
(
ds
);
pool
.
setMaxConnections
(
poolSize
);
return
pool
;
}
private
void
testConnect
()
throws
Exception
{
JdbcConnectionPool
Manager
man
=
getConnectionPool
(
3
);
JdbcConnectionPool
man
=
getConnectionPool
(
3
);
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
Connection
conn
=
man
.
getConnection
();
conn
.
close
();
...
...
h2/src/test/org/h2/test/server/TestWeb.java
浏览文件 @
158b3d44
...
...
@@ -55,6 +55,14 @@ public class TestWeb extends TestBase {
result
=
client
.
get
(
url
,
"getHistory.do?id=4"
);
checkContains
(
result
,
"select * from test"
);
result
=
client
.
get
(
url
,
"autoCompleteList.do?query=se"
);
// long time = System.currentTimeMillis();
// for (int i=0; i<1000; i++) {
// if(System.currentTimeMillis()-time > 15000) {
// break;
// }
// result = client.get(url, "autoCompleteList.do?query=select * from ");
checkContains
(
result
,
"select"
);
checkContains
(
result
,
"set"
);
result
=
client
.
get
(
url
,
"tables.do"
);
...
...
h2/src/test/org/h2/test/todo/
autoUpgrade
.txt
→
h2/src/test/org/h2/test/todo/
todo
.txt
浏览文件 @
158b3d44
Auto Upgrade
-----------------
file conversion should be done automatically when the new engine connects.
auto-upgrade application:
...
...
@@ -12,3 +14,20 @@ install new version
ftp client
task to download new version from another HTTP / HTTPS / FTP server
multi-task
Direct Lookup
-----------------
drop table test;
create table test(id int, version int, idx int);
@LOOP 1000 insert into test values(1, 1, ?);
@LOOP 1000 insert into test values(1, 2, ?);
@LOOP 1000 insert into test values(2, 1, ?);
create index idx_test on test(id, version, idx);
@LOOP 1000 select max(id)+1 from test;
@LOOP 1000 select max(idx)+1 from test where id=1 and version=2;
@LOOP 1000 select max(id)+1 from test;
@LOOP 1000 select max(idx)+1 from test where id=1 and version=2;
@LOOP 1000 select max(id)+1 from test;
@LOOP 1000 select max(idx)+1 from test where id=1 and version=2;
-- should be direct query
h2/src/test/org/h2/test/unit/TestFileSystem.java
浏览文件 @
158b3d44
...
...
@@ -26,6 +26,7 @@ import org.h2.test.TestBase;
public
class
TestFileSystem
extends
TestBase
{
public
void
test
()
throws
Exception
{
testDatabaseInMemFileSys
();
testDatabaseInJar
();
testFileSystem
(
baseDir
+
"/fs"
);
testFileSystem
(
FileSystem
.
MEMORY_PREFIX
);
...
...
@@ -34,6 +35,20 @@ public class TestFileSystem extends TestBase {
testFileSystem
(
FileSystem
.
MEMORY_PREFIX_LZF
);
testUserHome
();
}
private
void
testDatabaseInMemFileSys
()
throws
Exception
{
Class
.
forName
(
"org.h2.Driver"
);
String
url
=
"jdbc:h2:"
+
baseDir
+
"/fsMem"
;
Connection
conn
=
DriverManager
.
getConnection
(
url
,
"sa"
,
"sa"
);
conn
.
createStatement
().
execute
(
"CREATE TABLE TEST AS SELECT * FROM DUAL"
);
conn
.
createStatement
().
execute
(
"BACKUP TO '"
+
baseDir
+
"/fsMem.zip'"
);
conn
.
close
();
org
.
h2
.
tools
.
Restore
.
main
(
new
String
[]{
"-file"
,
baseDir
+
"/fsMem.zip"
,
"-dir"
,
"memFS:"
});
conn
=
DriverManager
.
getConnection
(
"jdbc:h2:memFS:fsMem"
,
"sa"
,
"sa"
);
ResultSet
rs
=
conn
.
createStatement
().
executeQuery
(
"SELECT * FROM TEST"
);
rs
.
close
();
conn
.
close
();
}
private
void
testDatabaseInJar
()
throws
Exception
{
if
(
config
.
networked
)
{
...
...
h2/src/tools/org/h2/build/doclet/Doclet.java
浏览文件 @
158b3d44
...
...
@@ -59,8 +59,9 @@ public class Doclet {
return
true
;
}
private
static
String
getClass
(
String
name
)
{
if
(
name
.
startsWith
(
"Jdbc"
))
{
private
static
String
getClass
(
ClassDoc
clazz
)
{
String
name
=
clazz
.
name
();
if
(
clazz
.
qualifiedName
().
indexOf
(
".jdbc."
)
>
0
&&
name
.
startsWith
(
"Jdbc"
))
{
return
name
.
substring
(
4
);
}
return
name
;
...
...
@@ -71,7 +72,7 @@ public class Doclet {
String
dir
=
destDir
+
"/"
+
packageName
.
replace
(
'.'
,
'/'
);
(
new
File
(
dir
)).
mkdirs
();
String
fileName
=
dir
+
"/"
+
clazz
.
name
()
+
".html"
;
String
className
=
getClass
(
clazz
.
name
()
);
String
className
=
getClass
(
clazz
);
FileWriter
out
=
new
FileWriter
(
fileName
);
PrintWriter
writer
=
new
PrintWriter
(
new
BufferedWriter
(
out
));
writer
.
println
(
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
+
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论