Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
1fc1d43e
Unverified
提交
1fc1d43e
authored
6 年前
作者:
Evgenij Ryazanov
提交者:
GitHub
6 年前
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1729 from katzyn/PreparedStatement
Parse parameters properly in prepared statements with multiple commands
上级
6666417b
511f7585
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
128 行增加
和
20 行删除
+128
-20
changelog.html
h2/src/docsrc/html/changelog.html
+2
-0
CommandContainer.java
h2/src/main/org/h2/command/CommandContainer.java
+4
-0
CommandList.java
h2/src/main/org/h2/command/CommandList.java
+39
-10
Parser.java
h2/src/main/org/h2/command/Parser.java
+55
-10
TestPreparedStatement.java
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
+28
-0
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
1fc1d43e
...
...
@@ -21,6 +21,8 @@ Change Log
<h2>
Next Version (unreleased)
</h2>
<ul>
<li>
Issue #1590: Error on executing "DELETE FROM table1 WHERE ID = ?; DELETE FROM table2 WHERE ID = ?;"
</li>
<li>
Issue #1727: Support ISODOW as identifier for the extract function additional to ISO_DAY_OF_WEEK
</li>
<li>
PR #1580, #1726: Disable remote database creation by default
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/CommandContainer.java
浏览文件 @
1fc1d43e
...
...
@@ -185,4 +185,8 @@ public class CommandContainer extends Command {
return
prepared
.
getType
();
}
void
clearCTE
()
{
clearCTE
(
session
,
prepared
);
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/CommandList.java
浏览文件 @
1fc1d43e
...
...
@@ -8,6 +8,7 @@ package org.h2.command;
import
java.util.ArrayList
;
import
org.h2.engine.Session
;
import
org.h2.expression.Parameter
;
import
org.h2.expression.ParameterInterface
;
import
org.h2.result.ResultInterface
;
...
...
@@ -16,28 +17,45 @@ import org.h2.result.ResultInterface;
*/
class
CommandList
extends
Command
{
private
final
Command
command
;
private
final
String
remaining
;
private
CommandContainer
command
;
private
final
ArrayList
<
Prepared
>
commands
;
private
final
ArrayList
<
Parameter
>
parameters
;
private
String
remaining
;
private
Command
remainingCommand
;
CommandList
(
Session
session
,
String
sql
,
Command
c
,
String
remaining
)
{
CommandList
(
Session
session
,
String
sql
,
CommandContainer
command
,
ArrayList
<
Prepared
>
commands
,
ArrayList
<
Parameter
>
parameters
,
String
remaining
)
{
super
(
session
,
sql
);
this
.
command
=
c
;
this
.
command
=
command
;
this
.
commands
=
commands
;
this
.
parameters
=
parameters
;
this
.
remaining
=
remaining
;
}
@Override
public
ArrayList
<?
extends
ParameterInterface
>
getParameters
()
{
return
command
.
getParameters
()
;
return
parameters
;
}
private
void
executeRemaining
()
{
Command
remainingCommand
=
session
.
prepareLocal
(
remaining
);
for
(
Prepared
prepared
:
commands
)
{
prepared
.
prepare
();
if
(
prepared
.
isQuery
())
{
prepared
.
query
(
0
);
}
else
{
prepared
.
update
();
}
}
if
(
remaining
!=
null
)
{
remainingCommand
=
session
.
prepareLocal
(
remaining
);
remaining
=
null
;
if
(
remainingCommand
.
isQuery
())
{
remainingCommand
.
query
(
0
);
}
else
{
remainingCommand
.
update
();
}
}
}
@Override
public
int
update
()
{
...
...
@@ -58,6 +76,17 @@ class CommandList extends Command {
return
result
;
}
@Override
public
void
stop
()
{
command
.
stop
();
for
(
Prepared
prepared
:
commands
)
{
CommandContainer
.
clearCTE
(
session
,
prepared
);
}
if
(
remainingCommand
!=
null
)
{
remainingCommand
.
stop
();
}
}
@Override
public
boolean
isQuery
()
{
return
command
.
isQuery
();
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/Parser.java
浏览文件 @
1fc1d43e
...
...
@@ -634,14 +634,15 @@ public class Parser {
private
Prepared
currentPrepared
;
private
Select
currentSelect
;
private
ArrayList
<
Parameter
>
parameters
;
private
ArrayList
<
Parameter
>
indexedParameterList
;
private
ArrayList
<
Parameter
>
suppliedParameters
;
private
ArrayList
<
Parameter
>
suppliedParameterList
;
private
String
schemaName
;
private
ArrayList
<
String
>
expectedList
;
private
boolean
rightsChecked
;
private
boolean
recompileAlways
;
private
boolean
literalsChecked
;
private
ArrayList
<
Parameter
>
indexedParameterList
;
private
int
orderInFrom
;
private
ArrayList
<
Parameter
>
suppliedParameterList
;
public
Parser
(
Session
session
)
{
this
.
database
=
session
.
getDatabase
();
...
...
@@ -673,8 +674,8 @@ public class Parser {
public
Command
prepareCommand
(
String
sql
)
{
try
{
Prepared
p
=
parse
(
sql
);
boolean
hasMore
=
isToken
(
SEMICOLON
);
if
(!
hasMore
&&
currentTokenType
!=
END
)
{
if
(
currentTokenType
!=
SEMICOLON
&&
currentTokenType
!=
END
)
{
addExpected
(
SEMICOLON
);
throw
getSyntaxError
();
}
try
{
...
...
@@ -683,11 +684,14 @@ public class Parser {
CommandContainer
.
clearCTE
(
session
,
p
);
throw
t
;
}
Command
c
=
new
CommandContainer
(
session
,
sql
,
p
);
if
(
hasMore
)
{
if
(
parseIndex
<
sql
.
length
())
{
sql
=
sql
.
substring
(
0
,
parseIndex
);
}
CommandContainer
c
=
new
CommandContainer
(
session
,
sql
,
p
);
if
(
currentTokenType
==
SEMICOLON
)
{
String
remaining
=
originalSQL
.
substring
(
parseIndex
);
if
(!
StringUtils
.
isWhitespaceOrEmpty
(
remaining
))
{
c
=
new
CommandList
(
session
,
sql
,
c
,
remaining
);
return
prepareCommandList
(
c
,
sql
,
remaining
);
}
}
return
c
;
...
...
@@ -696,6 +700,46 @@ public class Parser {
}
}
private
CommandList
prepareCommandList
(
CommandContainer
command
,
String
sql
,
String
remaining
)
{
try
{
ArrayList
<
Prepared
>
list
=
Utils
.
newSmallArrayList
();
boolean
stop
=
false
;
do
{
if
(
stop
)
{
return
new
CommandList
(
session
,
sql
,
command
,
list
,
parameters
,
remaining
);
}
suppliedParameters
=
parameters
;
suppliedParameterList
=
indexedParameterList
;
Prepared
p
;
try
{
p
=
parse
(
remaining
);
}
catch
(
DbException
ex
)
{
// This command may depend on results of previous commands.
if
(
ex
.
getErrorCode
()
==
ErrorCode
.
CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS
)
{
throw
ex
;
}
return
new
CommandList
(
session
,
sql
,
command
,
list
,
parameters
,
remaining
);
}
if
(
p
instanceof
DefineCommand
)
{
// Next commands may depend on results of this command.
stop
=
true
;
}
list
.
add
(
p
);
if
(
currentTokenType
==
END
)
{
break
;
}
if
(
currentTokenType
!=
SEMICOLON
)
{
addExpected
(
SEMICOLON
);
throw
getSyntaxError
();
}
}
while
(!
StringUtils
.
isWhitespaceOrEmpty
(
remaining
=
originalSQL
.
substring
(
parseIndex
)));
return
new
CommandList
(
session
,
sql
,
command
,
list
,
parameters
,
null
);
}
catch
(
Throwable
t
)
{
command
.
clearCTE
();
throw
t
;
}
}
/**
* Parse the statement, but don't prepare it for execution.
*
...
...
@@ -727,12 +771,12 @@ public class Parser {
}
else
{
expectedList
=
null
;
}
parameters
=
Utils
.
newSmallArrayList
();
parameters
=
suppliedParameters
!=
null
?
suppliedParameters
:
Utils
.<
Parameter
>
newSmallArrayList
();
indexedParameterList
=
suppliedParameterList
;
currentSelect
=
null
;
currentPrepared
=
null
;
createView
=
null
;
recompileAlways
=
false
;
indexedParameterList
=
suppliedParameterList
;
read
();
return
parsePrepared
();
}
...
...
@@ -3834,6 +3878,7 @@ public class Parser {
if
(
p
==
null
)
{
p
=
new
Parameter
(
index
);
indexedParameterList
.
set
(
index
,
p
);
parameters
.
add
(
p
);
}
read
();
}
else
{
...
...
@@ -3843,8 +3888,8 @@ public class Parser {
.
get
(
ErrorCode
.
CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS
);
}
p
=
new
Parameter
(
parameters
.
size
());
}
parameters
.
add
(
p
);
}
return
p
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
浏览文件 @
1fc1d43e
...
...
@@ -199,6 +199,7 @@ public class TestPreparedStatement extends TestDb {
testColumnMetaDataWithEquals
(
conn
);
testColumnMetaDataWithIn
(
conn
);
testValueResultSet
(
conn
);
testMultipleStatements
(
conn
);
conn
.
close
();
testPreparedStatementWithLiteralsNone
();
testPreparedStatementWithIndexedParameterAndLiteralsNone
();
...
...
@@ -1758,4 +1759,31 @@ public class TestPreparedStatement extends TestDb {
}
}
private
void
testMultipleStatements
(
Connection
conn
)
throws
SQLException
{
assertThrows
(
ErrorCode
.
CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS
,
conn
).
prepareStatement
(
"SELECT ?; SELECT ?1"
);
assertThrows
(
ErrorCode
.
CANNOT_MIX_INDEXED_AND_UNINDEXED_PARAMS
,
conn
).
prepareStatement
(
"SELECT ?1; SELECT ?"
);
Statement
stmt
=
conn
.
createStatement
();
stmt
.
execute
(
"CREATE TABLE TEST (ID IDENTITY, V INT)"
);
PreparedStatement
ps
=
conn
.
prepareStatement
(
"INSERT INTO TEST(V) VALUES ?; INSERT INTO TEST(V) VALUES ?"
);
ps
.
setInt
(
1
,
1
);
ps
.
setInt
(
2
,
2
);
ps
.
executeUpdate
();
ps
=
conn
.
prepareStatement
(
"INSERT INTO TEST(V) VALUES ?2; INSERT INTO TEST(V) VALUES ?1;"
);
ps
.
setInt
(
1
,
3
);
ps
.
setInt
(
2
,
4
);
ps
.
executeUpdate
();
try
(
ResultSet
rs
=
stmt
.
executeQuery
(
"SELECT V FROM TEST ORDER BY ID"
))
{
assertTrue
(
rs
.
next
());
assertEquals
(
1
,
rs
.
getInt
(
1
));
assertTrue
(
rs
.
next
());
assertEquals
(
2
,
rs
.
getInt
(
1
));
assertTrue
(
rs
.
next
());
assertEquals
(
4
,
rs
.
getInt
(
1
));
assertTrue
(
rs
.
next
());
assertEquals
(
3
,
rs
.
getInt
(
1
));
assertFalse
(
rs
.
next
());
}
stmt
.
execute
(
"DROP TABLE TEST"
);
}
}
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论