Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
3e3a604a
提交
3e3a604a
authored
2月 07, 2018
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support for = ANY(?)
上级
fb533419
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
210 行增加
和
3 行删除
+210
-3
Parser.java
h2/src/main/org/h2/command/Parser.java
+9
-3
ConditionInParameter.java
h2/src/main/org/h2/expression/ConditionInParameter.java
+164
-0
TestPreparedStatement.java
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
+37
-0
没有找到文件。
h2/src/main/org/h2/command/Parser.java
浏览文件 @
3e3a604a
...
...
@@ -112,6 +112,7 @@ import org.h2.expression.Comparison;
import
org.h2.expression.ConditionAndOr
;
import
org.h2.expression.ConditionExists
;
import
org.h2.expression.ConditionIn
;
import
org.h2.expression.ConditionInParameter
;
import
org.h2.expression.ConditionInSelect
;
import
org.h2.expression.ConditionNot
;
import
org.h2.expression.Expression
;
...
...
@@ -2504,9 +2505,14 @@ public class Parser {
read
(
")"
);
}
else
if
(
readIf
(
"ANY"
)
||
readIf
(
"SOME"
))
{
read
(
"("
);
Query
query
=
parseSelect
();
r
=
new
ConditionInSelect
(
database
,
r
,
query
,
false
,
compareType
);
if
(
currentTokenType
==
PARAMETER
&&
compareType
==
0
)
{
Parameter
p
=
readParameter
();
r
=
new
ConditionInParameter
(
database
,
r
,
p
);
}
else
{
Query
query
=
parseSelect
();
r
=
new
ConditionInSelect
(
database
,
r
,
query
,
false
,
compareType
);
}
read
(
")"
);
}
else
{
Expression
right
=
readConcat
();
...
...
h2/src/main/org/h2/expression/ConditionInParameter.java
0 → 100644
浏览文件 @
3e3a604a
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
expression
;
import
java.util.AbstractList
;
import
org.h2.engine.Database
;
import
org.h2.engine.Session
;
import
org.h2.index.IndexCondition
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.TableFilter
;
import
org.h2.value.Value
;
import
org.h2.value.ValueArray
;
import
org.h2.value.ValueBoolean
;
import
org.h2.value.ValueNull
;
/**
* A condition with parameter as {@code = ANY(?)}.
*/
public
class
ConditionInParameter
extends
Condition
{
private
static
final
class
ParameterList
extends
AbstractList
<
Expression
>
{
private
final
Parameter
parameter
;
ParameterList
(
Parameter
parameter
)
{
this
.
parameter
=
parameter
;
}
@Override
public
Expression
get
(
int
index
)
{
Value
value
=
parameter
.
getParamValue
();
if
(
value
instanceof
ValueArray
)
{
return
ValueExpression
.
get
(((
ValueArray
)
value
).
getList
()[
index
]);
}
if
(
index
!=
0
)
{
throw
new
IndexOutOfBoundsException
();
}
return
ValueExpression
.
get
(
value
);
}
@Override
public
int
size
()
{
if
(!
parameter
.
isValueSet
())
{
return
0
;
}
Value
value
=
parameter
.
getParamValue
();
if
(
value
instanceof
ValueArray
)
{
return
((
ValueArray
)
value
).
getList
().
length
;
}
return
1
;
}
}
private
final
Database
database
;
private
Expression
left
;
final
Parameter
parameter
;
/**
* Create a new {@code = ANY(?)} condition.
*
* @param database
* the database
* @param left
* the expression before {@code = ANY(?)}
* @param parameter
* parameter
*/
public
ConditionInParameter
(
Database
database
,
Expression
left
,
Parameter
parameter
)
{
this
.
database
=
database
;
this
.
left
=
left
;
this
.
parameter
=
parameter
;
}
@Override
public
Value
getValue
(
Session
session
)
{
Value
l
=
left
.
getValue
(
session
);
if
(
l
==
ValueNull
.
INSTANCE
)
{
return
l
;
}
boolean
result
=
false
;
boolean
hasNull
=
false
;
Value
value
=
parameter
.
getValue
(
session
);
if
(
value
instanceof
ValueArray
)
{
for
(
Value
r
:
((
ValueArray
)
value
).
getList
())
{
if
(
r
==
ValueNull
.
INSTANCE
)
{
hasNull
=
true
;
}
else
{
r
=
r
.
convertTo
(
l
.
getType
());
result
=
Comparison
.
compareNotNull
(
database
,
l
,
r
,
Comparison
.
EQUAL
);
if
(
result
)
{
break
;
}
}
}
}
else
{
if
(
value
==
ValueNull
.
INSTANCE
)
{
hasNull
=
true
;
}
else
{
value
=
value
.
convertTo
(
l
.
getType
());
result
=
Comparison
.
compareNotNull
(
database
,
l
,
value
,
Comparison
.
EQUAL
);
}
}
if
(!
result
&&
hasNull
)
{
return
ValueNull
.
INSTANCE
;
}
return
ValueBoolean
.
get
(
result
);
}
@Override
public
void
mapColumns
(
ColumnResolver
resolver
,
int
level
)
{
left
.
mapColumns
(
resolver
,
level
);
}
@Override
public
Expression
optimize
(
Session
session
)
{
left
=
left
.
optimize
(
session
);
if
(
left
.
isConstant
()
&&
left
==
ValueExpression
.
getNull
())
{
return
left
;
}
return
this
;
}
@Override
public
void
createIndexConditions
(
Session
session
,
TableFilter
filter
)
{
if
(!(
left
instanceof
ExpressionColumn
))
{
return
;
}
ExpressionColumn
l
=
(
ExpressionColumn
)
left
;
if
(
filter
!=
l
.
getTableFilter
())
{
return
;
}
filter
.
addIndexCondition
(
IndexCondition
.
getInList
(
l
,
new
ParameterList
(
parameter
)));
}
@Override
public
void
setEvaluatable
(
TableFilter
tableFilter
,
boolean
b
)
{
left
.
setEvaluatable
(
tableFilter
,
b
);
}
@Override
public
String
getSQL
()
{
return
'('
+
left
.
getSQL
()
+
" = ANY("
+
parameter
.
getSQL
()
+
"))"
;
}
@Override
public
void
updateAggregate
(
Session
session
)
{
left
.
updateAggregate
(
session
);
}
@Override
public
boolean
isEverything
(
ExpressionVisitor
visitor
)
{
return
left
.
isEverything
(
visitor
)
&&
parameter
.
isEverything
(
visitor
);
}
@Override
public
int
getCost
()
{
return
left
.
getCost
();
}
}
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
浏览文件 @
3e3a604a
...
...
@@ -99,6 +99,7 @@ public class TestPreparedStatement extends TestBase {
conn
.
close
();
testPreparedStatementWithLiteralsNone
();
testPreparedStatementWithIndexedParameterAndLiteralsNone
();
testPreparedStatementWithAnyParameter
();
deleteDb
(
"preparedStatement"
);
}
...
...
@@ -1491,7 +1492,43 @@ public class TestPreparedStatement extends TestBase {
deleteDb
(
"preparedStatement"
);
}
private
void
testPreparedStatementWithAnyParameter
()
throws
SQLException
{
deleteDb
(
"preparedStatement"
);
Connection
conn
=
getConnection
(
"preparedStatement"
);
conn
.
prepareStatement
(
"CREATE TABLE TEST(ID INT PRIMARY KEY, VALUE INT UNIQUE)"
).
execute
();
PreparedStatement
ps
=
conn
.
prepareStatement
(
"INSERT INTO TEST(ID, VALUE) VALUES (?, ?)"
);
for
(
int
i
=
0
;
i
<
10_000
;
i
++)
{
ps
.
setInt
(
1
,
i
);
ps
.
setInt
(
2
,
i
*
10
);
ps
.
executeUpdate
();
}
Object
[]
values
=
{-
100
,
10
,
200
,
3_000
,
40_000
,
500_000
};
int
[]
expected
=
{
1
,
20
,
300
,
4_000
};
// Ensure that other methods return the same results
ps
=
conn
.
prepareStatement
(
"SELECT ID FROM TEST WHERE VALUE IN (SELECT * FROM TABLE(X INT=?)) ORDER BY ID"
);
anyParameterCheck
(
ps
,
values
,
expected
);
ps
=
conn
.
prepareStatement
(
"SELECT ID FROM TEST INNER JOIN TABLE(X INT=?) T ON TEST.VALUE = T.X"
);
anyParameterCheck
(
ps
,
values
,
expected
);
// Test expression = ANY(?)
ps
=
conn
.
prepareStatement
(
"SELECT ID FROM TEST WHERE VALUE = ANY(?)"
);
assertThrows
(
ErrorCode
.
PARAMETER_NOT_SET_1
,
ps
).
executeQuery
();
anyParameterCheck
(
ps
,
values
,
expected
);
anyParameterCheck
(
ps
,
300
,
new
int
[]
{
30
});
anyParameterCheck
(
ps
,
-
5
,
new
int
[
0
]);
conn
.
close
();
deleteDb
(
"preparedStatement"
);
}
private
void
anyParameterCheck
(
PreparedStatement
ps
,
Object
values
,
int
[]
expected
)
throws
SQLException
{
ps
.
setObject
(
1
,
values
);
try
(
ResultSet
rs
=
ps
.
executeQuery
())
{
for
(
int
exp
:
expected
)
{
assertTrue
(
rs
.
next
());
assertEquals
(
exp
,
rs
.
getInt
(
1
));
}
assertFalse
(
rs
.
next
());
}
}
private
void
checkBigDecimal
(
ResultSet
rs
,
String
[]
value
)
throws
SQLException
{
for
(
String
v
:
value
)
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论