Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
apache
Shardingsphere
提交
1f7ed616
Shardingsphere
项目概览
apache
/
Shardingsphere
通知
56
Star
3
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Shardingsphere
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
1f7ed616
编写于
7月 06, 2016
作者:
G
gaohongtao
提交者:
gaoht
7月 06, 2016
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix #36 cannot reuse ShardingPreparedStatement
fix #114 ShardingPreparedStatement batch execution parse sql
上级
fe49c45d
变更
27
隐藏空白更改
内联
并排
Showing
27 changed file
with
571 addition
and
133 deletion
+571
-133
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/PreparedStatementExecutor.java
...rame/rdb/sharding/executor/PreparedStatementExecutor.java
+75
-0
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/wrapper/BatchPreparedStatementExecutorWrapper.java
...ecutor/wrapper/BatchPreparedStatementExecutorWrapper.java
+42
-0
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/wrapper/PreparedStatementExecutorWrapper.java
...ng/executor/wrapper/PreparedStatementExecutorWrapper.java
+4
-3
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingPreparedStatement.java
.../ddframe/rdb/sharding/jdbc/ShardingPreparedStatement.java
+60
-63
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingStatement.java
...dangdang/ddframe/rdb/sharding/jdbc/ShardingStatement.java
+12
-8
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/parser/result/router/Condition.java
.../ddframe/rdb/sharding/parser/result/router/Condition.java
+5
-3
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/parser/result/router/ConditionContext.java
...e/rdb/sharding/parser/result/router/ConditionContext.java
+21
-5
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/parser/visitor/ParseContext.java
...ang/ddframe/rdb/sharding/parser/visitor/ParseContext.java
+50
-13
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/parser/visitor/basic/mysql/MySQLEvalVisitor.java
...sharding/parser/visitor/basic/mysql/MySQLEvalVisitor.java
+58
-0
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/router/PreparedSQLRouter.java
...ngdang/ddframe/rdb/sharding/router/PreparedSQLRouter.java
+58
-0
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/router/SQLRouteEngine.java
.../dangdang/ddframe/rdb/sharding/router/SQLRouteEngine.java
+12
-2
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/AbstractDBUnitTest.java
...om/dangdang/ddframe/rdb/integrate/AbstractDBUnitTest.java
+12
-12
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/dbtbl/common/statement/AbstractShardingBothForStatementWithDMLTest.java
...tatement/AbstractShardingBothForStatementWithDMLTest.java
+1
-1
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/dbtbl/statically/statement/StaticShardingBothForStatementWithDMLTest.java
.../statement/StaticShardingBothForStatementWithDMLTest.java
+2
-2
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/statement/ShardingMasterSlaveForStatementWithDMLTest.java
...statement/ShardingMasterSlaveForStatementWithDMLTest.java
+4
-4
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingPreparedStatementTest.java
...rame/rdb/sharding/jdbc/ShardingPreparedStatementTest.java
+49
-11
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/AbstractBaseParseTest.java
...ng/ddframe/rdb/sharding/parser/AbstractBaseParseTest.java
+3
-0
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/AllParserTests.java
.../dangdang/ddframe/rdb/sharding/parser/AllParserTests.java
+3
-1
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/jaxb/Condition.java
.../dangdang/ddframe/rdb/sharding/parser/jaxb/Condition.java
+6
-4
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/result/SQLParsedResultTest.java
...frame/rdb/sharding/parser/result/SQLParsedResultTest.java
+1
-1
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/visitor/basic/mysql/MySQLEvalVisitorTest.java
...ding/parser/visitor/basic/mysql/MySQLEvalVisitorTest.java
+82
-0
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/one_param/delete.xml
...ding/parser/mysql/prepared_statement/one_param/delete.xml
+1
-0
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/one_param/insert.xml
...ding/parser/mysql/prepared_statement/one_param/insert.xml
+1
-0
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/one_param/select.xml
...ding/parser/mysql/prepared_statement/one_param/select.xml
+1
-0
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/one_param/update.xml
...ding/parser/mysql/prepared_statement/one_param/update.xml
+1
-0
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/two_params/select.xml
...ing/parser/mysql/prepared_statement/two_params/select.xml
+2
-0
sharding-jdbc-doc/content/post/release_notes.md
sharding-jdbc-doc/content/post/release_notes.md
+5
-0
未找到文件。
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/PreparedStatementExecutor.java
浏览文件 @
1f7ed616
...
...
@@ -23,6 +23,7 @@ import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEventBus;
import
com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEvent
;
import
com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEventBus
;
import
com.dangdang.ddframe.rdb.sharding.executor.event.EventExecutionType
;
import
com.dangdang.ddframe.rdb.sharding.executor.wrapper.BatchPreparedStatementExecutorWrapper
;
import
com.dangdang.ddframe.rdb.sharding.executor.wrapper.PreparedStatementExecutorWrapper
;
import
com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext
;
import
com.google.common.base.Optional
;
...
...
@@ -194,6 +195,80 @@ public final class PreparedStatementExecutor {
return
result
;
}
/**
* 执行批量接口.
*
* @return 每个
*/
public
int
[]
executeBatch
()
{
Context
context
=
MetricsContext
.
start
(
"ShardingPreparedStatement-executeUpdate"
);
postExecutionEvents
();
final
boolean
isExceptionThrown
=
ExecutorExceptionHandler
.
isExceptionThrown
();
final
Map
<
String
,
Object
>
dataMap
=
ExecutorDataMap
.
getDataMap
();
try
{
if
(
1
==
preparedStatementExecutorWrappers
.
size
())
{
return
executeBatchInternal
((
BatchPreparedStatementExecutorWrapper
)
preparedStatementExecutorWrappers
.
iterator
().
next
(),
isExceptionThrown
,
dataMap
);
}
return
executorEngine
.
execute
(
preparedStatementExecutorWrappers
,
new
ExecuteUnit
<
PreparedStatementExecutorWrapper
,
int
[]>()
{
@Override
public
int
[]
execute
(
final
PreparedStatementExecutorWrapper
input
)
throws
Exception
{
return
executeBatchInternal
((
BatchPreparedStatementExecutorWrapper
)
input
,
isExceptionThrown
,
dataMap
);
}
},
new
MergeUnit
<
int
[],
int
[]>()
{
@Override
public
int
[]
merge
(
final
List
<
int
[]>
results
)
{
if
(
null
==
results
)
{
return
new
int
[]{
0
};
}
int
length
=
0
;
for
(
int
[]
array
:
results
)
{
length
+=
array
.
length
;
}
int
[]
result
=
new
int
[
length
];
int
pos
=
0
;
for
(
int
[]
array
:
results
)
{
System
.
arraycopy
(
array
,
0
,
result
,
pos
,
array
.
length
);
pos
+=
array
.
length
;
}
return
result
;
}
});
}
finally
{
MetricsContext
.
stop
(
context
);
}
}
private
int
[]
executeBatchInternal
(
final
BatchPreparedStatementExecutorWrapper
batchPreparedStatementExecutorWrapper
,
final
boolean
isExceptionThrown
,
final
Map
<
String
,
Object
>
dataMap
)
{
int
[]
result
;
ExecutorExceptionHandler
.
setExceptionThrown
(
isExceptionThrown
);
ExecutorDataMap
.
setDataMap
(
dataMap
);
try
{
result
=
batchPreparedStatementExecutorWrapper
.
getPreparedStatement
().
executeBatch
();
}
catch
(
final
SQLException
ex
)
{
postBatchExecutionEventsAfterExecution
(
batchPreparedStatementExecutorWrapper
,
EventExecutionType
.
EXECUTE_FAILURE
,
Optional
.
of
(
ex
));
ExecutorExceptionHandler
.
handleException
(
ex
);
return
null
;
}
postBatchExecutionEventsAfterExecution
(
batchPreparedStatementExecutorWrapper
);
return
result
;
}
private
void
postBatchExecutionEventsAfterExecution
(
final
BatchPreparedStatementExecutorWrapper
batchPreparedStatementExecutorWrapper
)
{
postBatchExecutionEventsAfterExecution
(
batchPreparedStatementExecutorWrapper
,
EventExecutionType
.
EXECUTE_SUCCESS
,
Optional
.<
SQLException
>
absent
());
}
private
void
postBatchExecutionEventsAfterExecution
(
final
BatchPreparedStatementExecutorWrapper
batchPreparedStatementExecutorWrapper
,
final
EventExecutionType
eventExecutionType
,
final
Optional
<
SQLException
>
exp
)
{
for
(
DMLExecutionEvent
each
:
batchPreparedStatementExecutorWrapper
.
getDmlExecutionEvents
())
{
each
.
setEventExecutionType
(
eventExecutionType
);
each
.
setExp
(
exp
);
DMLExecutionEventBus
.
post
(
each
);
}
}
private
void
postExecutionEvents
()
{
for
(
PreparedStatementExecutorWrapper
each
:
preparedStatementExecutorWrappers
)
{
if
(
each
.
getDMLExecutionEvent
().
isPresent
())
{
...
...
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/wrapper/BatchPreparedStatementExecutorWrapper.java
0 → 100644
浏览文件 @
1f7ed616
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package
com.dangdang.ddframe.rdb.sharding.executor.wrapper
;
import
com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEvent
;
import
com.dangdang.ddframe.rdb.sharding.router.SQLExecutionUnit
;
import
lombok.Getter
;
import
java.sql.PreparedStatement
;
import
java.util.LinkedList
;
import
java.util.List
;
/**
* 批量操作执行上下文.
* 批量操作只支持DML语句,故只包含DML操作的事件.
*
* @author gaohongtao
*/
@Getter
public
class
BatchPreparedStatementExecutorWrapper
extends
PreparedStatementExecutorWrapper
{
private
final
List
<
DMLExecutionEvent
>
dmlExecutionEvents
=
new
LinkedList
<>();
public
BatchPreparedStatementExecutorWrapper
(
final
PreparedStatement
preparedStatement
,
final
List
<
Object
>
parameters
,
final
SQLExecutionUnit
sqlExecutionUnit
)
{
super
(
preparedStatement
,
parameters
,
sqlExecutionUnit
);
}
}
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/executor/wrapper/PreparedStatementExecutorWrapper.java
浏览文件 @
1f7ed616
...
...
@@ -21,6 +21,7 @@ import com.dangdang.ddframe.rdb.sharding.executor.event.DMLExecutionEvent;
import
com.dangdang.ddframe.rdb.sharding.executor.event.DQLExecutionEvent
;
import
com.dangdang.ddframe.rdb.sharding.router.SQLExecutionUnit
;
import
com.google.common.base.Optional
;
import
com.google.common.collect.Lists
;
import
lombok.Getter
;
import
java.sql.PreparedStatement
;
...
...
@@ -31,7 +32,7 @@ import java.util.List;
*
* @author zhangliang
*/
public
final
class
PreparedStatementExecutorWrapper
extends
AbstractExecutorWrapper
{
public
class
PreparedStatementExecutorWrapper
extends
AbstractExecutorWrapper
{
@Getter
private
final
PreparedStatement
preparedStatement
;
...
...
@@ -45,10 +46,10 @@ public final class PreparedStatementExecutorWrapper extends AbstractExecutorWrap
super
(
sqlExecutionUnit
);
this
.
preparedStatement
=
preparedStatement
;
if
(
isDML
())
{
dmlExecutionEvent
=
Optional
.
of
(
new
DMLExecutionEvent
(
getSqlExecutionUnit
().
getDataSource
(),
getSqlExecutionUnit
().
getSql
(),
parameters
));
dmlExecutionEvent
=
Optional
.
of
(
new
DMLExecutionEvent
(
getSqlExecutionUnit
().
getDataSource
(),
getSqlExecutionUnit
().
getSql
(),
Lists
.
newArrayList
(
parameters
)
));
dqlExecutionEvent
=
Optional
.
absent
();
}
else
if
(
isDQL
())
{
dqlExecutionEvent
=
Optional
.
of
(
new
DQLExecutionEvent
(
getSqlExecutionUnit
().
getDataSource
(),
getSqlExecutionUnit
().
getSql
(),
parameters
));
dqlExecutionEvent
=
Optional
.
of
(
new
DQLExecutionEvent
(
getSqlExecutionUnit
().
getDataSource
(),
getSqlExecutionUnit
().
getSql
(),
Lists
.
newArrayList
(
parameters
)
));
dmlExecutionEvent
=
Optional
.
absent
();
}
else
{
dmlExecutionEvent
=
Optional
.
absent
();
...
...
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingPreparedStatement.java
浏览文件 @
1f7ed616
...
...
@@ -18,24 +18,23 @@
package
com.dangdang.ddframe.rdb.sharding.jdbc
;
import
com.dangdang.ddframe.rdb.sharding.executor.PreparedStatementExecutor
;
import
com.dangdang.ddframe.rdb.sharding.executor.wrapper.BatchPreparedStatementExecutorWrapper
;
import
com.dangdang.ddframe.rdb.sharding.executor.wrapper.PreparedStatementExecutorWrapper
;
import
com.dangdang.ddframe.rdb.sharding.jdbc.adapter.AbstractPreparedStatementAdapter
;
import
com.dangdang.ddframe.rdb.sharding.merger.ResultSetFactory
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.merger.MergeContext
;
import
com.dangdang.ddframe.rdb.sharding.router.PreparedSQLRouter
;
import
com.dangdang.ddframe.rdb.sharding.router.SQLExecutionUnit
;
import
com.dangdang.ddframe.rdb.sharding.router.SQLRouteResult
;
import
com.google.common.base.Function
;
import
com.google.common.collect.Lists
;
import
java.sql.Connection
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.LinkedList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* 支持分片的预编译语句对象.
...
...
@@ -45,9 +44,9 @@ import java.util.List;
*/
public
final
class
ShardingPreparedStatement
extends
AbstractPreparedStatementAdapter
{
private
final
String
sql
;
private
final
PreparedSQLRouter
preparedSQLRouter
;
private
final
List
<
PreparedStatementExecutorWrapper
>
cachedRoutedPreparedStatements
=
new
LinkedList
<>();
private
final
Map
<
PreparedStatement
,
PreparedStatementExecutorWrapper
>
cachedRoutePreparedStatementMap
=
new
HashMap
<>();
private
Integer
autoGeneratedKeys
;
...
...
@@ -55,10 +54,6 @@ public final class ShardingPreparedStatement extends AbstractPreparedStatementAd
private
String
[]
columnNames
;
private
boolean
hasExecuted
;
private
final
List
<
List
<
Object
>>
batchParameters
=
new
ArrayList
<>();
public
ShardingPreparedStatement
(
final
ShardingConnection
shardingConnection
,
final
String
sql
)
throws
SQLException
{
this
(
shardingConnection
,
sql
,
ResultSet
.
TYPE_FORWARD_ONLY
,
ResultSet
.
CONCUR_READ_ONLY
,
ResultSet
.
HOLD_CURSORS_OVER_COMMIT
);
}
...
...
@@ -69,9 +64,9 @@ public final class ShardingPreparedStatement extends AbstractPreparedStatementAd
}
public
ShardingPreparedStatement
(
final
ShardingConnection
shardingConnection
,
final
String
sql
,
final
int
resultSetType
,
final
int
resultSetConcurrency
,
final
int
resultSetHoldability
)
throws
SQLException
{
final
String
sql
,
final
int
resultSetType
,
final
int
resultSetConcurrency
,
final
int
resultSetHoldability
)
{
super
(
shardingConnection
,
resultSetType
,
resultSetConcurrency
,
resultSetHoldability
);
this
.
sql
=
sql
;
preparedSQLRouter
=
shardingConnection
.
getShardingContext
().
getSqlRouteEngine
().
prepareSQL
(
sql
)
;
}
public
ShardingPreparedStatement
(
final
ShardingConnection
shardingConnection
,
final
String
sql
,
final
int
autoGeneratedKeys
)
throws
SQLException
{
...
...
@@ -91,82 +86,84 @@ public final class ShardingPreparedStatement extends AbstractPreparedStatementAd
@Override
public
ResultSet
executeQuery
()
throws
SQLException
{
hasExecuted
=
true
;
setCurrentResultSet
(
ResultSetFactory
.
getResultSet
(
new
PreparedStatementExecutor
(
getShardingConnection
().
getShardingContext
().
getExecutorEngine
(),
getRoutedPreparedStatements
()).
executeQuery
(),
getMergeContext
()));
return
getCurrentResultSet
();
ResultSet
rs
;
try
{
rs
=
ResultSetFactory
.
getResultSet
(
new
PreparedStatementExecutor
(
getShardingConnection
().
getShardingContext
().
getExecutorEngine
(),
routeSQL
()).
executeQuery
(),
getMergeContext
());
}
finally
{
clearRouteContext
();
}
setCurrentResultSet
(
rs
);
return
rs
;
}
@Override
public
int
executeUpdate
()
throws
SQLException
{
hasExecuted
=
true
;
return
new
PreparedStatementExecutor
(
getShardingConnection
().
getShardingContext
().
getExecutorEngine
(),
getRoutedPreparedStatements
()).
executeUpdate
();
try
{
return
new
PreparedStatementExecutor
(
getShardingConnection
().
getShardingContext
().
getExecutorEngine
(),
routeSQL
()).
executeUpdate
();
}
finally
{
clearRouteContext
();
}
}
@Override
public
boolean
execute
()
throws
SQLException
{
hasExecuted
=
true
;
return
new
PreparedStatementExecutor
(
getShardingConnection
().
getShardingContext
().
getExecutorEngine
(),
getRoutedPreparedStatements
()).
execute
();
try
{
return
new
PreparedStatementExecutor
(
getShardingConnection
().
getShardingContext
().
getExecutorEngine
(),
routeSQL
()).
execute
();
}
finally
{
clearRouteContext
();
}
}
private
void
clearRouteContext
()
throws
SQLException
{
clearParameters
();
setCurrentResultSet
(
null
);
}
@Override
public
void
addBatch
()
throws
SQLException
{
batchParameters
.
add
(
Lists
.
newArrayList
(
getParameters
()));
getParameters
().
clear
();
try
{
for
(
PreparedStatementExecutorWrapper
each
:
routeSQL
())
{
each
.
getPreparedStatement
().
addBatch
();
BatchPreparedStatementExecutorWrapper
wrapper
;
if
(
cachedRoutePreparedStatementMap
.
containsKey
(
each
.
getPreparedStatement
()))
{
wrapper
=
(
BatchPreparedStatementExecutorWrapper
)
cachedRoutePreparedStatementMap
.
get
(
each
.
getPreparedStatement
());
}
else
{
wrapper
=
new
BatchPreparedStatementExecutorWrapper
(
each
.
getPreparedStatement
(),
getParameters
(),
each
.
getSqlExecutionUnit
());
cachedRoutePreparedStatementMap
.
put
(
each
.
getPreparedStatement
(),
wrapper
);
}
if
(
each
.
getDMLExecutionEvent
().
isPresent
())
{
wrapper
.
getDmlExecutionEvents
().
add
(
each
.
getDMLExecutionEvent
().
get
());
}
}
}
finally
{
clearRouteContext
();
}
}
@Override
public
void
clearBatch
()
throws
SQLException
{
batchParameters
.
clear
();
cachedRoutePreparedStatementMap
.
clear
();
clearRouteContext
();
}
@Override
public
int
[]
executeBatch
()
throws
SQLException
{
hasExecuted
=
true
;
int
[]
result
=
new
int
[
batchParameters
.
size
()];
int
i
=
0
;
for
(
List
<
Object
>
each
:
batchParameters
)
{
List
<
PreparedStatementExecutorWrapper
>
routePreparedStatements
=
routeSQL
(
each
);
cachedRoutedPreparedStatements
.
addAll
(
routePreparedStatements
);
result
[
i
++]
=
new
PreparedStatementExecutor
(
getShardingConnection
().
getShardingContext
().
getExecutorEngine
(),
routePreparedStatements
).
executeUpdate
();
}
return
result
;
}
private
List
<
PreparedStatementExecutorWrapper
>
getRoutedPreparedStatements
()
throws
SQLException
{
if
(!
hasExecuted
)
{
return
Collections
.
emptyList
();
}
routeIfNeed
();
return
cachedRoutedPreparedStatements
;
}
@Override
public
List
<?
extends
Statement
>
getRoutedStatements
()
throws
SQLException
{
return
Lists
.
transform
(
getRoutedPreparedStatements
(),
new
Function
<
PreparedStatementExecutorWrapper
,
Statement
>()
{
@Override
public
Statement
apply
(
final
PreparedStatementExecutorWrapper
input
)
{
return
input
.
getPreparedStatement
();
}
});
}
private
void
routeIfNeed
()
throws
SQLException
{
if
(!
cachedRoutedPreparedStatements
.
isEmpty
())
{
return
;
try
{
return
new
PreparedStatementExecutor
(
getShardingConnection
().
getShardingContext
().
getExecutorEngine
(),
cachedRoutePreparedStatementMap
.
values
()).
executeBatch
();
}
finally
{
clearBatch
();
}
cachedRoutedPreparedStatements
.
addAll
(
routeSQL
(
getParameters
()));
}
private
List
<
PreparedStatementExecutorWrapper
>
routeSQL
(
final
List
<
Object
>
parameters
)
throws
SQLException
{
private
List
<
PreparedStatementExecutorWrapper
>
routeSQL
()
throws
SQLException
{
List
<
Object
>
parameters
=
getParameters
();
List
<
PreparedStatementExecutorWrapper
>
result
=
new
ArrayList
<>();
SQLRouteResult
sqlRouteResult
=
getShardingConnection
().
getShardingContext
().
getSqlRouteEngine
().
route
(
sql
,
parameters
);
SQLRouteResult
sqlRouteResult
=
preparedSQLRouter
.
route
(
parameters
);
MergeContext
mergeContext
=
sqlRouteResult
.
getMergeContext
();
setMergeContext
(
mergeContext
);
for
(
SQLExecutionUnit
each
:
sqlRouteResult
.
getExecutionUnits
())
{
PreparedStatement
preparedStatement
=
generatePrepare
Statement
(
getShardingConnection
().
getConnection
(
each
.
getDataSource
(),
sqlRouteResult
.
getSqlStatementType
()),
each
.
getSql
());
PreparedStatement
preparedStatement
=
(
PreparedStatement
)
get
Statement
(
getShardingConnection
().
getConnection
(
each
.
getDataSource
(),
sqlRouteResult
.
getSqlStatementType
()),
each
.
getSql
());
replayMethodsInvocation
(
preparedStatement
);
setParameters
(
preparedStatement
,
parameters
);
result
.
add
(
new
PreparedStatementExecutorWrapper
(
preparedStatement
,
parameters
,
each
));
...
...
@@ -174,7 +171,7 @@ public final class ShardingPreparedStatement extends AbstractPreparedStatementAd
return
result
;
}
pr
ivate
PreparedStatement
generatePrepar
eStatement
(
final
Connection
conn
,
final
String
shardingSql
)
throws
SQLException
{
pr
otected
PreparedStatement
generat
eStatement
(
final
Connection
conn
,
final
String
shardingSql
)
throws
SQLException
{
if
(
null
!=
autoGeneratedKeys
)
{
return
conn
.
prepareStatement
(
shardingSql
,
autoGeneratedKeys
);
}
...
...
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingStatement.java
浏览文件 @
1f7ed616
...
...
@@ -22,7 +22,6 @@ import com.dangdang.ddframe.rdb.sharding.executor.wrapper.StatementExecutorWrapp
import
com.dangdang.ddframe.rdb.sharding.jdbc.adapter.AbstractStatementAdapter
;
import
com.dangdang.ddframe.rdb.sharding.merger.ResultSetFactory
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.merger.MergeContext
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.router.SQLStatementType
;
import
com.dangdang.ddframe.rdb.sharding.router.SQLExecutionUnit
;
import
com.dangdang.ddframe.rdb.sharding.router.SQLRouteResult
;
import
com.google.common.base.Charsets
;
...
...
@@ -62,13 +61,13 @@ public class ShardingStatement extends AbstractStatementAdapter {
@Getter
private
final
int
resultSetHoldability
;
@Getter
(
AccessLevel
.
PROTECTED
)
private
final
Map
<
HashCode
,
Statement
>
cachedRoutedStatements
=
new
HashMap
<>();
@Getter
(
AccessLevel
.
PROTECTED
)
@Setter
(
AccessLevel
.
PROTECTED
)
private
MergeContext
mergeContext
;
@Getter
(
AccessLevel
.
PROTECTED
)
@Setter
(
AccessLevel
.
PROTECTED
)
private
ResultSet
currentResultSet
;
...
...
@@ -147,25 +146,30 @@ public class ShardingStatement extends AbstractStatementAdapter {
SQLRouteResult
sqlRouteResult
=
shardingConnection
.
getShardingContext
().
getSqlRouteEngine
().
route
(
sql
);
mergeContext
=
sqlRouteResult
.
getMergeContext
();
for
(
SQLExecutionUnit
each
:
sqlRouteResult
.
getExecutionUnits
())
{
result
.
addStatement
(
new
StatementExecutorWrapper
(
generateStatement
(
each
.
getSql
(),
each
.
getDataSource
(),
sqlRouteResult
.
getSqlStatementType
()),
each
));
Statement
statement
=
getStatement
(
shardingConnection
.
getConnection
(
each
.
getDataSource
(),
sqlRouteResult
.
getSqlStatementType
()),
each
.
getSql
());
replayMethodsInvocation
(
statement
);
result
.
addStatement
(
new
StatementExecutorWrapper
(
statement
,
each
));
}
return
result
;
}
pr
ivate
Statement
generateStatement
(
final
String
sql
,
final
String
dataSourceName
,
final
SQLStatementType
sqlStatementType
)
throws
SQLException
{
HashCode
hashCode
=
Hashing
.
md5
().
newHasher
().
put
String
(
sql
,
Charsets
.
UTF_8
).
putString
(
dataSourceName
,
Charsets
.
UTF_8
).
hash
();
pr
otected
Statement
getStatement
(
final
Connection
connection
,
final
String
sql
)
throws
SQLException
{
HashCode
hashCode
=
Hashing
.
md5
().
newHasher
().
put
Int
(
connection
.
hashCode
()).
putString
(
sql
,
Charsets
.
UTF_8
).
hash
();
if
(
cachedRoutedStatements
.
containsKey
(
hashCode
))
{
return
cachedRoutedStatements
.
get
(
hashCode
);
}
Connection
connection
=
shardingConnection
.
getConnection
(
dataSourceName
,
sqlStatementType
);
Statement
statement
=
generateStatement
(
connection
,
sql
);
cachedRoutedStatements
.
put
(
hashCode
,
statement
);
return
statement
;
}
protected
Statement
generateStatement
(
final
Connection
connection
,
final
String
sql
)
throws
SQLException
{
Statement
result
;
if
(
0
==
resultSetHoldability
)
{
result
=
connection
.
createStatement
(
resultSetType
,
resultSetConcurrency
);
}
else
{
result
=
connection
.
createStatement
(
resultSetType
,
resultSetConcurrency
,
resultSetHoldability
);
}
replayMethodsInvocation
(
result
);
cachedRoutedStatements
.
put
(
hashCode
,
result
);
return
result
;
}
...
...
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/parser/result/router/Condition.java
浏览文件 @
1f7ed616
...
...
@@ -17,14 +17,14 @@
package
com.dangdang.ddframe.rdb.sharding.parser.result.router
;
import
java.util.ArrayList
;
import
java.util.List
;
import
lombok.EqualsAndHashCode
;
import
lombok.Getter
;
import
lombok.RequiredArgsConstructor
;
import
lombok.ToString
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* 条件对象.
*
...
...
@@ -42,6 +42,8 @@ public final class Condition {
private
final
List
<
Comparable
<?>>
values
=
new
ArrayList
<>();
private
final
List
<
Integer
>
valueIndices
=
new
ArrayList
<>();
/**
* 列对象.
*
...
...
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/parser/result/router/ConditionContext.java
浏览文件 @
1f7ed616
...
...
@@ -17,16 +17,16 @@
package
com.dangdang.ddframe.rdb.sharding.parser.result.router
;
import
java.util.Collection
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.router.Condition.BinaryOperator
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.router.Condition.Column
;
import
com.google.common.base.Optional
;
import
lombok.ToString
;
import
java.util.Collection
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* 条件对象上下文.
*
...
...
@@ -85,4 +85,20 @@ public final class ConditionContext {
public
Collection
<
Condition
>
getAllConditions
()
{
return
conditions
.
values
();
}
public
void
setNewConditionValue
(
final
List
<
Object
>
parameters
)
{
for
(
Condition
each
:
conditions
.
values
())
{
if
(
each
.
getValueIndices
().
isEmpty
())
{
continue
;
}
for
(
int
i
=
0
;
i
<
each
.
getValueIndices
().
size
();
i
++)
{
Object
value
=
parameters
.
get
(
each
.
getValueIndices
().
get
(
i
));
if
(
value
instanceof
Comparable
<?>)
{
each
.
getValues
().
set
(
i
,
(
Comparable
<?>)
value
);
}
else
{
each
.
getValues
().
set
(
i
,
""
);
}
}
}
}
}
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/parser/visitor/ParseContext.java
浏览文件 @
1f7ed616
...
...
@@ -24,7 +24,9 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import
com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr
;
import
com.alibaba.druid.sql.ast.expr.SQLPropertyExpr
;
import
com.alibaba.druid.sql.ast.statement.SQLExprTableSource
;
import
com.alibaba.druid.sql.visitor.SQLEvalVisitor
;
import
com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils
;
import
com.alibaba.druid.util.JdbcUtils
;
import
com.dangdang.ddframe.rdb.sharding.constants.DatabaseType
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.SQLParsedResult
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.merger.AggregationColumn
;
...
...
@@ -37,9 +39,11 @@ import com.dangdang.ddframe.rdb.sharding.parser.result.router.Condition.BinaryOp
import
com.dangdang.ddframe.rdb.sharding.parser.result.router.Condition.Column
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.router.ConditionContext
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.router.Table
;
import
com.dangdang.ddframe.rdb.sharding.parser.visitor.basic.mysql.MySQLEvalVisitor
;
import
com.dangdang.ddframe.rdb.sharding.util.SQLUtil
;
import
com.google.common.base.Optional
;
import
lombok.Getter
;
import
lombok.RequiredArgsConstructor
;
import
lombok.Setter
;
import
java.util.ArrayList
;
...
...
@@ -136,9 +140,9 @@ public final class ParseContext {
if
(!
column
.
isPresent
()
||
!
shardingColumns
.
contains
(
column
.
get
().
getColumnName
()))
{
return
;
}
List
<
Comparable
<?>
>
values
=
new
ArrayList
<>(
valueExprList
.
size
());
List
<
ValuePair
>
values
=
new
ArrayList
<>(
valueExprList
.
size
());
for
(
SQLExpr
each
:
valueExprList
)
{
Comparable
<?>
evalValue
=
evalExpression
(
databaseType
,
each
,
parameters
);
ValuePair
evalValue
=
evalExpression
(
databaseType
,
each
,
parameters
);
if
(
null
!=
evalValue
)
{
values
.
add
(
evalValue
);
}
...
...
@@ -164,13 +168,13 @@ public final class ParseContext {
if
(!
shardingColumns
.
contains
(
column
.
getColumnName
()))
{
return
;
}
Comparable
<?>
value
=
evalExpression
(
databaseType
,
valueExpr
,
parameters
);
ValuePair
value
=
evalExpression
(
databaseType
,
valueExpr
,
parameters
);
if
(
null
!=
value
)
{
addCondition
(
column
,
operator
,
Collections
.
<
Comparable
<?>>
singletonList
(
value
));
addCondition
(
column
,
operator
,
Collections
.
singletonList
(
value
));
}
}
private
void
addCondition
(
final
Column
column
,
final
BinaryOperator
operator
,
final
List
<
Comparable
<?>>
value
s
)
{
private
void
addCondition
(
final
Column
column
,
final
BinaryOperator
operator
,
final
List
<
ValuePair
>
valuePair
s
)
{
Optional
<
Condition
>
optionalCondition
=
currentConditionContext
.
find
(
column
.
getTableName
(),
column
.
getColumnName
(),
operator
);
Condition
condition
;
// TODO 待讨论
...
...
@@ -180,23 +184,48 @@ public final class ParseContext {
condition
=
new
Condition
(
column
,
operator
);
currentConditionContext
.
add
(
condition
);
}
condition
.
getValues
().
addAll
(
values
);
for
(
ValuePair
each
:
valuePairs
)
{
condition
.
getValues
().
add
(
each
.
value
);
if
(
each
.
paramIndex
>
-
1
)
{
condition
.
getValueIndices
().
add
(
each
.
paramIndex
);
}
}
}
private
Comparable
<?>
evalExpression
(
final
DatabaseType
databaseType
,
final
SQLObject
sqlObject
,
final
List
<
Object
>
parameters
)
{
private
ValuePair
evalExpression
(
final
DatabaseType
databaseType
,
final
SQLObject
sqlObject
,
final
List
<
Object
>
parameters
)
{
if
(
sqlObject
instanceof
SQLMethodInvokeExpr
)
{
// TODO 解析函数中的sharingValue不支持
return
null
;
}
Object
result
=
SQLEvalVisitorUtils
.
eval
(
databaseType
.
name
().
toLowerCase
(),
sqlObject
,
parameters
,
false
);
if
(
null
==
result
)
{
SQLEvalVisitor
visitor
;
switch
(
databaseType
.
name
().
toLowerCase
())
{
case
JdbcUtils
.
MYSQL
:
case
JdbcUtils
.
H2
:
visitor
=
new
MySQLEvalVisitor
();
break
;
default
:
visitor
=
SQLEvalVisitorUtils
.
createEvalVisitor
(
databaseType
.
name
());
}
visitor
.
setParameters
(
parameters
);
sqlObject
.
accept
(
visitor
);
Object
value
=
SQLEvalVisitorUtils
.
getValue
(
sqlObject
);
if
(
null
==
value
)
{
// TODO 对于NULL目前解析为空字符串,此处待考虑解决方法
return
null
;
}
if
(
result
instanceof
Comparable
<?>)
{
return
(
Comparable
<?>)
result
;
Comparable
<?>
finalValue
;
if
(
value
instanceof
Comparable
<?>)
{
finalValue
=
(
Comparable
<?>)
value
;
}
else
{
finalValue
=
""
;
}
// TODO 对于NULL目前解析为空字符串,此处待考虑解决方法
return
""
;
Integer
index
=
(
Integer
)
sqlObject
.
getAttribute
(
MySQLEvalVisitor
.
EVAL_VAR_INDEX
);
if
(
null
==
index
)
{
index
=
-
1
;
}
return
new
ValuePair
(
finalValue
,
index
);
}
private
Optional
<
Column
>
getColumn
(
final
SQLExpr
expr
)
{
...
...
@@ -375,4 +404,12 @@ public final class ParseContext {
}
selectItems
.
add
(
rawItemExpr
);
}
@RequiredArgsConstructor
private
static
class
ValuePair
{
private
final
Comparable
<?>
value
;
private
final
Integer
paramIndex
;
}
}
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/parser/visitor/basic/mysql/MySQLEvalVisitor.java
0 → 100644
浏览文件 @
1f7ed616
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package
com.dangdang.ddframe.rdb.sharding.parser.visitor.basic.mysql
;
import
com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr
;
import
com.alibaba.druid.sql.dialect.mysql.visitor.MySqlEvalVisitorImpl
;
import
java.util.Map
;
/**
* MySQL变量中提取参数值与编号.
*
* @author gaohongtao.
*/
public
class
MySQLEvalVisitor
extends
MySqlEvalVisitorImpl
{
public
static
final
String
EVAL_VAR_INDEX
=
"EVAL_VAR_INDEX"
;
@Override
public
boolean
visit
(
final
SQLVariantRefExpr
x
)
{
if
(!
"?"
.
equals
(
x
.
getName
()))
{
return
false
;
}
Map
<
String
,
Object
>
attributes
=
x
.
getAttributes
();
int
varIndex
=
x
.
getIndex
();
if
(
varIndex
==
-
1
||
getParameters
().
size
()
<=
varIndex
)
{
return
false
;
}
if
(
attributes
.
containsKey
(
EVAL_VALUE
))
{
return
false
;
}
Object
value
=
getParameters
().
get
(
varIndex
);
if
(
value
==
null
)
{
value
=
EVAL_VALUE_NULL
;
}
attributes
.
put
(
EVAL_VALUE
,
value
);
attributes
.
put
(
EVAL_VAR_INDEX
,
varIndex
);
return
false
;
}
}
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/router/PreparedSQLRouter.java
0 → 100644
浏览文件 @
1f7ed616
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package
com.dangdang.ddframe.rdb.sharding.router
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.SQLParsedResult
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.router.ConditionContext
;
import
lombok.RequiredArgsConstructor
;
import
java.util.List
;
/**
* 预解析功能的SQL路由器.
*
* @author gaohongtao
*/
@RequiredArgsConstructor
public
class
PreparedSQLRouter
{
private
final
String
logicSql
;
private
final
SQLRouteEngine
engine
;
private
SQLParsedResult
sqlParsedResult
;
/**
* 使用参数进行SQL路由.
* 当第一次路由时进行SQL解析,之后的路由复用第一次的解析结果.
*
* @param parameters SQL中的参数
* @return 路由结果
*/
public
SQLRouteResult
route
(
final
List
<
Object
>
parameters
)
{
if
(
null
==
sqlParsedResult
)
{
sqlParsedResult
=
engine
.
parseSQL
(
logicSql
,
parameters
);
}
else
{
for
(
ConditionContext
each
:
sqlParsedResult
.
getConditionContexts
())
{
each
.
setNewConditionValue
(
parameters
);
}
}
return
engine
.
routeSQL
(
sqlParsedResult
);
}
}
sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/router/SQLRouteEngine.java
浏览文件 @
1f7ed616
...
...
@@ -80,14 +80,24 @@ public final class SQLRouteEngine {
return
routeSQL
(
parseSQL
(
logicSql
,
parameters
));
}
private
SQLParsedResult
parseSQL
(
final
String
logicSql
,
final
List
<
Object
>
parameters
)
{
/**
* 预解析SQL路由.
*
* @param logicSql 逻辑SQL
* @return 预解析SQL路由器
*/
public
PreparedSQLRouter
prepareSQL
(
final
String
logicSql
)
{
return
new
PreparedSQLRouter
(
logicSql
,
this
);
}
SQLParsedResult
parseSQL
(
final
String
logicSql
,
final
List
<
Object
>
parameters
)
{
Context
context
=
MetricsContext
.
start
(
"Parse SQL"
);
SQLParsedResult
result
=
SQLParserFactory
.
create
(
databaseType
,
logicSql
,
parameters
,
shardingRule
.
getAllShardingColumns
()).
parse
();
MetricsContext
.
stop
(
context
);
return
result
;
}
private
SQLRouteResult
routeSQL
(
final
SQLParsedResult
parsedResult
)
{
SQLRouteResult
routeSQL
(
final
SQLParsedResult
parsedResult
)
{
Context
context
=
MetricsContext
.
start
(
"Route SQL"
);
SQLRouteResult
result
=
new
SQLRouteResult
(
parsedResult
.
getRouteContext
().
getSqlStatementType
(),
parsedResult
.
getMergeContext
());
for
(
ConditionContext
each
:
parsedResult
.
getConditionContexts
())
{
...
...
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/AbstractDBUnitTest.java
浏览文件 @
1f7ed616
...
...
@@ -17,17 +17,6 @@
package
com.dangdang.ddframe.rdb.integrate
;
import
java.io.File
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.sql.Connection
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
javax.sql.DataSource
;
import
com.dangdang.ddframe.rdb.sharding.constants.DatabaseType
;
import
org.apache.commons.dbcp.BasicDataSource
;
import
org.dbunit.DatabaseUnitException
;
...
...
@@ -42,13 +31,24 @@ import org.dbunit.operation.DatabaseOperation;
import
org.h2.tools.RunScript
;
import
org.junit.Before
;
import
javax.sql.DataSource
;
import
java.io.File
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.sql.Connection
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
dbunit
.
Assertion
.
assertEquals
;
public
abstract
class
AbstractDBUnitTest
{
protected
static
final
DatabaseType
CURRENT_DB_TYPE
=
DatabaseType
.
H2
;
pr
ivate
static
final
Map
<
String
,
DataSource
>
DATA_SOURCES
=
new
HashMap
<>();
pr
otected
static
final
Map
<
String
,
DataSource
>
DATA_SOURCES
=
new
HashMap
<>();
private
final
DataBaseEnvironment
dbEnv
=
new
DataBaseEnvironment
(
CURRENT_DB_TYPE
);
...
...
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/dbtbl/common/statement/AbstractShardingBothForStatementWithDMLTest.java
浏览文件 @
1f7ed616
...
...
@@ -77,7 +77,7 @@ public abstract class AbstractShardingBothForStatementWithDMLTest extends Abstra
for
(
int
i
=
10
;
i
<
20
;
i
++)
{
for
(
int
j
=
0
;
j
<
10
;
j
++)
{
try
(
Connection
connection
=
shardingDataSource
.
getConnection
())
{
Statement
stmt
=
connection
.
prepareStatement
(
sql
);
Statement
stmt
=
connection
.
createStatement
(
);
assertThat
(
stmt
.
executeUpdate
(
String
.
format
(
sql
,
i
*
100
+
j
,
i
)),
is
(
1
));
}
}
...
...
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/dbtbl/statically/statement/StaticShardingBothForStatementWithDMLTest.java
浏览文件 @
1f7ed616
...
...
@@ -41,7 +41,7 @@ public final class StaticShardingBothForStatementWithDMLTest extends AbstractSha
public
void
assertUpdateWithoutShardingValue
()
throws
SQLException
,
DatabaseUnitException
{
String
sql
=
"UPDATE `t_order` SET `status` = '%s' WHERE `status` = '%s'"
;
try
(
Connection
connection
=
getShardingDataSource
().
getConnection
())
{
Statement
stmt
=
connection
.
prepareStatement
(
sql
);
Statement
stmt
=
connection
.
createStatement
(
);
assertThat
(
stmt
.
executeUpdate
(
String
.
format
(
sql
,
"updated"
,
"init"
)),
is
(
100
));
}
assertDataSet
(
"update"
,
"updated"
);
...
...
@@ -51,7 +51,7 @@ public final class StaticShardingBothForStatementWithDMLTest extends AbstractSha
public
void
assertDeleteWithoutShardingValue
()
throws
SQLException
,
DatabaseUnitException
{
String
sql
=
"DELETE `t_order` WHERE `status` = '%s'"
;
try
(
Connection
connection
=
getShardingDataSource
().
getConnection
())
{
Statement
stmt
=
connection
.
prepareStatement
(
sql
);
Statement
stmt
=
connection
.
createStatement
(
);
assertThat
(
stmt
.
executeUpdate
(
String
.
format
(
sql
,
"init"
)),
is
(
100
));
}
assertDataSet
(
"delete"
,
"init"
);
...
...
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/statement/ShardingMasterSlaveForStatementWithDMLTest.java
浏览文件 @
1f7ed616
...
...
@@ -47,7 +47,7 @@ public final class ShardingMasterSlaveForStatementWithDMLTest extends AbstractSh
assertSelectBeforeUpdate
();
String
sql
=
"UPDATE `t_order` SET `status` = '%s' WHERE `status` = '%s'"
;
try
(
Connection
connection
=
getShardingDataSource
().
getConnection
())
{
Statement
stmt
=
connection
.
prepareStatement
(
sql
);
Statement
stmt
=
connection
.
createStatement
(
);
assertThat
(
stmt
.
executeUpdate
(
String
.
format
(
sql
,
"updated"
,
"init_master"
)),
is
(
100
));
}
assertDataSet
(
"update"
,
"updated"
);
...
...
@@ -57,7 +57,7 @@ public final class ShardingMasterSlaveForStatementWithDMLTest extends AbstractSh
private
void
assertSelectBeforeUpdate
()
throws
SQLException
,
DatabaseUnitException
{
String
sql
=
"SELECT * FROM `t_order` WHERE `status` = '%s'"
;
try
(
Connection
connection
=
getShardingDataSource
().
getConnection
())
{
Statement
stmt
=
connection
.
prepareStatement
(
sql
);
Statement
stmt
=
connection
.
createStatement
(
);
assertFalse
(
stmt
.
executeQuery
(
String
.
format
(
sql
,
"updated"
)).
next
());
}
}
...
...
@@ -65,7 +65,7 @@ public final class ShardingMasterSlaveForStatementWithDMLTest extends AbstractSh
private
void
assertSelectAfterUpdate
()
throws
SQLException
,
DatabaseUnitException
{
String
sql
=
"SELECT * FROM `t_order` WHERE `status` = '%s'"
;
try
(
Connection
connection
=
getShardingDataSource
().
getConnection
())
{
Statement
stmt
=
connection
.
prepareStatement
(
sql
);
Statement
stmt
=
connection
.
createStatement
(
);
assertTrue
(
stmt
.
executeQuery
(
String
.
format
(
sql
,
"updated"
)).
next
());
}
}
...
...
@@ -74,7 +74,7 @@ public final class ShardingMasterSlaveForStatementWithDMLTest extends AbstractSh
public
void
assertDeleteWithoutShardingValue
()
throws
SQLException
,
DatabaseUnitException
{
String
sql
=
"DELETE `t_order` WHERE `status` = '%s'"
;
try
(
Connection
connection
=
getShardingDataSource
().
getConnection
())
{
Statement
stmt
=
connection
.
prepareStatement
(
sql
);
Statement
stmt
=
connection
.
createStatement
(
);
assertThat
(
stmt
.
executeUpdate
(
String
.
format
(
sql
,
"init_master"
)),
is
(
100
));
}
assertDataSet
(
"delete"
,
"init"
);
...
...
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingPreparedStatementTest.java
浏览文件 @
1f7ed616
...
...
@@ -17,21 +17,20 @@
package
com.dangdang.ddframe.rdb.sharding.jdbc
;
import
static
org
.
hamcrest
.
CoreMatchers
.
is
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
com.dangdang.ddframe.rdb.integrate.db.AbstractShardingDataBasesOnlyDBUnitTest
;
import
com.mysql.jdbc.Statement
;
import
org.junit.Before
;
import
org.junit.Test
;
import
java.sql.Connection
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
org.junit.Before
;
import
org.junit.Test
;
import
com.dangdang.ddframe.rdb.integrate.db.AbstractShardingDataBasesOnlyDBUnitTest
;
import
com.mysql.jdbc.Statement
;
import
static
org
.
hamcrest
.
CoreMatchers
.
is
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
public
final
class
ShardingPreparedStatementTest
extends
AbstractShardingDataBasesOnlyDBUnitTest
{
...
...
@@ -52,6 +51,14 @@ public final class ShardingPreparedStatementTest extends AbstractShardingDataBas
ResultSet
resultSet
=
preparedStatement
.
executeQuery
();
assertTrue
(
resultSet
.
next
());
assertThat
(
resultSet
.
getLong
(
1
),
is
(
40L
));
preparedStatement
.
setString
(
1
,
"null"
);
resultSet
=
preparedStatement
.
executeQuery
();
assertTrue
(
resultSet
.
next
());
assertThat
(
resultSet
.
getLong
(
1
),
is
(
0L
));
preparedStatement
.
setString
(
1
,
"init"
);
resultSet
=
preparedStatement
.
executeQuery
();
assertTrue
(
resultSet
.
next
());
assertThat
(
resultSet
.
getLong
(
1
),
is
(
40L
));
}
}
...
...
@@ -64,6 +71,12 @@ public final class ShardingPreparedStatementTest extends AbstractShardingDataBas
ResultSet
resultSet
=
preparedStatement
.
executeQuery
();
assertTrue
(
resultSet
.
next
());
assertThat
(
resultSet
.
getLong
(
1
),
is
(
40L
));
resultSet
=
preparedStatement
.
executeQuery
();
assertTrue
(
resultSet
.
next
());
assertThat
(
resultSet
.
getLong
(
1
),
is
(
40L
));
resultSet
=
preparedStatement
.
executeQuery
();
assertTrue
(
resultSet
.
next
());
assertThat
(
resultSet
.
getLong
(
1
),
is
(
40L
));
}
}
...
...
@@ -75,6 +88,10 @@ public final class ShardingPreparedStatementTest extends AbstractShardingDataBas
PreparedStatement
preparedStatement
=
connection
.
prepareStatement
(
sql
))
{
preparedStatement
.
setString
(
1
,
"init"
);
assertThat
(
preparedStatement
.
executeUpdate
(),
is
(
40
));
preparedStatement
.
setString
(
1
,
"null"
);
assertThat
(
preparedStatement
.
executeUpdate
(),
is
(
0
));
preparedStatement
.
setString
(
1
,
"init"
);
assertThat
(
preparedStatement
.
executeUpdate
(),
is
(
0
));
}
}
...
...
@@ -85,6 +102,8 @@ public final class ShardingPreparedStatementTest extends AbstractShardingDataBas
Connection
connection
=
shardingDataSource
.
getConnection
();
PreparedStatement
preparedStatement
=
connection
.
prepareStatement
(
sql
))
{
assertThat
(
preparedStatement
.
executeUpdate
(),
is
(
40
));
assertThat
(
preparedStatement
.
executeUpdate
(),
is
(
0
));
assertThat
(
preparedStatement
.
executeUpdate
(),
is
(
0
));
}
}
...
...
@@ -98,6 +117,14 @@ public final class ShardingPreparedStatementTest extends AbstractShardingDataBas
assertTrue
(
preparedStatement
.
execute
());
assertTrue
(
preparedStatement
.
getResultSet
().
next
());
assertThat
(
preparedStatement
.
getResultSet
().
getLong
(
1
),
is
(
40L
));
preparedStatement
.
setString
(
1
,
"null"
);
assertTrue
(
preparedStatement
.
execute
());
assertTrue
(
preparedStatement
.
getResultSet
().
next
());
assertThat
(
preparedStatement
.
getResultSet
().
getLong
(
1
),
is
(
0L
));
preparedStatement
.
setString
(
1
,
"init"
);
assertTrue
(
preparedStatement
.
execute
());
assertTrue
(
preparedStatement
.
getResultSet
().
next
());
assertThat
(
preparedStatement
.
getResultSet
().
getLong
(
1
),
is
(
40L
));
}
}
...
...
@@ -108,6 +135,8 @@ public final class ShardingPreparedStatementTest extends AbstractShardingDataBas
Connection
connection
=
shardingDataSource
.
getConnection
();
PreparedStatement
preparedStatement
=
connection
.
prepareStatement
(
sql
))
{
assertFalse
(
preparedStatement
.
execute
());
assertFalse
(
preparedStatement
.
execute
());
assertFalse
(
preparedStatement
.
execute
());
}
}
...
...
@@ -203,6 +232,14 @@ public final class ShardingPreparedStatementTest extends AbstractShardingDataBas
preparedStatement
.
setInt
(
2
,
12
);
preparedStatement
.
setString
(
3
,
"BATCH"
);
preparedStatement
.
addBatch
();
preparedStatement
.
setInt
(
1
,
3111
);
preparedStatement
.
setInt
(
2
,
21
);
preparedStatement
.
setString
(
3
,
"BATCH"
);
preparedStatement
.
addBatch
();
preparedStatement
.
setInt
(
1
,
3112
);
preparedStatement
.
setInt
(
2
,
22
);
preparedStatement
.
setString
(
3
,
"BATCH"
);
preparedStatement
.
addBatch
();
int
[]
result
=
preparedStatement
.
executeBatch
();
for
(
int
each
:
result
)
{
assertThat
(
each
,
is
(
1
));
...
...
@@ -210,7 +247,7 @@ public final class ShardingPreparedStatementTest extends AbstractShardingDataBas
}
}
@Test
(
expected
=
IllegalStateException
.
class
)
@Test
public
void
assertClearBatch
()
throws
SQLException
{
String
sql
=
"INSERT INTO `t_order`(`order_id`, `user_id`, `status`) VALUES (?,?,?)"
;
try
(
...
...
@@ -221,7 +258,8 @@ public final class ShardingPreparedStatementTest extends AbstractShardingDataBas
preparedStatement
.
setString
(
3
,
"BATCH"
);
preparedStatement
.
addBatch
();
preparedStatement
.
clearBatch
();
preparedStatement
.
executeBatch
();
int
[]
result
=
preparedStatement
.
executeBatch
();
assertThat
(
result
.
length
,
is
(
0
));
}
}
}
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/AbstractBaseParseTest.java
浏览文件 @
1f7ed616
...
...
@@ -146,6 +146,9 @@ public abstract class AbstractBaseParseTest {
return
input
.
getValueWithType
();
}
}));
if
(
null
!=
each
.
getValueIndices
())
{
condition
.
getValueIndices
().
addAll
(
each
.
getValueIndices
());
}
result
.
add
(
condition
);
}
return
result
;
...
...
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/AllParserTests.java
浏览文件 @
1f7ed616
...
...
@@ -22,6 +22,7 @@ import com.dangdang.ddframe.rdb.sharding.parser.mysql.MySQLPreparedStatementForT
import
com.dangdang.ddframe.rdb.sharding.parser.mysql.MySQLStatementTest
;
import
com.dangdang.ddframe.rdb.sharding.parser.mysql.OrParseTest
;
import
com.dangdang.ddframe.rdb.sharding.parser.result.SQLParsedResultTest
;
import
com.dangdang.ddframe.rdb.sharding.parser.visitor.basic.mysql.MySQLEvalVisitorTest
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Suite
;
...
...
@@ -32,7 +33,8 @@ import org.junit.runners.Suite;
MySQLPreparedStatementForOneParameterTest
.
class
,
MySQLPreparedStatementForTowParametersTest
.
class
,
OrParseTest
.
class
,
UnsupportedParseTest
.
class
UnsupportedParseTest
.
class
,
MySQLEvalVisitorTest
.
class
,
})
public
class
AllParserTests
{
}
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/jaxb/Condition.java
浏览文件 @
1f7ed616
...
...
@@ -17,15 +17,14 @@
package
com.dangdang.ddframe.rdb.sharding.parser.jaxb
;
import
java.util.List
;
import
lombok.Getter
;
import
lombok.Setter
;
import
javax.xml.bind.annotation.XmlAccessType
;
import
javax.xml.bind.annotation.XmlAccessorType
;
import
javax.xml.bind.annotation.XmlAttribute
;
import
javax.xml.bind.annotation.XmlElement
;
import
lombok.Getter
;
import
lombok.Setter
;
import
java.util.List
;
@Getter
@Setter
...
...
@@ -43,4 +42,7 @@ public final class Condition {
@XmlElement
(
name
=
"value"
)
private
List
<
Value
>
values
;
@XmlElement
(
name
=
"valueIndices"
)
private
List
<
Integer
>
valueIndices
;
}
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/result/SQLParsedResultTest.java
浏览文件 @
1f7ed616
...
...
@@ -54,7 +54,7 @@ public final class SQLParsedResultTest {
+
"sqlStatementType=null, "
+
"sqlBuilder=SELECT * FROM [Token(order)]), "
+
"conditionContexts=[ConditionContext(conditions={Condition.Column(columnName=id, tableName=order)=Condition(column=Condition.Column(columnName=id, tableName=order), "
+
"operator=IN, values=[1, 2, 3])})], "
+
"operator=IN, values=[1, 2, 3]
, valueIndices=[]
)})], "
+
"mergeContext=MergeContext("
+
"orderByColumns=[OrderByColumn(super=AbstractSortableColumn(owner=Optional.absent(), "
+
"name=Optional.of(id), alias=Optional.of(a), orderByType=DESC), index=Optional.absent(), columnIndex=0)], "
...
...
sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/parser/visitor/basic/mysql/MySQLEvalVisitorTest.java
0 → 100644
浏览文件 @
1f7ed616
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/
package
com.dangdang.ddframe.rdb.sharding.parser.visitor.basic.mysql
;
import
com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr
;
import
com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils
;
import
com.google.common.collect.Lists
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
nullValue
;
import
static
org
.
hamcrest
.
core
.
Is
.
is
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
MySQLEvalVisitorTest
{
@Test
public
void
testVisit
()
throws
Exception
{
SQLVariantRefExpr
expr
=
new
SQLVariantRefExpr
(
"?"
);
expr
.
setIndex
(
1
);
MySQLEvalVisitor
visitor
=
new
MySQLEvalVisitor
();
visitor
.
setParameters
(
Lists
.<
Object
>
newArrayList
(
1
,
2
));
expr
.
accept
(
visitor
);
assertThat
((
Integer
)
SQLEvalVisitorUtils
.
getValue
(
expr
),
is
(
2
));
assertThat
((
Integer
)
expr
.
getAttribute
(
MySQLEvalVisitor
.
EVAL_VAR_INDEX
),
is
(
1
));
}
@Test
public
void
testVisitErrorIndex
()
throws
Exception
{
SQLVariantRefExpr
expr
=
new
SQLVariantRefExpr
(
"?"
);
expr
.
setIndex
(
2
);
MySQLEvalVisitor
visitor
=
new
MySQLEvalVisitor
();
visitor
.
setParameters
(
Lists
.<
Object
>
newArrayList
(
1
,
2
));
expr
.
accept
(
visitor
);
assertThat
(
SQLEvalVisitorUtils
.
getValue
(
expr
),
nullValue
());
}
@Test
public
void
testVisitNotOverride
()
throws
Exception
{
SQLVariantRefExpr
expr
=
new
SQLVariantRefExpr
(
"?"
);
expr
.
setIndex
(
1
);
expr
.
getAttributes
().
put
(
MySQLEvalVisitor
.
EVAL_VALUE
,
"test"
);
MySQLEvalVisitor
visitor
=
new
MySQLEvalVisitor
();
visitor
.
setParameters
(
Lists
.<
Object
>
newArrayList
(
1
,
2
));
expr
.
accept
(
visitor
);
assertThat
((
String
)
SQLEvalVisitorUtils
.
getValue
(
expr
),
is
(
"test"
));
}
@Test
public
void
testVisitWrongName
()
throws
Exception
{
SQLVariantRefExpr
expr
=
new
SQLVariantRefExpr
(
""
);
expr
.
setIndex
(
1
);
MySQLEvalVisitor
visitor
=
new
MySQLEvalVisitor
();
visitor
.
setParameters
(
Lists
.<
Object
>
newArrayList
(
1
,
2
));
expr
.
accept
(
visitor
);
assertThat
(
SQLEvalVisitorUtils
.
getValue
(
expr
),
nullValue
());
}
@Test
public
void
testVisitNullValue
()
throws
Exception
{
SQLVariantRefExpr
expr
=
new
SQLVariantRefExpr
(
"?"
);
expr
.
setIndex
(
1
);
MySQLEvalVisitor
visitor
=
new
MySQLEvalVisitor
();
visitor
.
setParameters
(
Lists
.<
Object
>
newArrayList
(
1
,
null
));
expr
.
accept
(
visitor
);
assertThat
(
SQLEvalVisitorUtils
.
getValue
(
expr
),
is
(
MySQLEvalVisitor
.
EVAL_VALUE_NULL
));
}
}
\ No newline at end of file
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/one_param/delete.xml
浏览文件 @
1f7ed616
...
...
@@ -8,6 +8,7 @@
<condition-context>
<condition
column-name=
"order_id"
table-name=
"order"
operator=
"IN"
>
<value
value=
"1"
type=
"java.lang.Integer"
/>
<valueIndices>
0
</valueIndices>
</condition>
</condition-context>
</condition-contexts>
...
...
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/one_param/insert.xml
浏览文件 @
1f7ed616
...
...
@@ -8,6 +8,7 @@
<condition-context>
<condition
column-name=
"order_id"
table-name=
"order"
operator=
"EQUAL"
>
<value
value=
"1"
type=
"java.lang.Integer"
/>
<valueIndices>
0
</valueIndices>
</condition>
<condition
column-name=
"state"
table-name=
"order"
operator=
"EQUAL"
>
<value
value=
"RUNNING"
type=
"java.lang.String"
/>
...
...
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/one_param/select.xml
浏览文件 @
1f7ed616
...
...
@@ -10,6 +10,7 @@
<value
value=
"1"
type=
"int"
/>
<value
value=
"2"
type=
"int"
/>
<value
value=
"3"
type=
"int"
/>
<valueIndices>
0
</valueIndices>
</condition>
</condition-context>
</condition-contexts>
...
...
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/one_param/update.xml
浏览文件 @
1f7ed616
...
...
@@ -8,6 +8,7 @@
<condition-context>
<condition
column-name=
"order_id"
table-name=
"order"
operator=
"EQUAL"
>
<value
value=
"1"
type=
"java.lang.Integer"
/>
<valueIndices>
0
</valueIndices>
</condition>
</condition-context>
</condition-contexts>
...
...
sharding-jdbc-core/src/test/resources/com/dangdang/ddframe/rdb/sharding/parser/mysql/prepared_statement/two_params/select.xml
浏览文件 @
1f7ed616
...
...
@@ -9,6 +9,8 @@
<condition
column-name=
"order_id"
table-name=
"order"
operator=
"BETWEEN"
>
<value
value=
"1"
type=
"int"
/>
<value
value=
"2"
type=
"int"
/>
<valueIndices>
0
</valueIndices>
<valueIndices>
1
</valueIndices>
</condition>
</condition-context>
</condition-contexts>
...
...
sharding-jdbc-doc/content/post/release_notes.md
浏览文件 @
1f7ed616
...
...
@@ -8,6 +8,11 @@ weight = 1
## 1.3.2-SNAPSHOT
### 缺陷修正
1.
[
ISSUE #36
](
https://github.com/dangdangdotcom/sharding-jdbc/issues/36
)
ShardingPreparedStatement无法反复设置参数
1.
[
ISSUE #114
](
https://github.com/dangdangdotcom/sharding-jdbc/issues/114
)
ShardingPreparedStatement执行批处理任务时,反复解析sql导致oom
## 1.3.1
### 功能提升
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录