Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
26414c8e
提交
26414c8e
authored
4月 03, 2008
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
--no commit message
--no commit message
上级
07470668
显示空白字符变更
内嵌
并排
正在显示
18 个修改的文件
包含
197 行增加
和
147 行删除
+197
-147
ScriptBase.java
h2/src/main/org/h2/command/dml/ScriptBase.java
+2
-2
SysProperties.java
h2/src/main/org/h2/constant/SysProperties.java
+18
-0
Constants.java
h2/src/main/org/h2/engine/Constants.java
+0
-7
Database.java
h2/src/main/org/h2/engine/Database.java
+5
-33
Engine.java
h2/src/main/org/h2/engine/Engine.java
+56
-8
Session.java
h2/src/main/org/h2/engine/Session.java
+4
-1
User.java
h2/src/main/org/h2/engine/User.java
+4
-17
Aggregate.java
h2/src/main/org/h2/expression/Aggregate.java
+2
-2
BaseIndex.java
h2/src/main/org/h2/index/BaseIndex.java
+4
-3
BtreeCursor.java
h2/src/main/org/h2/index/BtreeCursor.java
+3
-1
BtreeIndex.java
h2/src/main/org/h2/index/BtreeIndex.java
+2
-2
MultiVersionCursor.java
h2/src/main/org/h2/index/MultiVersionCursor.java
+25
-24
MultiVersionIndex.java
h2/src/main/org/h2/index/MultiVersionIndex.java
+32
-33
ScanIndex.java
h2/src/main/org/h2/index/ScanIndex.java
+1
-1
TreeIndex.java
h2/src/main/org/h2/index/TreeIndex.java
+4
-4
RowList.java
h2/src/main/org/h2/result/RowList.java
+1
-1
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+32
-7
dictionary.txt
h2/src/tools/org/h2/build/doc/dictionary.txt
+2
-1
没有找到文件。
h2/src/main/org/h2/command/dml/ScriptBase.java
浏览文件 @
26414c8e
...
...
@@ -79,8 +79,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
}
protected
String
getFileName
()
throws
SQLException
{
if
(
file
Name
!
=
null
)
{
fileName
=
file
==
null
?
null
:
file
.
getValue
(
session
).
getString
();
if
(
file
!=
null
&&
fileName
=
=
null
)
{
fileName
=
file
.
getValue
(
session
).
getString
();
if
(
fileName
==
null
||
fileName
.
trim
().
length
()
==
0
)
{
fileName
=
"script.sql"
;
}
...
...
h2/src/main/org/h2/constant/SysProperties.java
浏览文件 @
26414c8e
...
...
@@ -158,6 +158,24 @@ public class SysProperties {
*/
public
static
final
int
DEFAULT_LOCK_MODE
=
getIntSetting
(
"h2.defaultLockMode"
,
Constants
.
LOCK_MODE_READ_COMMITTED
);
/**
* System property <code>h2.delayWrongPasswordMin</code> (default: 200).<br />
* The minimum delay in milliseconds before an exception is thrown for using
* the wrong user name or password. This slows down brute force attacks. The
* delay is reset to this value after a successful login. Unsuccessful
* logins will double the time until DELAY_WRONG_PASSWORD_MAX.
*/
public
static
final
int
DELAY_WRONG_PASSWORD_MIN
=
getIntSetting
(
"h2.delayWrongPasswordMin"
,
200
);
/**
* System property <code>h2.delayWrongPasswordMax</code> (default: 0).<br />
* The maximum delay in milliseconds before an exception is thrown for using
* the wrong user name or password. This slows down brute force attacks. The
* delay is reset after a successful login. The value 0 means there is no
* maximum delay.
*/
public
static
final
int
DELAY_WRONG_PASSWORD_MAX
=
getIntSetting
(
"h2.delayWrongPasswordMax"
,
0
);
/**
* System property <code>h2.emergencySpaceInitial</code> (default: 262144).<br />
* Size of 'reserve' file to detect disk full problems early.
...
...
h2/src/main/org/h2/engine/Constants.java
浏览文件 @
26414c8e
...
...
@@ -191,11 +191,4 @@ public class Constants {
public
static
final
String
SCRIPT_SQL
=
"script.sql"
;
public
static
final
int
CACHE_MIN_RECORDS
=
16
;
/**
* The delay in milliseconds before an exception about
* a wrong user or password is thrown.
* This slows down dictionary attacks.
* An attacker can still open multiple connections.
*/
public
static
final
long
DELAY_WRONG_PASSWORD
=
200
;
}
h2/src/main/org/h2/engine/Database.java
浏览文件 @
26414c8e
...
...
@@ -396,15 +396,8 @@ public class Database implements DataHandler {
return
store
;
}
public
void
checkFilePasswordHash
(
String
c
,
byte
[]
hash
)
throws
SQLException
{
if
(!
ByteUtils
.
compareSecure
(
hash
,
filePasswordHash
)
||
!
StringUtils
.
equals
(
c
,
cipher
))
{
try
{
Thread
.
sleep
(
Constants
.
DELAY_WRONG_PASSWORD
);
}
catch
(
InterruptedException
e
)
{
// ignore
}
throw
Message
.
getSQLException
(
ErrorCode
.
WRONG_USER_OR_PASSWORD
);
}
public
boolean
validateFilePasswordHash
(
String
c
,
byte
[]
hash
)
throws
SQLException
{
return
ByteUtils
.
compareSecure
(
hash
,
filePasswordHash
)
&&
StringUtils
.
equals
(
c
,
cipher
);
}
private
void
openFileData
()
throws
SQLException
{
...
...
@@ -789,35 +782,14 @@ public class Database implements DataHandler {
return
(
UserDataType
)
userDataTypes
.
get
(
name
);
}
/**
* Get the user with the given name. If there is no such user, this method
* waits a short amount of time (to make rainbow table attacks harder) and
* then throws the exception that is passed. There is only one exception
* both for wrong user and for wrong password, to make it harder to get the
* list of user names.
*
* @param name the user name
* @param notFound the exception that should be thrown if the user does not
* exist
* @throws SQLException if the user does not exist
*/
public
User
getUser
(
String
name
,
SQLException
notFound
)
throws
SQLException
{
User
user
=
(
User
)
users
.
get
(
name
);
public
User
getUser
(
String
name
)
throws
SQLException
{
User
user
=
findUser
(
name
);
if
(
user
==
null
)
{
try
{
Thread
.
sleep
(
Constants
.
DELAY_WRONG_PASSWORD
);
}
catch
(
InterruptedException
e
)
{
// ignore
}
throw
notFound
;
throw
Message
.
getSQLException
(
ErrorCode
.
USER_NOT_FOUND_1
,
name
);
}
return
user
;
}
public
User
getUser
(
String
name
)
throws
SQLException
{
return
getUser
(
name
,
Message
.
getSQLException
(
ErrorCode
.
USER_NOT_FOUND_1
,
name
));
}
public
synchronized
Session
createUserSession
(
User
user
)
throws
SQLException
{
if
(
exclusiveSession
!=
null
)
{
throw
Message
.
getSQLException
(
ErrorCode
.
DATABASE_IS_IN_EXCLUSIVE_MODE
);
...
...
h2/src/main/org/h2/engine/Engine.java
浏览文件 @
26414c8e
...
...
@@ -12,8 +12,10 @@ import org.h2.command.CommandInterface;
import
org.h2.command.Parser
;
import
org.h2.command.dml.SetTypes
;
import
org.h2.constant.ErrorCode
;
import
org.h2.constant.SysProperties
;
import
org.h2.message.Message
;
import
org.h2.message.Trace
;
import
org.h2.util.RandomUtils
;
import
org.h2.util.StringUtils
;
/**
...
...
@@ -22,10 +24,9 @@ import org.h2.util.StringUtils;
* This is a singleton class.
*/
public
class
Engine
{
// TODO use a 'engine'/'master' database to allow shut down the server,
// view & kill sessions and so on
private
static
final
Engine
INSTANCE
=
new
Engine
();
private
static
long
delayWrongPassword
=
SysProperties
.
DELAY_WRONG_PASSWORD_MIN
;
private
final
HashMap
databases
=
new
HashMap
();
private
Engine
()
{
...
...
@@ -73,12 +74,16 @@ public class Engine {
}
if
(
user
==
null
)
{
try
{
database
.
checkFilePasswordHash
(
cipher
,
ci
.
getFilePasswordHash
());
// create the exception here so it is not possible from the stack trace
// to see if the user name was wrong or the password
SQLException
wrongUserOrPassword
=
Message
.
getSQLException
(
ErrorCode
.
WRONG_USER_OR_PASSWORD
);
user
=
database
.
getUser
(
ci
.
getUserName
(),
wrongUserOrPassword
);
user
.
checkUserPasswordHash
(
ci
.
getUserPasswordHash
(),
wrongUserOrPassword
);
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
());
}
}
validateUserAndPassword
(
correct
);
if
(
opened
&&
!
user
.
getAdmin
())
{
// reset - because the user is not an admin, and has no
// right to listen to exceptions
...
...
@@ -158,4 +163,47 @@ public class Engine {
databases
.
remove
(
name
);
}
/**
* This method is called after validating user name and password. If user
* name and password were correct, the sleep time is reset, otherwise this
* method waits some time (to make brute force / rainbow table attacks
* harder) and then throws a 'wrong user or password' exception. The delay
* is a bit randomized to protect against timing attacks. Also the delay
* doubles after each unsuccessful logins, to make brute force attacks harder.
*
* There is only one exception both for wrong user and for wrong password,
* to make it harder to get the list of user names. This method must only be
* called from one place, so it is not possible from the stack trace to see
* if the user name was wrong or the password.
*
* @param correct if the user name or the password was correct
* @throws SQLException the exception 'wrong user or password'
*/
public
static
synchronized
void
validateUserAndPassword
(
boolean
correct
)
throws
SQLException
{
int
min
=
SysProperties
.
DELAY_WRONG_PASSWORD_MIN
;
if
(
correct
)
{
delayWrongPassword
=
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
}
}
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
浏览文件 @
26414c8e
...
...
@@ -659,7 +659,10 @@ public class Session implements SessionInterface {
return
database
;
}
public
void
unlinkAtCommit
(
Value
v
)
{
public
void
unlinkAtCommit
(
ValueLob
v
)
{
if
(
SysProperties
.
CHECK
&&
!
v
.
isLinked
())
{
throw
Message
.
getInternalError
();
}
if
(
unlinkMap
==
null
)
{
unlinkMap
=
new
HashMap
();
}
...
...
h2/src/main/org/h2/engine/User.java
浏览文件 @
26414c8e
...
...
@@ -149,28 +149,15 @@ public class User extends RightOwner {
}
/**
* Check the password of this user. If the password is wrong, this method
* waits a short amount of time (to make S attacks harder) and then throws
* the exception that is passed. There is only one exception both for wrong
* user and for wrong password, to make it harder to get the list of user
* names.
* Check the password of this user.
*
* @param userPasswordHash the password data (the user password hash)
* @param onError the exception that should be thrown if the password does
* not match
* @throws SQLException if the password does not match
* @return true if the user password hash is correct
*/
public
void
checkUserPasswordHash
(
byte
[]
userPasswordHash
,
SQLException
onError
)
throws
SQLException
{
public
boolean
validateUserPasswordHash
(
byte
[]
userPasswordHash
)
{
SHA256
sha
=
new
SHA256
();
byte
[]
hash
=
sha
.
getHashWithSalt
(
userPasswordHash
,
salt
);
if
(!
ByteUtils
.
compareSecure
(
hash
,
passwordHash
))
{
try
{
Thread
.
sleep
(
Constants
.
DELAY_WRONG_PASSWORD
);
}
catch
(
InterruptedException
e
)
{
// ignore
}
throw
onError
;
}
return
ByteUtils
.
compareSecure
(
hash
,
passwordHash
);
}
/**
...
...
h2/src/main/org/h2/expression/Aggregate.java
浏览文件 @
26414c8e
...
...
@@ -169,11 +169,11 @@ public class Aggregate extends Expression {
first
=
!
first
;
}
Cursor
cursor
=
index
.
findFirstOrLast
(
session
,
first
);
SearchRow
row
=
cursor
.
getSearchRow
();
Value
v
;
if
(
cursor
==
null
)
{
if
(
row
==
null
)
{
v
=
ValueNull
.
INSTANCE
;
}
else
{
SearchRow
row
=
cursor
.
getSearchRow
();
v
=
row
.
getValue
(
index
.
getColumns
()[
0
].
getColumnId
());
}
return
v
;
...
...
h2/src/main/org/h2/index/BaseIndex.java
浏览文件 @
26414c8e
...
...
@@ -115,11 +115,12 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
public
abstract
boolean
canGetFirstOrLast
();
/**
* Find the first (or last) value of this index.
* Find the first (or last) value of this index. The cursor returned is
* positioned on the correct row, or on null if no row has been found.
*
* @param session the session
* @param first true for the first value, false for the last
* @return a cursor
or null
* @return a cursor
(never null)
*/
public
abstract
Cursor
findFirstOrLast
(
Session
session
,
boolean
first
)
throws
SQLException
;
...
...
h2/src/main/org/h2/index/BtreeCursor.java
浏览文件 @
26414c8e
...
...
@@ -92,7 +92,9 @@ public class BtreeCursor implements Cursor {
}
public
boolean
previous
()
throws
SQLException
{
if
(
currentSearchRow
!=
null
)
{
top
.
page
.
previous
(
this
,
top
.
position
);
}
return
currentSearchRow
!=
null
;
}
...
...
h2/src/main/org/h2/index/BtreeIndex.java
浏览文件 @
26414c8e
...
...
@@ -345,7 +345,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
return
cursor
;
}
}
return
null
;
return
cursor
;
}
else
{
BtreePage
root
=
getRoot
(
session
);
BtreeCursor
cursor
=
new
BtreeCursor
(
session
,
this
,
null
);
...
...
@@ -361,7 +361,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
return
cursor
;
}
}
while
(
cursor
.
previous
());
return
null
;
return
cursor
;
}
}
...
...
h2/src/main/org/h2/index/MultiVersionCursor.java
浏览文件 @
26414c8e
...
...
@@ -26,6 +26,7 @@ public class MultiVersionCursor implements Cursor {
private
boolean
onBase
;
private
boolean
end
;
private
boolean
needNewDelta
,
needNewBase
;
private
boolean
reverse
;
MultiVersionCursor
(
Session
session
,
MultiVersionIndex
index
,
Cursor
base
,
Cursor
delta
,
Object
sync
)
throws
SQLException
{
this
.
session
=
session
;
...
...
@@ -36,34 +37,25 @@ public class MultiVersionCursor implements Cursor {
needNewDelta
=
needNewBase
=
true
;
}
private
void
loadNext
(
boolean
base
)
throws
SQLException
{
void
loadCurrent
(
)
throws
SQLException
{
synchronized
(
sync
)
{
if
(
base
)
{
if
(
baseCursor
.
next
())
{
baseRow
=
baseCursor
.
getSearchRow
();
}
else
{
baseRow
=
null
;
}
}
else
{
if
(
deltaCursor
.
next
())
{
deltaRow
=
deltaCursor
.
get
();
}
else
{
deltaRow
=
null
;
}
}
needNewDelta
=
false
;
needNewBase
=
false
;
}
}
private
void
load
Previous
(
boolean
base
)
throws
SQLException
{
private
void
load
Next
(
boolean
base
)
throws
SQLException
{
synchronized
(
sync
)
{
if
(
base
)
{
if
(
baseCursor
.
previous
(
))
{
if
(
step
(
baseCursor
))
{
baseRow
=
baseCursor
.
getSearchRow
();
}
else
{
baseRow
=
null
;
}
}
else
{
if
(
deltaCursor
.
previous
(
))
{
if
(
step
(
deltaCursor
))
{
deltaRow
=
deltaCursor
.
get
();
}
else
{
deltaRow
=
null
;
...
...
@@ -72,10 +64,14 @@ public class MultiVersionCursor implements Cursor {
}
}
private
boolean
step
(
Cursor
cursor
)
throws
SQLException
{
return
reverse
?
cursor
.
previous
()
:
cursor
.
next
();
}
public
Row
get
()
throws
SQLException
{
synchronized
(
sync
)
{
if
(
SysProperties
.
CHECK
&&
end
)
{
throw
Message
.
getInternalError
()
;
if
(
end
)
{
return
null
;
}
return
onBase
?
baseCursor
.
get
()
:
deltaCursor
.
get
();
}
...
...
@@ -92,8 +88,8 @@ public class MultiVersionCursor implements Cursor {
public
SearchRow
getSearchRow
()
throws
SQLException
{
synchronized
(
sync
)
{
if
(
SysProperties
.
CHECK
&&
end
)
{
throw
Message
.
getInternalError
()
;
if
(
end
)
{
return
null
;
}
return
onBase
?
baseCursor
.
getSearchRow
()
:
deltaCursor
.
getSearchRow
();
}
...
...
@@ -186,8 +182,13 @@ public class MultiVersionCursor implements Cursor {
}
}
public
boolean
previous
()
{
throw
Message
.
getInternalError
();
public
boolean
previous
()
throws
SQLException
{
reverse
=
true
;
try
{
return
next
();
}
finally
{
reverse
=
false
;
}
}
}
h2/src/main/org/h2/index/MultiVersionIndex.java
浏览文件 @
26414c8e
...
...
@@ -31,6 +31,7 @@ public class MultiVersionIndex implements Index {
private
final
TreeIndex
delta
;
private
final
TableData
table
;
private
final
Object
sync
;
private
final
Column
firstColumn
;
public
MultiVersionIndex
(
Index
base
,
TableData
table
)
throws
SQLException
{
this
.
base
=
base
;
...
...
@@ -38,6 +39,7 @@ public class MultiVersionIndex implements Index {
IndexType
deltaIndexType
=
IndexType
.
createNonUnique
(
false
);
this
.
delta
=
new
TreeIndex
(
table
,
-
1
,
"DELTA"
,
base
.
getIndexColumns
(),
deltaIndexType
);
this
.
sync
=
base
.
getDatabase
();
this
.
firstColumn
=
base
.
getColumns
()[
0
];
}
public
void
add
(
Session
session
,
Row
row
)
throws
SQLException
{
...
...
@@ -76,42 +78,39 @@ public class MultiVersionIndex implements Index {
}
public
boolean
canGetFirstOrLast
()
{
// TODO in many cases possible, but more complicated
return
false
;
return
base
.
canGetFirstOrLast
()
&&
delta
.
canGetFirstOrLast
();
}
public
Cursor
findFirstOrLast
(
Session
session
,
boolean
first
)
throws
SQLException
{
int
test
;
throw
Message
.
getUnsupportedException
();
// if (first) {
// // TODO optimization: this loops through NULL elements
// Cursor cursor = find(session, null, false, null);
// while (cursor.next()) {
// SearchRow row = cursor.getSearchRow();
// Value v = row.getValue(columnIds[0]);
// if (v != ValueNull.INSTANCE) {
// return cursor;
// }
// }
// return null;
// } else {
// BtreePage root = getRoot(session);
// BtreeCursor cursor = new BtreeCursor(session, this, null);
// root.last(cursor);
// // TODO optimization: this loops through NULL elements
// do {
// SearchRow row = cursor.getSearchRow();
// if (row == null) {
// break;
// }
// Value v = row.getValue(columnIds[0]);
// if (v != ValueNull.INSTANCE) {
// return cursor;
// }
// } while (cursor.previous());
// return null;
// }
if
(
first
)
{
// TODO optimization: this loops through NULL elements
Cursor
cursor
=
find
(
session
,
null
,
null
);
while
(
cursor
.
next
())
{
SearchRow
row
=
cursor
.
getSearchRow
();
Value
v
=
row
.
getValue
(
firstColumn
.
getColumnId
());
if
(
v
!=
ValueNull
.
INSTANCE
)
{
return
cursor
;
}
}
return
cursor
;
}
else
{
Cursor
baseCursor
=
base
.
findFirstOrLast
(
session
,
false
);
Cursor
deltaCursor
=
delta
.
findFirstOrLast
(
session
,
false
);
MultiVersionCursor
cursor
=
new
MultiVersionCursor
(
session
,
this
,
baseCursor
,
deltaCursor
,
sync
);
cursor
.
loadCurrent
();
// TODO optimization: this loops through NULL elements
while
(
cursor
.
previous
())
{
SearchRow
row
=
cursor
.
getSearchRow
();
if
(
row
==
null
)
{
break
;
}
Value
v
=
row
.
getValue
(
firstColumn
.
getColumnId
());
if
(
v
!=
ValueNull
.
INSTANCE
)
{
return
cursor
;
}
}
return
cursor
;
}
}
public
double
getCost
(
Session
session
,
int
[]
masks
)
throws
SQLException
{
...
...
h2/src/main/org/h2/index/ScanIndex.java
浏览文件 @
26414c8e
...
...
@@ -166,7 +166,7 @@ public class ScanIndex extends BaseIndex {
for
(
int
i
=
0
;
i
<
row
.
getColumnCount
();
i
++)
{
Value
v
=
row
.
getValue
(
i
);
if
(
v
.
isLinked
())
{
session
.
unlinkAtCommit
(
v
);
session
.
unlinkAtCommit
(
(
ValueLob
)
v
);
}
}
}
...
...
h2/src/main/org/h2/index/TreeIndex.java
浏览文件 @
26414c8e
...
...
@@ -382,7 +382,7 @@ public class TreeIndex extends BaseIndex {
return
cursor
;
}
}
return
null
;
return
cursor
;
}
else
{
TreeNode
x
=
root
,
n
;
while
(
x
!=
null
)
{
...
...
@@ -392,10 +392,10 @@ public class TreeIndex extends BaseIndex {
}
x
=
n
;
}
TreeCursor
cursor
=
new
TreeCursor
(
this
,
x
,
null
,
null
);
if
(
x
==
null
)
{
return
null
;
return
cursor
;
}
TreeCursor
cursor
=
new
TreeCursor
(
this
,
x
,
null
,
null
);
// TODO optimization: this loops through NULL elements
do
{
SearchRow
row
=
cursor
.
getSearchRow
();
...
...
@@ -407,7 +407,7 @@ public class TreeIndex extends BaseIndex {
return
cursor
;
}
}
while
(
cursor
.
previous
());
return
null
;
return
cursor
;
}
}
...
...
h2/src/main/org/h2/result/RowList.java
浏览文件 @
26414c8e
...
...
@@ -157,7 +157,7 @@ public class RowList {
// the table id is 0 if it was linked when writing
// a temporary entry
if
(
lob
.
getTableId
()
==
0
)
{
session
.
unlinkAtCommit
(
v
);
session
.
unlinkAtCommit
(
lob
);
}
}
values
[
i
]
=
v
;
...
...
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
26414c8e
...
...
@@ -159,15 +159,42 @@ java org.h2.test.TestAll timer
/*
test # in h2 console (other languages)
delay on wrong password: double the time, randomized, reset on right password
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;
drop table test;
create table test(id int);
select * from test t1 inner join test t2
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
make everything translatable
Derby doesn't optimize it
drop table test;
create table test(id int, version int, idx int);
...
...
@@ -183,10 +210,6 @@ create index idx_test on test(id, version, idx);
@LOOP 1000 select max(idx)+1 from test where id=1 and version=2;
-- should be direct query
Fix ScriptBase.getFileName()
Fix Shell.java 159 (close PreparedStatement)
Browser problems:
There has been a reported incompatibility with the
RealPlayer Browser Record Plugin 1.0 when using Firefox 2.0 and Vista
...
...
@@ -240,6 +263,7 @@ 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.
Roadmap:
...
...
@@ -441,6 +465,7 @@ Roadmap:
* Run all tests with the current settings.
*/
private
void
test
()
throws
Exception
{
System
.
out
.
println
();
System
.
out
.
println
(
"Test big:"
+
big
+
" net:"
+
networked
+
" cipher:"
+
cipher
+
" memory:"
+
memory
+
" log:"
+
logMode
+
" diskResult:"
+
diskResult
+
" mvcc:"
+
mvcc
+
" deleteIndex:"
+
deleteIndex
);
beforeTest
();
...
...
h2/src/tools/org/h2/build/doc/dictionary.txt
浏览文件 @
26414c8e
...
...
@@ -488,4 +488,5 @@ greenwich sqli informix pointbase fbj pervasive jtds ifx syb mimer sybase
frontbase intersys maxwidth belonging learning mono typical toggle winexe
hider ikvmc invert recycle filtering lesser recycled assertion runner teradata
christian lgpl elapsed ncr disposed heureuse tera years retrieves unlocked
selecting vista everywhere locations zones fragment svg thought
\ No newline at end of file
selecting vista everywhere locations zones fragment svg thought constructors
doubles validating
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论