Merge pull request #202 from wenshao/master

sharding support & bug fixed & improve sqlserver sql parser
This commit is contained in:
温高铁
2012-11-24 23:59:06 -08:00
20 changed files with 820 additions and 157 deletions
@@ -90,7 +90,22 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
}
public void incrementExecuteCount() {
this.getPoolableConnection().getConnectionHolder().getDataSource().incrementExecuteCount();
DruidPooledConnection conn = this.getPoolableConnection();
if (conn == null) {
return;
}
DruidConnectionHolder holder = conn.getConnectionHolder();
if (holder == null) {
return;
}
if (holder.getDataSource() == null) {
return;
}
holder.getDataSource().incrementExecuteCount();
}
protected void transactionRecord(String sql) throws SQLException {
@@ -259,7 +274,10 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
clearResultSet();
stmt.close();
this.closed = true;
conn.getConnectionHolder().removeTrace(this);
if (conn.getConnectionHolder() != null) {
conn.getConnectionHolder().removeTrace(this);
}
}
}
@@ -0,0 +1,20 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding;
public class ShardingDataSource {
}
@@ -0,0 +1,40 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding;
import com.alibaba.druid.DruidRuntimeException;
public class ShardingRuntimeException extends DruidRuntimeException {
private static final long serialVersionUID = 1L;
public ShardingRuntimeException(){
super();
}
public ShardingRuntimeException(String message, Throwable cause){
super(message, cause);
}
public ShardingRuntimeException(String message){
super(message);
}
public ShardingRuntimeException(Throwable cause){
super(cause);
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding.config;
import java.util.HashMap;
import java.util.Map;
public class LogicTable {
private String logicTable;
private Map<String, TablePartition> partitions = new HashMap<String, TablePartition>();
public String getLogicTable() {
return logicTable;
}
public void setLogicTable(String logicTable) {
this.logicTable = logicTable;
}
public Map<String, TablePartition> getPartitions() {
return partitions;
}
public void setPartitions(Map<String, TablePartition> partitions) {
this.partitions = partitions;
}
public void addPartition(String partitionName, String physicalTableName) {
this.partitions.put(partitionName, new TablePartition(partitionName, physicalTableName));
}
public void addPartition(String partitionName, String database, String physicalTableName) {
this.partitions.put(partitionName, new TablePartition(partitionName, database, physicalTableName));
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding.config;
import java.util.List;
public interface MappingRule {
String getTable();
String getColumn();
List<MappingRuleEntry> getEntries();
String getPartition(Object value);
}
@@ -0,0 +1,71 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding.config;
import java.util.ArrayList;
import java.util.List;
public class MappingRuleAdapter implements MappingRule {
private String defaultPartition;
private String table;
private String column;
private List<MappingRuleEntry> entries = new ArrayList<MappingRuleEntry>();
public List<MappingRuleEntry> getEntries() {
return entries;
}
public void setEntries(List<MappingRuleEntry> entries) {
this.entries = entries;
}
public String getPartition(Object value) {
for (MappingRuleEntry entry : this.entries) {
if (entry.match(value)) {
return entry.getPartition();
}
}
return this.getDefaultPartition();
}
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
public String getColumn() {
return column;
}
public void setColumn(String column) {
this.column = column;
}
public String getDefaultPartition() {
return defaultPartition;
}
public void setDefaultPartition(String defaultPartition) {
this.defaultPartition = defaultPartition;
}
}
@@ -0,0 +1,23 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding.config;
public interface MappingRuleEntry {
boolean match(Object value);
String getPartition();
}
@@ -0,0 +1,64 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding.config;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
public class MappingRuleListEntry implements MappingRuleEntry {
private List<Object> values = new ArrayList<Object>();
private String partition;
public MappingRuleListEntry() {
}
public MappingRuleListEntry(String partition, Object...values) {
this.partition = partition;
for (Object value : values) {
this.values.add(value);
}
}
public List<Object> getValues() {
return values;
}
public void setValues(List<Object> values) {
this.values = values;
}
public String getPartition() {
return partition;
}
public void setPartition(String partition) {
this.partition = partition;
}
@Override
public boolean match(Object value) {
for (Object item : this.values) {
if (SQLEvalVisitorUtils.eq(item, value)) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding.config;
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
public class MappingRuleLtEntry implements MappingRuleEntry {
private Object value;
private String partition;
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String getPartition() {
return partition;
}
public void setPartition(String partition) {
this.partition = partition;
}
@Override
public boolean match(Object value) {
return SQLEvalVisitorUtils.eq(this.value, value);
}
}
@@ -0,0 +1,76 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding.config;
import java.util.HashMap;
import java.util.Map;
public class RouteConfig {
private Map<String, LogicTable> logicTables = new HashMap<String, LogicTable>();
private Map<String, MappingRule> mappingRules = new HashMap<String, MappingRule>();
public Map<String, LogicTable> getLogicTables() {
return logicTables;
}
public void setLogicTables(Map<String, LogicTable> logicTables) {
this.logicTables = logicTables;
}
public Map<String, MappingRule> getMappingRules() {
return mappingRules;
}
public void setMappingRules(Map<String, MappingRule> mappingRules) {
this.mappingRules = mappingRules;
}
public MappingRule getMappingRule(String table) {
if (table == null) {
return null;
}
String lowerTable = table.toLowerCase();
return mappingRules.get(lowerTable);
}
public TablePartition getPartition(String table, String partitionName) {
if (table == null) {
throw new IllegalArgumentException("table is null");
}
if (partitionName == null) {
throw new IllegalArgumentException("partitionName is null");
}
String lowerTable = table.toLowerCase();
LogicTable config = logicTables.get(lowerTable);
if (config == null) {
throw new IllegalArgumentException("table's partition config not exists, tableName : " + table);
}
String lowerPartitionName = partitionName.toLowerCase();
TablePartition tablePartition = config.getPartitions().get(lowerPartitionName);
if (tablePartition == null) {
throw new IllegalArgumentException("table's partition config not exists, tableName : " + table
+ ", partition : " + lowerPartitionName);
}
return tablePartition;
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding.config;
public class TablePartition {
private String name;
private String database;
private String table;
public TablePartition(){
}
public TablePartition(String name, String table){
this.name = name;
this.table = table;
}
public TablePartition(String name, String database, String table){
this.name = name;
this.database = database;
this.table = table;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
}
@@ -0,0 +1,111 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.sharding.sql;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.alibaba.druid.sharding.ShardingRuntimeException;
import com.alibaba.druid.sharding.config.MappingRule;
import com.alibaba.druid.sharding.config.RouteConfig;
import com.alibaba.druid.sharding.config.TablePartition;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
public class MySqlShardingVisitor extends MySqlASTVisitorAdapter implements ShardingVisitor {
private final RouteConfig routeConfig;
private final List<Object> parameters;
private List<SQLStatement> result = new ArrayList<SQLStatement>(2);
public MySqlShardingVisitor(RouteConfig routeConfig, List<Object> parameters){
this.routeConfig = routeConfig;
this.parameters = parameters;
}
public MySqlShardingVisitor(RouteConfig routeConfig, Object... parameters){
this(routeConfig, Arrays.asList(parameters));
}
public RouteConfig getRouteConfig() {
return routeConfig;
}
public List<Object> getParameters() {
return parameters;
}
public boolean visit(MySqlInsertStatement x) {
String table = x.getTableName().getSimleName();
MappingRule mappingRule = routeConfig.getMappingRule(table);
if (mappingRule == null) {
result.add(x);
return false;
}
if (x.getValues() == null) {
throw new ShardingRuntimeException("sharding rule violation, insert's values clause is null");
}
String column = mappingRule.getColumn();
int columnIndex = -1;
for (int i = 0; i < x.getColumns().size(); ++i) {
SQLExpr columnExpr = x.getColumns().get(i);
if (columnExpr instanceof SQLIdentifierExpr) {
String columnName = ((SQLIdentifierExpr) columnExpr).getName();
if (column.equalsIgnoreCase(columnName)) {
columnIndex = i;
break;
}
}
}
if (columnIndex == -1) {
throw new ShardingRuntimeException("sharding rule violation, columns not set : " + column);
}
SQLExpr valueExpr = x.getValues().getValues().get(columnIndex);
Object value = SQLEvalVisitorUtils.eval(null, valueExpr, parameters);
String partition = mappingRule.getPartition(value);
if (partition == null) {
throw new ShardingRuntimeException("sharding rule violation, partition not match, value : " + value);
}
TablePartition tablePartition = routeConfig.getPartition(table, partition);
x.setTableName(new SQLIdentifierExpr(tablePartition.getTable()));
if (tablePartition.getDatabase() != null) {
x.putAttribute(ATTR_DB, tablePartition.getDatabase());
}
result.add(x);
return false;
}
}
@@ -0,0 +1,5 @@
package com.alibaba.druid.sharding.sql;
public interface ShardingVisitor {
public static final String ATTR_DB = "sharding.db";
}
@@ -15,9 +15,16 @@
*/
package com.alibaba.druid.sql.dialect.sqlserver.parser;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
import com.alibaba.druid.sql.ast.statement.SQLInsertInto;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
public class SQLServerStatementParser extends SQLStatementParser {
@@ -32,5 +39,65 @@ public class SQLServerStatementParser extends SQLStatementParser {
public SQLServerStatementParser(Lexer lexer){
super(new SQLServerExprParser(lexer));
}
public SQLStatement parseInsert() {
SQLServerInsertStatement insertStatement = new SQLServerInsertStatement();
if (lexer.token() == Token.INSERT) {
accept(Token.INSERT);
}
parseInsert0(insertStatement);
return insertStatement;
}
protected void parseInsert0(SQLInsertInto insert, boolean acceptSubQuery) {
SQLServerInsertStatement insertStatement = (SQLServerInsertStatement) insert;
if (lexer.token() == Token.INTO) {
lexer.nextToken();
SQLName tableName = this.exprParser.name();
insertStatement.setTableName(tableName);
if (lexer.token() == Token.LITERAL_ALIAS) {
insertStatement.setAlias(as());
}
parseInsert0_hinits(insertStatement);
if (lexer.token() == Token.IDENTIFIER) {
insertStatement.setAlias(lexer.stringVal());
lexer.nextToken();
}
}
if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
this.exprParser.exprList(insertStatement.getColumns());
accept(Token.RPAREN);
}
if (lexer.token() == Token.VALUES) {
lexer.nextToken();
for (;;) {
accept(Token.LPAREN);
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
this.exprParser.exprList(values.getValues());
insertStatement.getValuesList().add(values);
accept(Token.RPAREN);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
} else {
break;
}
}
} else if (acceptSubQuery && (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN)) {
SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();
insertStatement.setQuery(queryExpr.getSubQuery());
}
}
}
@@ -103,7 +103,8 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
if (x.getColumns().size() > 0) {
incrementIndent();
print(" (");
println();
print("(");
for (int i = 0, size = x.getColumns().size(); i < size; ++i) {
if (i != 0) {
if (i % 5 == 0) {
@@ -120,14 +121,15 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
if (x.getValuesList().size() != 0) {
println();
print("VALUES ");
print("VALUES");
println();
for (int i = 0, size = x.getValuesList().size(); i < size; ++i) {
if (i != 0) {
print(", ");
print(",");
println();
}
x.getValuesList().get(i).accept(this);
}
}
if (x.getQuery() != null) {
@@ -1305,6 +1305,10 @@ public class SQLEvalVisitorUtils {
return d1.equals(d2);
}
if (a instanceof String || b instanceof String) {
return _string(a).equals(_string(b));
}
throw new IllegalArgumentException();
}
@@ -1,146 +0,0 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.util;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
/**
* A {@link BlockingQueue} in which producers may wait for consumers
* to receive elements. A {@code TransferQueue} may be useful for
* example in message passing applications in which producers
* sometimes (using method {@link #transfer}) await receipt of
* elements by consumers invoking {@code take} or {@code poll}, while
* at other times enqueue elements (via method {@code put}) without
* waiting for receipt.
* {@linkplain #tryTransfer(Object) Non-blocking} and
* {@linkplain #tryTransfer(Object,long,TimeUnit) time-out} versions of
* {@code tryTransfer} are also available.
* A {@code TransferQueue} may also be queried, via {@link
* #hasWaitingConsumer}, whether there are any threads waiting for
* items, which is a converse analogy to a {@code peek} operation.
*
* <p>Like other blocking queues, a {@code TransferQueue} may be
* capacity bounded. If so, an attempted transfer operation may
* initially block waiting for available space, and/or subsequently
* block waiting for reception by a consumer. Note that in a queue
* with zero capacity, such as {@link SynchronousQueue}, {@code put}
* and {@code transfer} are effectively synonymous.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @since 1.7
* @author Doug Lea
* @param <E> the type of elements held in this collection
*/
public interface TransferQueue<E> extends BlockingQueue<E> {
/**
* Transfers the element to a waiting consumer immediately, if possible.
*
* <p>More precisely, transfers the specified element immediately
* if there exists a consumer already waiting to receive it (in
* {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
* otherwise returning {@code false} without enqueuing the element.
*
* @param e the element to transfer
* @return {@code true} if the element was transferred, else
* {@code false}
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this queue
*/
boolean tryTransfer(E e);
/**
* Transfers the element to a consumer, waiting if necessary to do so.
*
* <p>More precisely, transfers the specified element immediately
* if there exists a consumer already waiting to receive it (in
* {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
* else waits until the element is received by a consumer.
*
* @param e the element to transfer
* @throws InterruptedException if interrupted while waiting,
* in which case the element is not left enqueued
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this queue
*/
void transfer(E e) throws InterruptedException;
/**
* Transfers the element to a consumer if it is possible to do so
* before the timeout elapses.
*
* <p>More precisely, transfers the specified element immediately
* if there exists a consumer already waiting to receive it (in
* {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
* else waits until the element is received by a consumer,
* returning {@code false} if the specified wait time elapses
* before the element can be transferred.
*
* @param e the element to transfer
* @param timeout how long to wait before giving up, in units of
* {@code unit}
* @param unit a {@code TimeUnit} determining how to interpret the
* {@code timeout} parameter
* @return {@code true} if successful, or {@code false} if
* the specified waiting time elapses before completion,
* in which case the element is not left enqueued
* @throws InterruptedException if interrupted while waiting,
* in which case the element is not left enqueued
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this queue
*/
boolean tryTransfer(E e, long timeout, TimeUnit unit)
throws InterruptedException;
/**
* Returns {@code true} if there is at least one consumer waiting
* to receive an element via {@link #take} or
* timed {@link #poll(long,TimeUnit) poll}.
* The return value represents a momentary state of affairs.
*
* @return {@code true} if there is at least one waiting consumer
*/
boolean hasWaitingConsumer();
/**
* Returns an estimate of the number of consumers waiting to
* receive elements via {@link #take} or timed
* {@link #poll(long,TimeUnit) poll}. The return value is an
* approximation of a momentary state of affairs, that may be
* inaccurate if consumers have completed or given up waiting.
* The value may be useful for monitoring and heuristics, but
* not for synchronization control. Implementations of this
* method are likely to be noticeably slower than those for
* {@link #hasWaitingConsumer}.
*
* @return the number of consumers waiting to receive elements
*/
int getWaitingConsumerCount();
}
@@ -0,0 +1,76 @@
package com.alibaba.druid.bvt.sharding;
import java.util.List;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.sharding.config.LogicTable;
import com.alibaba.druid.sharding.config.MappingRule;
import com.alibaba.druid.sharding.config.MappingRuleAdapter;
import com.alibaba.druid.sharding.config.MappingRuleListEntry;
import com.alibaba.druid.sharding.config.RouteConfig;
import com.alibaba.druid.sharding.sql.MySqlShardingVisitor;
import com.alibaba.druid.sharding.sql.ShardingVisitor;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
public class InsertTest extends TestCase {
private RouteConfig routeConfig = new RouteConfig();
protected void setUp() throws Exception {
MappingRuleAdapter rule = new MappingRuleAdapter();
rule.setColumn("gender");
rule.getEntries().add(new MappingRuleListEntry("person_m", "M"));
rule.getEntries().add(new MappingRuleListEntry("person_f", "F"));
routeConfig.getMappingRules().put("person", rule);
LogicTable logicTable = new LogicTable();
logicTable.setLogicTable("person");
logicTable.addPartition("person_m", "db0", "person_001");
logicTable.addPartition("person_f", "db1", "person_002");
routeConfig.getLogicTables().put("person", logicTable);
}
public void test_insert_m() throws Exception {
String sql = "insert into person (name, gender) values ('a', 'M')";
SQLStatementParser parser = new MySqlStatementParser(sql);
List<SQLStatement> stmtList = parser.parseStatementList();
Assert.assertEquals(1, stmtList.size());
SQLStatement stmt = stmtList.get(0);
MySqlShardingVisitor visitor = new MySqlShardingVisitor(routeConfig);
stmt.accept(visitor);
String result = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT INTO person_001 (name, gender)" + //
"\nVALUES ('a', 'M')", result);
Assert.assertEquals("db0", stmt.getAttribute(ShardingVisitor.ATTR_DB));
}
public void test_insert_f() throws Exception {
String sql = "insert into person (name, gender) values ('a', 'F')";
SQLStatementParser parser = new MySqlStatementParser(sql);
List<SQLStatement> stmtList = parser.parseStatementList();
Assert.assertEquals(1, stmtList.size());
SQLStatement stmt = stmtList.get(0);
MySqlShardingVisitor visitor = new MySqlShardingVisitor(routeConfig);
stmt.accept(visitor);
String result = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT INTO person_002 (name, gender)" + //
"\nVALUES ('a', 'F')", result);
Assert.assertEquals("db1", stmt.getAttribute(ShardingVisitor.ATTR_DB));
}
}
@@ -24,13 +24,16 @@ import com.alibaba.druid.sql.test.TestUtils;
public class SQLServerInsertTest2 extends TestCase {
public void test_isEmpty() throws Exception {
String sql = "INSERT INTO Production.UnitMeasure " + //
"VALUES (N'F2', N'Square Feet', GETDATE());;";
public void test_multi_values() throws Exception {
String sql = "INSERT INTO test (name)" + //
"VALUES (N'a'), (N'b'), (N'c')";
String expect = "INSERT INTO Production.UnitMeasure" + //
String expect = "INSERT INTO test" + //
"\n\t(name)" + //
"\nVALUES" + //
"\n(N'F2', N'Square Feet', GETDATE())";
"\n(N'a')," + //
"\n(N'b')," + //
"\n(N'c')";
SQLServerStatementParser parser = new SQLServerStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
@@ -0,0 +1,44 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.
*/
package com.alibaba.druid.bvt.sql.sqlserver;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;
import com.alibaba.druid.sql.test.TestUtils;
public class SQLServerInsertTest3 extends TestCase {
public void test_isEmpty() throws Exception {
String sql = "INSERT INTO Production.UnitMeasure " + //
"VALUES (N'F2', N'Square Feet', GETDATE());;";
String expect = "INSERT INTO Production.UnitMeasure" + //
"\nVALUES" + //
"\n(N'F2', N'Square Feet', GETDATE())";
SQLServerStatementParser parser = new SQLServerStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
String text = TestUtils.outputSqlServer(stmt);
Assert.assertEquals(expect, text);
System.out.println(text);
}
}