Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
2bbf093a
提交
2bbf093a
authored
16 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Could not use the same linked table multiple times in the same query.
上级
e995b56b
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
87 行增加
和
33 行删除
+87
-33
changelog.html
h2/src/docsrc/html/changelog.html
+2
-1
roadmap.html
h2/src/docsrc/html/roadmap.html
+1
-0
LinkedCursor.java
h2/src/main/org/h2/index/LinkedCursor.java
+19
-9
LinkedIndex.java
h2/src/main/org/h2/index/LinkedIndex.java
+9
-14
TableLink.java
h2/src/main/org/h2/table/TableLink.java
+34
-9
TestLinkedTable.java
h2/src/test/org/h2/test/db/TestLinkedTable.java
+22
-0
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
2bbf093a
...
@@ -18,7 +18,8 @@ Change Log
...
@@ -18,7 +18,8 @@ Change Log
<h1>
Change Log
</h1>
<h1>
Change Log
</h1>
<h2>
Next Version (unreleased)
</h2>
<h2>
Next Version (unreleased)
</h2>
<ul><li>
A bug in the server-less multi-connection mode has been fixed.
<ul><li>
Could not use the same linked table multiple times in the same query.
</li><li>
A bug in the server-less multi-connection mode has been fixed.
</li><li>
Column names could not be named "UNIQUE" (with the quotes).
</li><li>
Column names could not be named "UNIQUE" (with the quotes).
</li><li>
New system function TRANSACTION_ID() to get the current transaction
</li><li>
New system function TRANSACTION_ID() to get the current transaction
identifier for a session.
identifier for a session.
...
...
This diff is collapsed.
Click to expand it.
h2/src/docsrc/html/roadmap.html
浏览文件 @
2bbf093a
...
@@ -407,6 +407,7 @@ Of course, patches are always welcome, but are not always applied as is. Patches
...
@@ -407,6 +407,7 @@ Of course, patches are always welcome, but are not always applied as is. Patches
</li><li>
PostgreSQL compatibility: test DbVisualizer and Squirrel SQL using a new PostgreSQL JDBC driver.
</li><li>
PostgreSQL compatibility: test DbVisualizer and Squirrel SQL using a new PostgreSQL JDBC driver.
</li><li>
RunScript should be able to read from system in (or quite mode for Shell).
</li><li>
RunScript should be able to read from system in (or quite mode for Shell).
</li><li>
Natural join: support select x from dual natural join dual.
</li><li>
Natural join: support select x from dual natural join dual.
</li><li>
Optimize IN(...) for DELETE and UPDATE.
</li></ul>
</li></ul>
<h2>
Not Planned
</h2>
<h2>
Not Planned
</h2>
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/LinkedCursor.java
浏览文件 @
2bbf093a
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
*/
*/
package
org
.
h2
.
index
;
package
org
.
h2
.
index
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
...
@@ -14,7 +15,7 @@ import org.h2.message.Message;
...
@@ -14,7 +15,7 @@ import org.h2.message.Message;
import
org.h2.result.Row
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
import
org.h2.result.SearchRow
;
import
org.h2.table.Column
;
import
org.h2.table.Column
;
import
org.h2.table.Table
;
import
org.h2.table.Table
Link
;
import
org.h2.value.DataType
;
import
org.h2.value.DataType
;
import
org.h2.value.Value
;
import
org.h2.value.Value
;
...
@@ -23,15 +24,24 @@ import org.h2.value.Value;
...
@@ -23,15 +24,24 @@ import org.h2.value.Value;
*/
*/
public
class
LinkedCursor
implements
Cursor
{
public
class
LinkedCursor
implements
Cursor
{
private
Session
session
;
private
final
TableLink
tableLink
;
private
final
PreparedStatement
prep
;
private
final
String
sql
;
private
final
Session
session
;
private
final
ResultSet
rs
;
private
Row
current
;
private
Row
current
;
private
ResultSet
rs
;
private
Table
table
;
LinkedCursor
(
Table
table
,
ResultSet
rs
,
Session
session
)
{
LinkedCursor
(
Table
Link
tableLink
,
ResultSet
rs
,
Session
session
,
String
sql
,
PreparedStatement
prep
)
{
this
.
session
=
session
;
this
.
session
=
session
;
this
.
table
=
table
;
this
.
table
Link
=
tableLink
;
this
.
rs
=
rs
;
this
.
rs
=
rs
;
this
.
sql
=
sql
;
this
.
prep
=
prep
;
}
private
void
closeResultSetAndReusePreparedStatement
()
throws
SQLException
{
rs
.
close
();
tableLink
.
reusePreparedStatement
(
prep
,
sql
);
}
}
public
Row
get
()
{
public
Row
get
()
{
...
@@ -50,13 +60,13 @@ public class LinkedCursor implements Cursor {
...
@@ -50,13 +60,13 @@ public class LinkedCursor implements Cursor {
public
boolean
next
()
throws
SQLException
{
public
boolean
next
()
throws
SQLException
{
boolean
result
=
rs
.
next
();
boolean
result
=
rs
.
next
();
if
(!
result
)
{
if
(!
result
)
{
rs
.
close
();
closeResultSetAndReusePreparedStatement
();
current
=
null
;
current
=
null
;
return
false
;
return
false
;
}
}
current
=
table
.
getTemplateRow
();
current
=
table
Link
.
getTemplateRow
();
for
(
int
i
=
0
;
i
<
current
.
getColumnCount
();
i
++)
{
for
(
int
i
=
0
;
i
<
current
.
getColumnCount
();
i
++)
{
Column
col
=
table
.
getColumn
(
i
);
Column
col
=
table
Link
.
getColumn
(
i
);
Value
v
=
DataType
.
readValue
(
session
,
rs
,
i
+
1
,
col
.
getType
());
Value
v
=
DataType
.
readValue
(
session
,
rs
,
i
+
1
,
col
.
getType
());
current
.
setValue
(
i
,
v
);
current
.
setValue
(
i
,
v
);
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/LinkedIndex.java
浏览文件 @
2bbf093a
...
@@ -10,7 +10,6 @@ import java.sql.PreparedStatement;
...
@@ -10,7 +10,6 @@ import java.sql.PreparedStatement;
import
java.sql.ResultSet
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
org.h2.constant.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Session
;
import
org.h2.engine.Session
;
import
org.h2.message.Message
;
import
org.h2.message.Message
;
...
@@ -70,7 +69,7 @@ public class LinkedIndex extends BaseIndex {
...
@@ -70,7 +69,7 @@ public class LinkedIndex extends BaseIndex {
String
sql
=
buff
.
toString
();
String
sql
=
buff
.
toString
();
synchronized
(
link
.
getConnection
())
{
synchronized
(
link
.
getConnection
())
{
try
{
try
{
PreparedStatement
prep
=
link
.
getPreparedStatement
(
sql
);
PreparedStatement
prep
=
link
.
getPreparedStatement
(
sql
,
false
);
for
(
int
i
=
0
,
j
=
0
;
i
<
row
.
getColumnCount
();
i
++)
{
for
(
int
i
=
0
,
j
=
0
;
i
<
row
.
getColumnCount
();
i
++)
{
Value
v
=
row
.
getValue
(
i
);
Value
v
=
row
.
getValue
(
i
);
if
(
v
!=
null
&&
v
!=
ValueNull
.
INSTANCE
)
{
if
(
v
!=
null
&&
v
!=
ValueNull
.
INSTANCE
)
{
...
@@ -81,7 +80,7 @@ public class LinkedIndex extends BaseIndex {
...
@@ -81,7 +80,7 @@ public class LinkedIndex extends BaseIndex {
prep
.
executeUpdate
();
prep
.
executeUpdate
();
rowCount
++;
rowCount
++;
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
throw
wrapException
(
sql
,
e
);
throw
link
.
wrapException
(
sql
,
e
);
}
}
}
}
}
}
...
@@ -119,7 +118,7 @@ public class LinkedIndex extends BaseIndex {
...
@@ -119,7 +118,7 @@ public class LinkedIndex extends BaseIndex {
String
sql
=
buff
.
toString
();
String
sql
=
buff
.
toString
();
synchronized
(
link
.
getConnection
())
{
synchronized
(
link
.
getConnection
())
{
try
{
try
{
PreparedStatement
prep
=
link
.
getPreparedStatement
(
sql
);
PreparedStatement
prep
=
link
.
getPreparedStatement
(
sql
,
true
);
int
j
=
0
;
int
j
=
0
;
for
(
int
i
=
0
;
first
!=
null
&&
i
<
first
.
getColumnCount
();
i
++)
{
for
(
int
i
=
0
;
first
!=
null
&&
i
<
first
.
getColumnCount
();
i
++)
{
Value
v
=
first
.
getValue
(
i
);
Value
v
=
first
.
getValue
(
i
);
...
@@ -136,9 +135,9 @@ public class LinkedIndex extends BaseIndex {
...
@@ -136,9 +135,9 @@ public class LinkedIndex extends BaseIndex {
}
}
}
}
ResultSet
rs
=
prep
.
executeQuery
();
ResultSet
rs
=
prep
.
executeQuery
();
return
new
LinkedCursor
(
table
,
rs
,
session
);
return
new
LinkedCursor
(
link
,
rs
,
session
,
sql
,
prep
);
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
throw
wrapException
(
sql
,
e
);
throw
link
.
wrapException
(
sql
,
e
);
}
}
}
}
}
}
...
@@ -209,7 +208,7 @@ public class LinkedIndex extends BaseIndex {
...
@@ -209,7 +208,7 @@ public class LinkedIndex extends BaseIndex {
String
sql
=
buff
.
toString
();
String
sql
=
buff
.
toString
();
synchronized
(
link
.
getConnection
())
{
synchronized
(
link
.
getConnection
())
{
try
{
try
{
PreparedStatement
prep
=
link
.
getPreparedStatement
(
sql
);
PreparedStatement
prep
=
link
.
getPreparedStatement
(
sql
,
false
);
for
(
int
i
=
0
,
j
=
0
;
i
<
row
.
getColumnCount
();
i
++)
{
for
(
int
i
=
0
,
j
=
0
;
i
<
row
.
getColumnCount
();
i
++)
{
Value
v
=
row
.
getValue
(
i
);
Value
v
=
row
.
getValue
(
i
);
if
(!
isNull
(
v
))
{
if
(!
isNull
(
v
))
{
...
@@ -220,7 +219,7 @@ public class LinkedIndex extends BaseIndex {
...
@@ -220,7 +219,7 @@ public class LinkedIndex extends BaseIndex {
int
count
=
prep
.
executeUpdate
();
int
count
=
prep
.
executeUpdate
();
rowCount
-=
count
;
rowCount
-=
count
;
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
throw
wrapException
(
sql
,
e
);
throw
link
.
wrapException
(
sql
,
e
);
}
}
}
}
}
}
...
@@ -261,7 +260,7 @@ public class LinkedIndex extends BaseIndex {
...
@@ -261,7 +260,7 @@ public class LinkedIndex extends BaseIndex {
synchronized
(
link
.
getConnection
())
{
synchronized
(
link
.
getConnection
())
{
try
{
try
{
int
j
=
1
;
int
j
=
1
;
PreparedStatement
prep
=
link
.
getPreparedStatement
(
sql
);
PreparedStatement
prep
=
link
.
getPreparedStatement
(
sql
,
false
);
for
(
int
i
=
0
;
i
<
newRow
.
getColumnCount
();
i
++)
{
for
(
int
i
=
0
;
i
<
newRow
.
getColumnCount
();
i
++)
{
newRow
.
getValue
(
i
).
set
(
prep
,
j
);
newRow
.
getValue
(
i
).
set
(
prep
,
j
);
j
++;
j
++;
...
@@ -277,15 +276,11 @@ public class LinkedIndex extends BaseIndex {
...
@@ -277,15 +276,11 @@ public class LinkedIndex extends BaseIndex {
// this has no effect but at least it allows to debug the update count
// this has no effect but at least it allows to debug the update count
rowCount
=
rowCount
+
count
-
count
;
rowCount
=
rowCount
+
count
-
count
;
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
throw
wrapException
(
sql
,
e
);
throw
link
.
wrapException
(
sql
,
e
);
}
}
}
}
}
}
private
SQLException
wrapException
(
String
sql
,
SQLException
e
)
{
return
Message
.
getSQLException
(
ErrorCode
.
ERROR_ACCESSING_LINKED_TABLE_2
,
new
String
[]
{
sql
,
e
.
toString
()
},
e
);
}
public
long
getRowCount
(
Session
session
)
{
public
long
getRowCount
(
Session
session
)
{
return
rowCount
;
return
rowCount
;
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/TableLink.java
浏览文件 @
2bbf093a
...
@@ -367,13 +367,29 @@ public class TableLink extends Table {
...
@@ -367,13 +367,29 @@ public class TableLink extends Table {
}
}
}
}
public
long
getRowCount
(
Session
session
)
throws
SQLException
{
public
synchronized
long
getRowCount
(
Session
session
)
throws
SQLException
{
PreparedStatement
prep
=
getPreparedStatement
(
"SELECT COUNT(*) FROM "
+
qualifiedTableName
);
String
sql
=
"SELECT COUNT(*) FROM "
+
qualifiedTableName
;
ResultSet
rs
=
prep
.
executeQuery
();
try
{
rs
.
next
();
PreparedStatement
prep
=
getPreparedStatement
(
sql
,
false
);
long
count
=
rs
.
getLong
(
1
);
ResultSet
rs
=
prep
.
executeQuery
();
rs
.
close
();
rs
.
next
();
return
count
;
long
count
=
rs
.
getLong
(
1
);
rs
.
close
();
return
count
;
}
catch
(
SQLException
e
)
{
throw
wrapException
(
sql
,
e
);
}
}
/**
* Wrap a SQL exception that occurred while accessing a linked table.
*
* @param sql the SQL statement
* @param e the SQL exception from the remote database
* @return the wrapped SQL exception
*/
public
SQLException
wrapException
(
String
sql
,
SQLException
e
)
{
return
Message
.
getSQLException
(
ErrorCode
.
ERROR_ACCESSING_LINKED_TABLE_2
,
new
String
[]
{
sql
,
e
.
toString
()
},
e
);
}
}
public
String
getQualifiedTable
()
{
public
String
getQualifiedTable
()
{
...
@@ -384,10 +400,12 @@ public class TableLink extends Table {
...
@@ -384,10 +400,12 @@ public class TableLink extends Table {
* Get a prepared statement object for the given statement. Prepared
* Get a prepared statement object for the given statement. Prepared
* statements are kept in a hash map to avoid re-creating them.
* statements are kept in a hash map to avoid re-creating them.
*
*
* @param sql the SQL statement.
* @param sql the SQL statement
* @param exclusive if the prepared statement must be removed from the map
* until reusePreparedStatement is called (only required for queries)
* @return the prepared statement
* @return the prepared statement
*/
*/
public
PreparedStatement
getPreparedStatement
(
String
sql
)
throws
SQLException
{
public
PreparedStatement
getPreparedStatement
(
String
sql
,
boolean
exclusive
)
throws
SQLException
{
Trace
trace
=
database
.
getTrace
(
Trace
.
TABLE
);
Trace
trace
=
database
.
getTrace
(
Trace
.
TABLE
);
if
(
trace
.
isDebugEnabled
())
{
if
(
trace
.
isDebugEnabled
())
{
trace
.
debug
(
getName
()
+
":\n"
+
sql
);
trace
.
debug
(
getName
()
+
":\n"
+
sql
);
...
@@ -400,6 +418,9 @@ public class TableLink extends Table {
...
@@ -400,6 +418,9 @@ public class TableLink extends Table {
prep
=
conn
.
getConnection
().
prepareStatement
(
sql
);
prep
=
conn
.
getConnection
().
prepareStatement
(
sql
);
prepared
.
put
(
sql
,
prep
);
prepared
.
put
(
sql
,
prep
);
}
}
if
(
exclusive
)
{
prepared
.
remove
(
sql
);
}
return
prep
;
return
prep
;
}
}
...
@@ -502,4 +523,8 @@ public class TableLink extends Table {
...
@@ -502,4 +523,8 @@ public class TableLink extends Table {
return
ROW_COUNT_APPROXIMATION
;
return
ROW_COUNT_APPROXIMATION
;
}
}
public
void
reusePreparedStatement
(
PreparedStatement
prep
,
String
sql
)
{
prepared
.
put
(
sql
,
prep
);
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/db/TestLinkedTable.java
浏览文件 @
2bbf093a
...
@@ -34,6 +34,7 @@ public class TestLinkedTable extends TestBase {
...
@@ -34,6 +34,7 @@ public class TestLinkedTable extends TestBase {
public
void
test
()
throws
SQLException
{
public
void
test
()
throws
SQLException
{
// testLinkAutoAdd();
// testLinkAutoAdd();
testNestedQueriesToSameTable
();
testSharedConnection
();
testSharedConnection
();
testMultipleSchemas
();
testMultipleSchemas
();
testReadOnlyLinkedTable
();
testReadOnlyLinkedTable
();
...
@@ -66,6 +67,27 @@ public class TestLinkedTable extends TestBase {
...
@@ -66,6 +67,27 @@ public class TestLinkedTable extends TestBase {
// cb.close();
// cb.close();
// }
// }
private
void
testNestedQueriesToSameTable
()
throws
SQLException
{
if
(
config
.
memory
||
!
SysProperties
.
SHARE_LINKED_CONNECTIONS
)
{
return
;
}
org
.
h2
.
Driver
.
load
();
deleteDb
(
"linkedTable"
);
String
url
=
getURL
(
"linkedTable"
,
true
);
String
user
=
getUser
();
String
password
=
getPassword
();
Connection
ca
=
getConnection
(
url
,
user
,
password
);
Statement
sa
=
ca
.
createStatement
();
sa
.
execute
(
"CREATE TABLE TEST(ID INT) AS SELECT 1"
);
ca
.
close
();
Connection
cb
=
DriverManager
.
getConnection
(
"jdbc:h2:mem:two"
,
"sa"
,
"sa"
);
Statement
sb
=
cb
.
createStatement
();
sb
.
execute
(
"CREATE LINKED TABLE T1(NULL, '"
+
url
+
"', '"
+
user
+
"', '"
+
password
+
"', 'TEST')"
);
sb
.
executeQuery
(
"SELECT * FROM DUAL A LEFT OUTER JOIN T1 A ON A.ID=1 LEFT OUTER JOIN T1 B ON B.ID=1"
);
sb
.
execute
(
"DROP ALL OBJECTS"
);
cb
.
close
();
}
private
void
testSharedConnection
()
throws
SQLException
{
private
void
testSharedConnection
()
throws
SQLException
{
if
(
config
.
memory
||
!
SysProperties
.
SHARE_LINKED_CONNECTIONS
)
{
if
(
config
.
memory
||
!
SysProperties
.
SHARE_LINKED_CONNECTIONS
)
{
return
;
return
;
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论