Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
e0e2869b
提交
e0e2869b
authored
12月 16, 2007
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
--no commit message
--no commit message
上级
488ecc5e
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
20 个修改的文件
包含
895 行增加
和
368 行删除
+895
-368
Command.java
h2/src/main/org/h2/command/Command.java
+5
-3
Parser.java
h2/src/main/org/h2/command/Parser.java
+6
-0
SelectUnion.java
h2/src/main/org/h2/command/dml/SelectUnion.java
+2
-5
Set.java
h2/src/main/org/h2/command/dml/Set.java
+6
-0
SetTypes.java
h2/src/main/org/h2/command/dml/SetTypes.java
+3
-2
ErrorCode.java
h2/src/main/org/h2/constant/ErrorCode.java
+1
-0
Database.java
h2/src/main/org/h2/engine/Database.java
+20
-3
Session.java
h2/src/main/org/h2/engine/Session.java
+26
-7
Function.java
h2/src/main/org/h2/expression/Function.java
+464
-303
BtreeIndex.java
h2/src/main/org/h2/index/BtreeIndex.java
+0
-2
_messages_en.properties
h2/src/main/org/h2/res/_messages_en.properties
+1
-0
help.csv
h2/src/main/org/h2/res/help.csv
+25
-0
FtpControl.java
h2/src/main/org/h2/server/ftp/FtpControl.java
+1
-0
WebServer.java
h2/src/main/org/h2/server/web/WebServer.java
+7
-0
WebThread.java
h2/src/main/org/h2/server/web/WebThread.java
+130
-5
table.js
h2/src/main/org/h2/server/web/res/table.js
+34
-5
MetaTable.java
h2/src/main/org/h2/table/MetaTable.java
+9
-4
Server.java
h2/src/main/org/h2/tools/Server.java
+29
-27
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+11
-2
TestSessionsLocks.java
h2/src/test/org/h2/test/db/TestSessionsLocks.java
+115
-0
没有找到文件。
h2/src/main/org/h2/command/Command.java
浏览文件 @
e0e2869b
...
...
@@ -64,10 +64,11 @@ public abstract class Command implements CommandInterface {
startTime
=
System
.
currentTimeMillis
();
Database
database
=
session
.
getDatabase
();
Object
sync
=
database
.
getMultiThreaded
()
?
(
Object
)
session
:
(
Object
)
database
;
session
.
waitIfExclusiveModeEnabled
();
synchronized
(
sync
)
{
try
{
database
.
checkPowerOff
();
session
.
setCurrentCommand
(
this
);
session
.
setCurrentCommand
(
this
,
startTime
);
return
query
(
maxrows
);
}
catch
(
Throwable
e
)
{
SQLException
s
=
Message
.
convert
(
e
);
...
...
@@ -92,7 +93,7 @@ public abstract class Command implements CommandInterface {
}
private
void
stop
()
throws
SQLException
{
session
.
setCurrentCommand
(
null
);
session
.
setCurrentCommand
(
null
,
0
);
if
(!
isTransactional
())
{
session
.
commit
(
true
);
}
else
if
(
session
.
getAutoCommit
())
{
...
...
@@ -115,9 +116,10 @@ public abstract class Command implements CommandInterface {
startTime
=
System
.
currentTimeMillis
();
Database
database
=
session
.
getDatabase
();
Object
sync
=
database
.
getMultiThreaded
()
?
(
Object
)
session
:
(
Object
)
database
;
session
.
waitIfExclusiveModeEnabled
();
synchronized
(
sync
)
{
int
rollback
=
session
.
getLogId
();
session
.
setCurrentCommand
(
this
);
session
.
setCurrentCommand
(
this
,
startTime
);
try
{
database
.
checkPowerOff
();
return
update
();
...
...
h2/src/main/org/h2/command/Parser.java
浏览文件 @
e0e2869b
...
...
@@ -3656,6 +3656,12 @@ public class Parser {
Set
command
=
new
Set
(
session
,
SetTypes
.
MVCC
);
command
.
setInt
(
value
?
1
:
0
);
return
command
;
}
else
if
(
readIf
(
"EXCLUSIVE"
))
{
readIfEqualOrTo
();
boolean
value
=
readBooleanSetting
();
Set
command
=
new
Set
(
session
,
SetTypes
.
EXCLUSIVE
);
command
.
setInt
(
value
?
1
:
0
);
return
command
;
}
else
if
(
readIf
(
"IGNORECASE"
))
{
readIfEqualOrTo
();
boolean
value
=
readBooleanSetting
();
...
...
h2/src/main/org/h2/command/dml/SelectUnion.java
浏览文件 @
e0e2869b
...
...
@@ -94,20 +94,17 @@ public class SelectUnion extends Query {
}
switch
(
unionType
)
{
case
UNION:
case
EXCEPT:
left
.
setDistinct
(
true
);
right
.
setDistinct
(
true
);
result
.
setDistinct
();
break
;
case
UNION_ALL:
break
;
case
EXCEPT:
result
.
setDistinct
();
// fall through
case
INTERSECT:
{
case
INTERSECT:
left
.
setDistinct
(
true
);
right
.
setDistinct
(
true
);
break
;
}
default
:
throw
Message
.
getInternalError
(
"type="
+
unionType
);
}
...
...
h2/src/main/org/h2/command/dml/Set.java
浏览文件 @
e0e2869b
...
...
@@ -274,6 +274,12 @@ public class Set extends Prepared {
database
.
setMaxOperationMemory
(
value
);
break
;
}
case
SetTypes
.
EXCLUSIVE
:
{
session
.
getUser
().
checkAdmin
();
int
value
=
getIntValue
();
database
.
setExclusiveSession
(
value
==
1
?
session
:
null
);
break
;
}
default
:
throw
Message
.
getInternalError
(
"type="
+
type
);
}
...
...
h2/src/main/org/h2/command/dml/SetTypes.java
浏览文件 @
e0e2869b
...
...
@@ -20,10 +20,10 @@ public class SetTypes {
public
static
final
int
LOG
=
19
,
THROTTLE
=
20
,
MAX_MEMORY_UNDO
=
21
,
MAX_LENGTH_INPLACE_LOB
=
22
;
public
static
final
int
COMPRESS_LOB
=
23
,
ALLOW_LITERALS
=
24
,
MULTI_THREADED
=
25
,
SCHEMA
=
26
;
public
static
final
int
OPTIMIZE_REUSE_RESULTS
=
27
,
SCHEMA_SEARCH_PATH
=
28
,
UNDO_LOG
=
29
;
public
static
final
int
REFERENTIAL_INTEGRITY
=
30
,
MVCC
=
31
,
MAX_OPERATION_MEMORY
=
32
;
public
static
final
int
REFERENTIAL_INTEGRITY
=
30
,
MVCC
=
31
,
MAX_OPERATION_MEMORY
=
32
,
EXCLUSIVE
=
33
;
private
static
ObjectArray
types
=
new
ObjectArray
();
static
{
setType
(
IGNORECASE
,
"IGNORECASE"
);
setType
(
MAX_LOG_SIZE
,
"MAX_LOG_SIZE"
);
...
...
@@ -57,6 +57,7 @@ public class SetTypes {
setType
(
REFERENTIAL_INTEGRITY
,
"REFERENTIAL_INTEGRITY"
);
setType
(
MVCC
,
"MVCC"
);
setType
(
MAX_OPERATION_MEMORY
,
"MAX_OPERATION_MEMORY"
);
setType
(
EXCLUSIVE
,
"EXCLUSIVE"
);
}
private
static
void
setType
(
int
type
,
String
name
)
{
...
...
h2/src/main/org/h2/constant/ErrorCode.java
浏览文件 @
e0e2869b
...
...
@@ -315,6 +315,7 @@ public class ErrorCode {
public
static
final
int
AGGREGATE_NOT_FOUND_1
=
90132
;
public
static
final
int
CANNOT_CHANGE_SETTING_WHEN_OPEN_1
=
90133
;
public
static
final
int
ACCESS_DENIED_TO_CLASS_1
=
90134
;
public
static
final
int
DATABASE_IS_IN_EXCLUSIVE_MODE
=
90135
;
/**
* INTERNAL
...
...
h2/src/main/org/h2/engine/Database.java
浏览文件 @
e0e2869b
...
...
@@ -7,9 +7,11 @@ package org.h2.engine;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.sql.SQLException
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.Set
;
import
java.util.StringTokenizer
;
import
org.h2.api.DatabaseEventListener
;
...
...
@@ -85,7 +87,8 @@ public class Database implements DataHandler {
private
final
HashMap
userDataTypes
=
new
HashMap
();
private
final
HashMap
aggregates
=
new
HashMap
();
private
final
HashMap
comments
=
new
HashMap
();
private
final
HashSet
sessions
=
new
HashSet
();
private
final
Set
sessions
=
Collections
.
synchronizedSet
(
new
HashSet
());
private
Session
exclusiveSession
;
private
final
BitField
objectIds
=
new
BitField
();
private
final
Object
lobSyncObject
=
new
Object
();
...
...
@@ -772,7 +775,10 @@ public class Database implements DataHandler {
return
getUser
(
name
,
Message
.
getSQLException
(
ErrorCode
.
USER_NOT_FOUND_1
,
name
));
}
public
synchronized
Session
createSession
(
User
user
)
{
public
synchronized
Session
createSession
(
User
user
)
throws
SQLException
{
if
(
exclusiveSession
!=
null
)
{
throw
Message
.
getSQLException
(
ErrorCode
.
DATABASE_IS_IN_EXCLUSIVE_MODE
);
}
Session
session
=
new
Session
(
this
,
user
,
++
nextSessionId
);
sessions
.
add
(
session
);
traceSystem
.
getTrace
(
Trace
.
SESSION
).
info
(
"connecting #"
+
session
.
getId
()
+
" to "
+
databaseName
);
...
...
@@ -785,6 +791,9 @@ public class Database implements DataHandler {
public
synchronized
void
removeSession
(
Session
session
)
throws
SQLException
{
if
(
session
!=
null
)
{
if
(
exclusiveSession
==
session
)
{
exclusiveSession
=
null
;
}
sessions
.
remove
(
session
);
if
(
session
!=
systemSession
)
{
traceSystem
.
getTrace
(
Trace
.
SESSION
).
info
(
"disconnecting #"
+
session
.
getId
());
...
...
@@ -1032,7 +1041,7 @@ public class Database implements DataHandler {
return
log
;
}
public
synchronized
Session
[]
getSessions
()
{
public
Session
[]
getSessions
()
{
Session
[]
list
=
new
Session
[
sessions
.
size
()];
sessions
.
toArray
(
list
);
return
list
;
...
...
@@ -1624,4 +1633,12 @@ public class Database implements DataHandler {
return
maxOperationMemory
;
}
public
Session
getExclusiveSession
()
{
return
exclusiveSession
;
}
public
void
setExclusiveSession
(
Session
session
)
{
this
.
exclusiveSession
=
session
;
}
}
h2/src/main/org/h2/engine/Session.java
浏览文件 @
e0e2869b
...
...
@@ -73,7 +73,8 @@ public class Session implements SessionInterface {
private
String
currentTransactionName
;
private
boolean
isClosed
;
private
boolean
rollbackMode
;
private
long
loginTime
=
System
.
currentTimeMillis
();
private
long
sessionStart
=
System
.
currentTimeMillis
();
private
long
currentCommandStart
;
public
Session
()
{
}
...
...
@@ -498,8 +499,9 @@ public class Session implements SessionInterface {
}
}
public
void
setCurrentCommand
(
Command
command
)
{
public
void
setCurrentCommand
(
Command
command
,
long
startTime
)
{
this
.
currentCommand
=
command
;
this
.
currentCommandStart
=
startTime
;
}
public
void
checkCancelled
()
throws
SQLException
{
...
...
@@ -508,9 +510,12 @@ public class Session implements SessionInterface {
}
}
public
String
getCurrentCommand
()
{
Command
c
=
currentCommand
;
return
c
==
null
?
null
:
c
.
toString
();
public
Command
getCurrentCommand
()
{
return
currentCommand
;
}
public
long
getCurrentCommandStart
()
{
return
currentCommandStart
;
}
public
boolean
getAllowLiterals
()
{
...
...
@@ -609,8 +614,8 @@ public class Session implements SessionInterface {
return
rollbackMode
;
}
public
long
get
LoginTime
()
{
return
loginTime
;
public
long
get
SessionStart
()
{
return
sessionStart
;
}
public
Table
[]
getLocks
()
{
...
...
@@ -621,4 +626,18 @@ public class Session implements SessionInterface {
}
}
public
void
waitIfExclusiveModeEnabled
()
{
while
(
true
)
{
Session
exclusive
=
database
.
getExclusiveSession
();
if
(
exclusive
==
null
||
exclusive
==
this
)
{
break
;
}
try
{
Thread
.
sleep
(
100
);
}
catch
(
InterruptedException
e
)
{
// ignore
}
}
}
}
h2/src/main/org/h2/expression/Function.java
浏览文件 @
e0e2869b
差异被折叠。
点击展开。
h2/src/main/org/h2/index/BtreeIndex.java
浏览文件 @
e0e2869b
...
...
@@ -57,8 +57,6 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
head
=
(
BtreeHead
)
rec
;
}
if
(
head
!=
null
&&
head
.
getConsistent
())
{
int
testing
;
// setRoot((BtreePage) storage.getRecord(session, head.getRootPosition()));
needRebuild
=
false
;
rowCount
=
table
.
getRowCount
(
session
);
}
else
{
...
...
h2/src/main/org/h2/res/_messages_en.properties
浏览文件 @
e0e2869b
...
...
@@ -155,6 +155,7 @@
90132
=
Aggregate {0} not found
90133
=
Cannot change the setting {0} when the database is already open
90134
=
Access to the class {0} is denied
90135
=
The database is open in exclusive mode; can not open additional connections
HY000
=
General error
\:
{0}
HY004
=
Unknown data type
\:
{0}
HYC00
=
Feature not supported
...
...
h2/src/main/org/h2/res/help.csv
浏览文件 @
e0e2869b
...
...
@@ -856,6 +856,19 @@ Admin rights are required to execute this command.
SET DEFAULT_TABLE_TYPE MEMORY
"
"Commands (Other)","SET EXCLUSIVE","
SET EXCLUSIVE {TRUE | FALSE}
","
Switched the database to exclusive mode and back. In exclusive mode, new connections are rejected,
and operations by other connections are paused until the exclusive mode is disabled.
Only the connection that set the exclusive mode can disable it. When the connection is closed,
it is automatically disabled.
This setting is not persistent.
Admin rights are required to execute this command.
","
SET EXCLUSIVE TRUE
"
"Commands (Other)","SET IGNORECASE","
SET IGNORECASE {TRUE|FALSE}
","
...
...
@@ -2559,6 +2572,18 @@ Returns true if auto commit is switched on for this session.
AUTOCOMMIT()
"
"Functions (System)","CANCEL_SESSION","
CANCEL_SESSION(sessionInt): boolean
","
Cancels the currently executing statement of another session.
The method only works if the multithreaded kernel is enabled (see SET MULTI_THREADED).
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_STATEMENT(3)
"
"Functions (System)","CASEWHEN Function","
CASEWHEN(boolean, aValue, bValue): value
","
...
...
h2/src/main/org/h2/server/ftp/FtpControl.java
浏览文件 @
e0e2869b
...
...
@@ -333,6 +333,7 @@ public class FtpControl extends Thread {
}
else
if
(
"XRMD"
.
equals
(
command
))
{
processRemoveDir
(
param
);
}
break
;
default
:
break
;
}
...
...
h2/src/main/org/h2/server/web/WebServer.java
浏览文件 @
e0e2869b
...
...
@@ -114,6 +114,7 @@ public class WebServer implements Service {
private
ShutdownHandler
shutdownHandler
;
private
Thread
listenerThread
;
private
boolean
ifExists
;
private
boolean
allowScript
;
byte
[]
getFile
(
String
file
)
throws
IOException
{
trace
(
"getFile <"
+
file
+
">"
);
...
...
@@ -196,6 +197,8 @@ public class WebServer implements Service {
ssl
=
Boolean
.
valueOf
(
args
[++
i
]).
booleanValue
();
}
else
if
(
"-webAllowOthers"
.
equals
(
a
))
{
allowOthers
=
Boolean
.
valueOf
(
args
[++
i
]).
booleanValue
();
}
else
if
(
"-webScript"
.
equals
(
a
))
{
allowScript
=
Boolean
.
valueOf
(
args
[++
i
]).
booleanValue
();
}
else
if
(
"-baseDir"
.
equals
(
a
))
{
String
baseDir
=
args
[++
i
];
SysProperties
.
setBaseDir
(
baseDir
);
...
...
@@ -508,4 +511,8 @@ public class WebServer implements Service {
this
.
shutdownHandler
=
shutdownHandler
;
}
public
boolean
getAllowScript
()
{
return
allowScript
;
}
}
h2/src/main/org/h2/server/web/WebThread.java
浏览文件 @
e0e2869b
...
...
@@ -5,13 +5,20 @@
package
org
.
h2
.
server
.
web
;
import
java.io.BufferedOutputStream
;
import
java.io.DataInputStream
;
import
java.io.DataOutputStream
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.PrintWriter
;
import
java.io.StringReader
;
import
java.io.StringWriter
;
import
java.lang.reflect.Method
;
import
java.net.MalformedURLException
;
import
java.net.Socket
;
import
java.security.SecureClassLoader
;
import
java.sql.Connection
;
import
java.sql.DatabaseMetaData
;
import
java.sql.PreparedStatement
;
...
...
@@ -40,12 +47,12 @@ import org.h2.engine.Constants;
import
org.h2.jdbc.JdbcSQLException
;
import
org.h2.message.TraceSystem
;
import
org.h2.tools.SimpleResultSet
;
import
org.h2.util.ObjectUtils
;
import
org.h2.util.JdbcUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.MemoryUtils
;
import
org.h2.util.NetUtils
;
import
org.h2.util.ObjectArray
;
import
org.h2.util.ObjectUtils
;
import
org.h2.util.ScriptReader
;
import
org.h2.util.StringUtils
;
...
...
@@ -1018,7 +1025,17 @@ class WebThread extends Thread implements DatabaseEventListener {
try
{
Connection
conn
=
session
.
getConnection
();
String
result
;
if
(
"@AUTOCOMMIT TRUE"
.
equals
(
sql
))
{
if
(
sql
.
startsWith
(
"@JAVA"
))
{
if
(
server
.
getAllowScript
())
{
try
{
result
=
executeJava
(
sql
.
substring
(
"@JAVA"
.
length
()));
}
catch
(
Throwable
t
)
{
result
=
getStackTrace
(
0
,
t
);
}
}
else
{
result
=
"Executing Java code is not allowed, use command line parameters -webScript true"
;
}
}
else
if
(
"@AUTOCOMMIT TRUE"
.
equals
(
sql
))
{
conn
.
setAutoCommit
(
true
);
result
=
"${text.result.autoCommitOn}"
;
}
else
if
(
"@AUTOCOMMIT FALSE"
.
equals
(
sql
))
{
...
...
@@ -1068,6 +1085,94 @@ class WebThread extends Thread implements DatabaseEventListener {
return
"result.jsp"
;
}
static
class
DynamicClassLoader
extends
SecureClassLoader
{
private
String
name
;
private
byte
[]
data
;
private
Class
clazz
;
DynamicClassLoader
(
String
name
,
byte
[]
data
)
throws
MalformedURLException
{
super
(
DynamicClassLoader
.
class
.
getClassLoader
());
this
.
name
=
name
;
this
.
data
=
data
;
}
public
Class
loadClass
(
String
className
)
throws
ClassNotFoundException
{
return
findClass
(
className
);
}
public
Class
findClass
(
String
className
)
throws
ClassNotFoundException
{
if
(
className
.
equals
(
name
))
{
if
(
clazz
==
null
)
{
clazz
=
defineClass
(
className
,
data
,
0
,
data
.
length
);
}
return
clazz
;
}
try
{
return
findSystemClass
(
className
);
}
catch
(
Exception
e
)
{
}
return
super
.
findClass
(
className
);
}
}
private
String
executeJava
(
String
code
)
throws
Exception
{
File
javaFile
=
new
File
(
"Java.java"
);
File
classFile
=
new
File
(
"Java.class"
);
try
{
PrintWriter
out
=
new
PrintWriter
(
new
FileWriter
(
javaFile
));
classFile
.
delete
();
int
endImport
=
code
.
indexOf
(
"@CODE"
);
String
importCode
=
"import java.util.*; import java.math.*; import java.sql.*;"
;
if
(
endImport
>=
0
)
{
importCode
=
code
.
substring
(
0
,
endImport
);
code
=
code
.
substring
(
"@CODE"
.
length
()
+
endImport
);
}
out
.
println
(
importCode
);
out
.
println
(
"public class Java { public static Object run() throws Throwable {"
+
code
+
"}}"
);
out
.
close
();
Process
p
=
Runtime
.
getRuntime
().
exec
(
"javac Java.java"
);
InputStream
processIn
=
p
.
getInputStream
();
InputStream
processErrorIn
=
p
.
getErrorStream
();
StringBuffer
buff
=
new
StringBuffer
();
while
(
true
)
{
int
c
=
processIn
.
read
();
if
(
c
==
-
1
)
{
break
;
}
buff
.
append
((
char
)
c
);
}
while
(
true
)
{
int
c
=
processErrorIn
.
read
();
if
(
c
==
-
1
)
{
break
;
}
buff
.
append
((
char
)
c
);
}
String
error
=
buff
.
toString
().
trim
();
if
(
error
.
length
()
>
0
)
{
throw
new
Exception
(
"Error compiling: "
+
error
.
toString
());
}
byte
[]
data
=
new
byte
[(
int
)
classFile
.
length
()];
DataInputStream
in
=
new
DataInputStream
(
new
FileInputStream
(
classFile
));
in
.
readFully
(
data
);
in
.
close
();
DynamicClassLoader
cl
=
new
DynamicClassLoader
(
"Java"
,
data
);
Class
clazz
=
cl
.
loadClass
(
"Java"
);
Method
[]
methods
=
clazz
.
getMethods
();
for
(
int
i
=
0
;
i
<
methods
.
length
;
i
++)
{
Method
m
=
methods
[
i
];
if
(
m
.
getName
().
equals
(
"run"
))
{
return
""
+
m
.
invoke
(
null
,
new
Object
[
0
]);
}
}
return
null
;
}
finally
{
javaFile
.
delete
();
classFile
.
delete
();
}
}
private
String
editResult
()
{
ResultSet
rs
=
session
.
result
;
int
row
=
Integer
.
parseInt
(
attributes
.
getProperty
(
"row"
));
...
...
@@ -1083,7 +1188,7 @@ class WebThread extends Thread implements DatabaseEventListener {
}
for
(
int
i
=
0
;
i
<
rs
.
getMetaData
().
getColumnCount
();
i
++)
{
String
x
=
attributes
.
getProperty
(
"r"
+
row
+
"c"
+
(
i
+
1
));
rs
.
updateString
(
i
+
1
,
x
);
rs
.
updateString
(
i
+
1
,
unescapeData
(
x
)
);
}
if
(
insert
)
{
rs
.
insertRow
();
...
...
@@ -1611,7 +1716,7 @@ class WebThread extends Thread implements DatabaseEventListener {
buff
.
append
(
PageParser
.
escapeHtml
(
meta
.
getColumnLabel
(
i
+
1
)));
buff
.
append
(
"</td>"
);
buff
.
append
(
"<td>"
);
buff
.
append
(
PageParser
.
escapeHtml
(
rs
.
getString
(
i
+
1
)));
buff
.
append
(
escapeData
(
rs
.
getString
(
i
+
1
)));
buff
.
append
(
"</td></tr>"
);
}
}
...
...
@@ -1645,7 +1750,7 @@ class WebThread extends Thread implements DatabaseEventListener {
}
for
(
int
i
=
0
;
i
<
columns
;
i
++)
{
buff
.
append
(
"<td>"
);
buff
.
append
(
PageParser
.
escapeHtml
(
rs
.
getString
(
i
+
1
)));
buff
.
append
(
escapeData
(
rs
.
getString
(
i
+
1
)));
buff
.
append
(
"</td>"
);
}
buff
.
append
(
"</tr>"
);
...
...
@@ -1713,6 +1818,26 @@ class WebThread extends Thread implements DatabaseEventListener {
return
"index.do"
;
}
private
String
escapeData
(
String
d
)
{
if
(
d
==
null
)
{
return
"<i>null</i>"
;
}
else
if
(
d
.
startsWith
(
"null"
))
{
return
"<div style='display: none'>=</div>"
+
PageParser
.
escapeHtml
(
d
);
}
return
PageParser
.
escapeHtml
(
d
);
}
private
String
unescapeData
(
String
d
)
{
if
(
d
.
endsWith
(
"null"
))
{
if
(
d
.
equals
(
"null"
))
{
return
null
;
}
else
if
(
d
.
startsWith
(
"="
))
{
return
d
.
substring
(
1
);
}
}
return
d
;
}
private
String
settingRemove
()
{
String
setting
=
attributes
.
getProperty
(
"name"
,
""
);
server
.
removeSetting
(
setting
);
...
...
h2/src/main/org/h2/server/web/res/table.js
浏览文件 @
e0e2869b
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
addEvent
(
window
,
"load"
,
initSort
);
function
addEvent
(
elm
,
evType
,
fn
,
useCapture
)
{
...
...
@@ -26,7 +26,7 @@ function initSort() {
}
var
tables
=
document
.
getElementsByTagName
(
"table"
);
for
(
var
i
=
0
;
i
<
tables
.
length
;
i
++
)
{
table
=
tables
[
i
];
table
=
tables
[
i
];
if
(
table
.
rows
&&
table
.
rows
.
length
>
0
)
{
var
header
=
table
.
rows
[
0
];
for
(
var
j
=
0
;
j
<
header
.
cells
.
length
;
j
++
)
{
...
...
@@ -45,8 +45,8 @@ function editRow(row, session, write, undo) {
for
(
i
=
1
;
i
<
table
.
rows
.
length
;
i
++
)
{
var
cell
=
table
.
rows
[
i
].
cells
[
0
];
if
(
i
==
y
)
{
var
edit
=
'<img width=16 height=16 src="ico_ok.gif" onclick="
javascript:editing.op.value=
\'
1
\'
;editing.row.value=
\'
'
+
row
+
'
\'
;editing.submit(
)" onmouseover = "this.className =
\'
icon_hover
\'
" onmouseout = "this.className=
\'
icon
\'
" class="icon" alt="'
+
write
+
'" title="'
+
write
+
'" border="1"/>'
;
var
undo
=
'<img width=16 height=16 src="ico_undo.gif" onclick="
javascript:editing.op.value=
\'
3
\'
;editing.row.value=
\'
'
+
row
+
'
\'
;editing.submit(
)" onmouseover = "this.className =
\'
icon_hover
\'
" onmouseout = "this.className=
\'
icon
\'
" class="icon" alt="'
+
undo
+
'" title="'
+
undo
+
'" border="1"/>'
;
var
edit
=
'<img width=16 height=16 src="ico_ok.gif" onclick="
editOk('
+
row
+
'
)" onmouseover = "this.className =
\'
icon_hover
\'
" onmouseout = "this.className=
\'
icon
\'
" class="icon" alt="'
+
write
+
'" title="'
+
write
+
'" border="1"/>'
;
var
undo
=
'<img width=16 height=16 src="ico_undo.gif" onclick="
editCancel('
+
row
+
'
)" onmouseover = "this.className =
\'
icon_hover
\'
" onmouseout = "this.className=
\'
icon
\'
" class="icon" alt="'
+
undo
+
'" title="'
+
undo
+
'" border="1"/>'
;
cell
.
innerHTML
=
edit
+
undo
;
}
else
{
cell
.
innerHTML
=
''
;
...
...
@@ -56,10 +56,39 @@ function editRow(row, session, write, undo) {
for
(
i
=
1
;
i
<
cells
.
length
;
i
++
)
{
var
cell
=
cells
[
i
];
var
text
=
getInnerText
(
cell
);
cell
.
innerHTML
=
'<input type="text" name="r'
+
row
+
'c'
+
i
+
'" value="'
+
text
+
'" size="'
+
(
text
.
length
+
5
)
+
'"/>'
;
cell
.
innerHTML
=
'<input type="text" name="r'
+
row
+
'c'
+
i
+
'" value="'
+
text
+
'" size="'
+
(
text
.
length
+
5
)
+
'"
onkeydown="return editKeyDown('
+
row
+
', this, event)"
/>'
;
}
}
function
editCancel
(
row
)
{
var
editing
=
document
.
getElementById
(
'editing'
);
editing
.
row
.
value
=
row
;
editing
.
op
.
value
=
'3'
;
editing
.
submit
();
}
function
editOk
(
row
)
{
var
editing
=
document
.
getElementById
(
'editing'
);
editing
.
row
.
value
=
row
;
editing
.
op
.
value
=
'1'
;
editing
.
submit
();
}
function
editKeyDown
(
row
,
object
,
event
)
{
var
key
=
event
.
keyCode
?
event
.
keyCode
:
event
.
charCode
;
if
(
key
==
46
&&
event
.
ctrlKey
)
{
// ctrl + delete
object
.
value
=
'null'
;
return
false
;
}
else
if
(
key
==
13
)
{
editOk
(
row
);
return
false
;
}
else
if
(
key
==
27
)
{
editCancel
(
row
);
return
false
;
}
}
function
getInnerText
(
el
)
{
if
(
typeof
el
==
"string"
)
return
el
;
if
(
typeof
el
==
"undefined"
)
{
return
el
};
...
...
h2/src/main/org/h2/table/MetaTable.java
浏览文件 @
e0e2869b
...
...
@@ -16,6 +16,7 @@ import java.sql.Timestamp;
import
java.text.Collator
;
import
java.util.Locale
;
import
org.h2.command.Command
;
import
org.h2.constant.SysProperties
;
import
org.h2.constraint.Constraint
;
import
org.h2.constraint.ConstraintCheck
;
...
...
@@ -434,8 +435,9 @@ public class MetaTable extends Table {
cols
=
createColumns
(
new
String
[]{
"ID INT"
,
"USER_NAME"
,
"CURRENT_STATEMENT"
,
"LOGIN_TIME"
,
"SESSION_START"
,
"STATEMENT"
,
"STATEMENT_START"
});
break
;
}
...
...
@@ -707,6 +709,7 @@ public class MetaTable extends Table {
}
}
add
(
rows
,
new
String
[]
{
"MVCC"
,
database
.
isMultiVersion
()
?
"TRUE"
:
"FALSE"
});
add
(
rows
,
new
String
[]
{
"EXCLUSIVE"
,
database
.
getExclusiveSession
()
==
null
?
"FALSE"
:
"TRUE"
});
add
(
rows
,
new
String
[]
{
"MODE"
,
database
.
getMode
().
getName
()
});
add
(
rows
,
new
String
[]
{
"MULTI_THREADED"
,
database
.
getMultiThreaded
()
?
"1"
:
"0"
});
DiskFile
dataFile
=
database
.
getDataFile
();
...
...
@@ -1205,11 +1208,13 @@ public class MetaTable extends Table {
for
(
int
i
=
0
;
i
<
sessions
.
length
;
i
++)
{
Session
s
=
sessions
[
i
];
if
(
admin
||
s
==
session
)
{
Command
command
=
s
.
getCurrentCommand
();
add
(
rows
,
new
String
[]
{
""
+
s
.
getId
(),
// ID
s
.
getUser
().
getName
(),
// USER_NAME
s
.
getCurrentCommand
(),
// CURRENT_COMMAND
new
Timestamp
(
s
.
getLoginTime
()).
toString
(),
// LOGIN_TIME
new
Timestamp
(
s
.
getSessionStart
()).
toString
(),
// SESSION_START
command
==
null
?
null
:
command
.
toString
(),
// STATEMENT
new
Timestamp
(
s
.
getCurrentCommandStart
()).
toString
()
// STATEMENT_START
});
}
}
...
...
h2/src/main/org/h2/tools/Server.java
浏览文件 @
e0e2869b
...
...
@@ -28,12 +28,12 @@ import org.h2.util.StartBrowser;
* This tool can be used to start various database servers (listeners).
*/
public
class
Server
implements
Runnable
,
ShutdownHandler
{
private
Service
service
;
private
static
final
int
EXIT_ERROR
=
1
;
private
Server
web
,
tcp
,
pg
,
ftp
;
private
ShutdownHandler
shutdownHandler
;
private
void
showUsage
(
String
a
,
PrintStream
out
)
{
if
(
a
!=
null
)
{
out
.
println
(
"Unknown option: "
+
a
);
...
...
@@ -53,30 +53,30 @@ public class Server implements Runnable, ShutdownHandler {
out
.
println
(
"-tcp (start the TCP Server)"
);
out
.
println
(
"-tcpAllowOthers {true|false}"
);
out
.
println
(
"-tcpPort <port> (default: "
+
TcpServer
.
DEFAULT_PORT
+
")"
);
out
.
println
(
"-tcpSSL {true|false}"
);
out
.
println
(
"-tcpSSL {true|false}"
);
out
.
println
(
"-tcpPassword {password} (the password for shutting down a TCP Server)"
);
out
.
println
(
"-tcpShutdown {url} (shutdown the TCP Server, URL example: tcp://localhost:9094)"
);
out
.
println
(
"-tcpShutdownForce {true|false} (don't wait for other connections to close)"
);
out
.
println
();
out
.
println
(
"-pg (start the PG Server)"
);
out
.
println
(
"-pgAllowOthers {true|false}"
);
out
.
println
(
"-pgAllowOthers {true|false}"
);
out
.
println
(
"-pgPort <port> (default: "
+
PgServer
.
DEFAULT_PORT
+
")"
);
out
.
println
();
out
.
println
(
"-ftp (start the FTP Server)"
);
out
.
println
(
"-ftpPort <port> (default: "
+
Constants
.
DEFAULT_FTP_PORT
+
")"
);
out
.
println
(
"-ftpDir <directory> (default: "
+
FtpServer
.
DEFAULT_ROOT
+
", use jdbc:... to access a database)"
);
out
.
println
(
"-ftpDir <directory> (default: "
+
FtpServer
.
DEFAULT_ROOT
+
", use jdbc:... to access a database)"
);
out
.
println
(
"-ftpRead <readUserName> (default: "
+
FtpServer
.
DEFAULT_READ
+
")"
);
out
.
println
(
"-ftpWrite <writeUserName> (default: "
+
FtpServer
.
DEFAULT_WRITE
+
")"
);
out
.
println
(
"-ftpWritePassword <password> (default: "
+
FtpServer
.
DEFAULT_WRITE_PASSWORD
+
")"
);
out
.
println
(
"-ftpWritePassword <password> (default: "
+
FtpServer
.
DEFAULT_WRITE_PASSWORD
+
")"
);
out
.
println
();
out
.
println
(
"-log {true|false} (enable or disable logging, for all servers)"
);
out
.
println
(
"-baseDir <directory> (sets the base directory for H2 databases, for all servers)"
);
out
.
println
(
"-ifExists {true|false} (only existing databases may be opened, for all servers)"
);
}
public
Server
()
{
}
/**
* The command line interface for this tool.
* The options must be split into strings like this: "-baseDir", "/temp/data",...
...
...
@@ -114,7 +114,7 @@ public class Server implements Runnable, ShutdownHandler {
* </li><li>-ftpWrite {writeUserName}
* </li><li>-ftpWritePassword {password}
* </li></ul>
*
*
* @param args the command line arguments
* @throws SQLException
*/
...
...
@@ -150,6 +150,8 @@ public class Server implements Runnable, ShutdownHandler {
i
++;
}
else
if
(
"-webPort"
.
equals
(
a
))
{
i
++;
}
else
if
(
"-webScript"
.
equals
(
a
))
{
i
++;
}
else
if
(
"-webSSL"
.
equals
(
a
))
{
i
++;
}
else
{
...
...
@@ -267,10 +269,10 @@ public class Server implements Runnable, ShutdownHandler {
// ignore (status is displayed)
e
.
printStackTrace
();
exitCode
=
EXIT_ERROR
;
}
}
out
.
println
(
web
.
getStatus
());
// start browser anyway (even if the server is already running)
// because some people don't look at the output,
// start browser anyway (even if the server is already running)
// because some people don't look at the output,
// but are wondering why nothing happens
if
(
browserStart
)
{
StartBrowser
.
openURL
(
web
.
getURL
());
...
...
@@ -289,22 +291,22 @@ public class Server implements Runnable, ShutdownHandler {
}
return
exitCode
;
}
/**
* Shutdown a TCP server. If force is set to false, the server will not allow new connections,
* but not kill existing connections, instead it will stop if the last connection is closed.
* but not kill existing connections, instead it will stop if the last connection is closed.
* If force is set to true, existing connections are killed.
* After calling the method with force=false, it is not possible to call it again with
* force=true because new connections are not allowed.
* Example:
* <pre>Server.shutdownTcpServer("tcp://localhost:9094", password, true);</pre>
*
*
* @param url example: tcp://localhost:9094
* @param password the password to use ("" for no password)
* @param force the shutdown (don't wait)
* @throws ClassNotFoundException
* @throws SQLException
*/
* @throws SQLException
*/
public
static
void
shutdownTcpServer
(
String
url
,
String
password
,
boolean
force
)
throws
SQLException
{
int
port
=
Constants
.
DEFAULT_SERVER_PORT
;
int
idx
=
url
.
indexOf
(
':'
,
"jdbc:h2:"
.
length
());
...
...
@@ -376,7 +378,7 @@ public class Server implements Runnable, ShutdownHandler {
* Create a new web server, but does not start it yet.
* Example:
* <pre>Server server = Server.createWebServer(new String[]{"-log", "true"}).start();</pre>
*
*
* @param args
* @return the server
*/
...
...
@@ -391,7 +393,7 @@ public class Server implements Runnable, ShutdownHandler {
* Create a new ftp server, but does not start it yet.
* Example:
* <pre>Server server = Server.createFtpServer(new String[]{"-log", "true"}).start();</pre>
*
*
* @param args
* @return the server
*/
...
...
@@ -403,26 +405,26 @@ public class Server implements Runnable, ShutdownHandler {
* Create a new TCP server, but does not start it yet.
* Example:
* <pre>Server server = Server.createTcpServer(new String[]{"-tcpAllowOthers", "true"}).start();</pre>
*
*
* @param args
* @return the server
*/
public
static
Server
createTcpServer
(
String
[]
args
)
throws
SQLException
{
return
new
Server
(
new
TcpServer
(),
args
);
}
/**
* Create a new PG server, but does not start it yet.
* Example:
* <pre>Server server = Server.createPgServer(new String[]{"-pgAllowOthers", "true"}).start();</pre>
*
*
* @param args
* @return the server
*/
public
static
Server
createPgServer
(
String
[]
args
)
throws
SQLException
{
return
new
Server
(
new
PgServer
(),
args
);
}
/**
* Tries to start the server.
* @return the server if successful
...
...
@@ -473,7 +475,7 @@ public class Server implements Runnable, ShutdownHandler {
/**
* Checks if the server is running.
*
*
* @return if the server is running
*/
public
boolean
isRunning
()
{
...
...
@@ -486,7 +488,7 @@ public class Server implements Runnable, ShutdownHandler {
public
void
stop
()
{
service
.
stop
();
}
/**
* Gets the URL of this server.
* @return the url
...
...
@@ -514,7 +516,7 @@ public class Server implements Runnable, ShutdownHandler {
TraceSystem
.
traceThrowable
(
e
);
}
}
/**
* INTERNAL
*/
...
...
@@ -524,7 +526,7 @@ public class Server implements Runnable, ShutdownHandler {
/**
* INTERNAL
*/
*/
public
void
shutdown
()
{
if
(
shutdownHandler
!=
null
)
{
shutdownHandler
.
shutdown
();
...
...
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
e0e2869b
...
...
@@ -40,6 +40,7 @@ import org.h2.test.db.TestSQLInjection;
import
org.h2.test.db.TestScript
;
import
org.h2.test.db.TestScriptSimple
;
import
org.h2.test.db.TestSequence
;
import
org.h2.test.db.TestSessionsLocks
;
import
org.h2.test.db.TestSpaceReuse
;
import
org.h2.test.db.TestSpeed
;
import
org.h2.test.db.TestTempTables
;
...
...
@@ -151,8 +152,15 @@ java org.h2.test.TestAll timer
/*
write simple test for
NFORMATION_SCHEMA.SESSIONS and LOCKS
test & document exclusive mode
test exlclusive mode (inform_sch.settings table, disallow new connections, delay operations by other,
disable when close session, disable
translate error code 90135
C:\temp\test\db
...
...
@@ -576,6 +584,7 @@ Features of H2
new
TestRights
().
runTest
(
this
);
new
TestRunscript
().
runTest
(
this
);
new
TestSQLInjection
().
runTest
(
this
);
new
TestSessionsLocks
().
runTest
(
this
);
new
TestSequence
().
runTest
(
this
);
new
TestSpaceReuse
().
runTest
(
this
);
new
TestSpeed
().
runTest
(
this
);
...
...
h2/src/test/org/h2/test/db/TestSessionsLocks.java
0 → 100644
浏览文件 @
e0e2869b
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
db
;
import
java.sql.Connection
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
org.h2.test.TestBase
;
public
class
TestSessionsLocks
extends
TestBase
{
public
void
test
()
throws
Exception
{
testCancelStatement
();
testLocks
();
}
private
void
testLocks
()
throws
Exception
{
deleteDb
(
"sessionsLocks"
);
Connection
conn
=
getConnection
(
"sessionsLocks;MULTI_THREADED=1"
);
Statement
stat
=
conn
.
createStatement
();
ResultSet
rs
;
rs
=
stat
.
executeQuery
(
"select * from information_schema.locks order by session_id"
);
checkFalse
(
rs
.
next
());
Connection
conn2
=
getConnection
(
"sessionsLocks"
);
Statement
stat2
=
conn2
.
createStatement
();
stat2
.
execute
(
"create table test(id int primary key, name varchar)"
);
conn2
.
setAutoCommit
(
false
);
stat2
.
execute
(
"insert into test values(1, 'Hello')"
);
rs
=
stat
.
executeQuery
(
"select * from information_schema.locks order by session_id"
);
rs
.
next
();
check
(
"PUBLIC"
,
rs
.
getString
(
"TABLE_SCHEMA"
));
check
(
"TEST"
,
rs
.
getString
(
"TABLE_NAME"
));
rs
.
getString
(
"SESSION_ID"
);
if
(
config
.
mvcc
)
{
check
(
"READ"
,
rs
.
getString
(
"LOCK_TYPE"
));
}
else
{
check
(
"WRITE"
,
rs
.
getString
(
"LOCK_TYPE"
));
}
checkFalse
(
rs
.
next
());
conn2
.
commit
();
conn2
.
setTransactionIsolation
(
Connection
.
TRANSACTION_SERIALIZABLE
);
stat2
.
execute
(
"SELECT * FROM TEST"
);
rs
=
stat
.
executeQuery
(
"select * from information_schema.locks order by session_id"
);
if
(!
config
.
mvcc
)
{
rs
.
next
();
check
(
"PUBLIC"
,
rs
.
getString
(
"TABLE_SCHEMA"
));
check
(
"TEST"
,
rs
.
getString
(
"TABLE_NAME"
));
rs
.
getString
(
"SESSION_ID"
);
check
(
"READ"
,
rs
.
getString
(
"LOCK_TYPE"
));
}
checkFalse
(
rs
.
next
());
conn2
.
commit
();
rs
=
stat
.
executeQuery
(
"select * from information_schema.locks order by session_id"
);
checkFalse
(
rs
.
next
());
conn
.
close
();
conn2
.
close
();
}
public
void
testCancelStatement
()
throws
Exception
{
deleteDb
(
"sessionsLocks"
);
Connection
conn
=
getConnection
(
"sessionsLocks;MULTI_THREADED=1"
);
Statement
stat
=
conn
.
createStatement
();
ResultSet
rs
;
rs
=
stat
.
executeQuery
(
"select * from information_schema.sessions order by SESSION_START, ID"
);
rs
.
next
();
int
sessionId
=
rs
.
getInt
(
"ID"
);
rs
.
getString
(
"USER_NAME"
);
rs
.
getTimestamp
(
"SESSION_START"
);
rs
.
getString
(
"STATEMENT"
);
rs
.
getTimestamp
(
"STATEMENT_START"
);
checkFalse
(
rs
.
next
());
Connection
conn2
=
getConnection
(
"sessionsLocks"
);
final
Statement
stat2
=
conn2
.
createStatement
();
rs
=
stat
.
executeQuery
(
"select * from information_schema.sessions order by SESSION_START, ID"
);
check
(
rs
.
next
());
check
(
sessionId
,
rs
.
getInt
(
"ID"
));
check
(
rs
.
next
());
int
otherId
=
rs
.
getInt
(
"ID"
);
check
(
otherId
!=
sessionId
);
checkFalse
(
rs
.
next
());
stat2
.
execute
(
"set throttle 1"
);
final
boolean
[]
done
=
new
boolean
[
1
];
Runnable
runnable
=
new
Runnable
()
{
public
void
run
()
{
try
{
stat2
.
execute
(
"select count(*) from system_range(1, 10000000) t1, system_range(1, 10000000) t2"
);
new
Error
(
"Unexpected success"
).
printStackTrace
();
}
catch
(
SQLException
e
)
{
done
[
0
]
=
true
;
}
}
};
new
Thread
(
runnable
).
start
();
while
(
true
)
{
Thread
.
sleep
(
1000
);
rs
=
stat
.
executeQuery
(
"CALL CANCEL_SESSION("
+
otherId
+
")"
);
rs
.
next
();
if
(
rs
.
getBoolean
(
1
))
{
Thread
.
sleep
(
100
);
check
(
done
[
0
]);
break
;
}
else
{
System
.
out
.
println
(
"no statement is executing yet"
);
}
}
conn2
.
close
();
conn
.
close
();
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论