Repository: alibaba/fescar (java)

Issue:
com.alibaba.druid.sql.ast.expr.SQLBetweenExpr cannot be cast to com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr
jdbcTemplate.update("update itest2 set x=x+1 where id between 9 and 11 ");

throw an exception "com.alibaba.druid.sql.ast.expr.SQLBetweenExpr cannot be cast to com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr"

"id" is primarykey for table of itest2 , it is not support for "between" syntax ? ? 


Pull request description:
fixed issue #75,support BETWEEN in update statement.
<!-- Please make sure you have read and understood the contributing guidelines -->

### Ⅰ. Describe what this PR did
fixed issue #75,support BETWEEN in update statement.

### Ⅱ. Does this pull request fix one issue?
<!-- If that, add "fixes #xxx" below in the next line, for example, fixes #97. -->
fixes #75


### Ⅲ. Why don't you add test cases (unit test/integration test)? 


### Ⅳ. Describe how to verify it


### Ⅴ. Special notes for reviews



Patch:
diff --git a/core/src/main/java/com/alibaba/fescar/core/rpc/netty/NettyClientConfig.java b/core/src/main/java/com/alibaba/fescar/core/rpc/netty/NettyClientConfig.java
index 51872a6fb..07af6db81 100644
--- a/core/src/main/java/com/alibaba/fescar/core/rpc/netty/NettyClientConfig.java
+++ b/core/src/main/java/com/alibaba/fescar/core/rpc/netty/NettyClientConfig.java
@@ -51,7 +51,7 @@ public class NettyClientConfig extends NettyBaseConfig {
     private static final int DEFAULT_MIN_POOL_IDLE = 0;
     private static final boolean DEFAULT_POOL_TEST_BORROW = true;
     private static final boolean DEFAULT_POOL_TEST_RETURN = true;
-    private static final boolean DEFAULT_POOL_FIFO = true;
+    private static final boolean DEFAULT_POOL_LIFO = true;
 
     /**
      * Gets connect timeout millis.
@@ -423,8 +423,8 @@ public class NettyClientConfig extends NettyBaseConfig {
      *
      * @return the boolean
      */
-    public boolean isPoolFifo() {
-        return DEFAULT_POOL_FIFO;
+    public boolean isPoolLifo() {
+        return DEFAULT_POOL_LIFO;
     }
 
     /**
diff --git a/core/src/main/java/com/alibaba/fescar/core/rpc/netty/RmRpcClient.java b/core/src/main/java/com/alibaba/fescar/core/rpc/netty/RmRpcClient.java
index 212349ade..2f57ee260 100644
--- a/core/src/main/java/com/alibaba/fescar/core/rpc/netty/RmRpcClient.java
+++ b/core/src/main/java/com/alibaba/fescar/core/rpc/netty/RmRpcClient.java
@@ -190,7 +190,7 @@ public final class RmRpcClient extends AbstractRpcRemotingClient {
         poolConfig.maxWait = rmClientConfig.getMaxAcquireConnMills();
         poolConfig.testOnBorrow = rmClientConfig.isPoolTestBorrow();
         poolConfig.testOnReturn = rmClientConfig.isPoolTestReturn();
-        poolConfig.lifo = rmClientConfig.isPoolFifo();
+        poolConfig.lifo = rmClientConfig.isPoolLifo();
         return poolConfig;
     }
 
diff --git a/core/src/main/java/com/alibaba/fescar/core/rpc/netty/TmRpcClient.java b/core/src/main/java/com/alibaba/fescar/core/rpc/netty/TmRpcClient.java
index 5cdd38af1..5632b1678 100644
--- a/core/src/main/java/com/alibaba/fescar/core/rpc/netty/TmRpcClient.java
+++ b/core/src/main/java/com/alibaba/fescar/core/rpc/netty/TmRpcClient.java
@@ -83,7 +83,7 @@ public final class TmRpcClient extends AbstractRpcRemotingClient {
     private final AtomicBoolean initialized = new AtomicBoolean(false);
     private String applicationId;
     private String transactionServiceGroup;
-    private final NettyClientConfig nettyClientConfig;
+    private final NettyClientConfig tmClientConfig;
     private final ConcurrentMap<String, NettyPoolKey> poolKeyMap
         = new ConcurrentHashMap<String, NettyPoolKey>();
     /**
@@ -95,7 +95,7 @@ public final class TmRpcClient extends AbstractRpcRemotingClient {
                         EventExecutorGroup eventExecutorGroup,
                         ThreadPoolExecutor messageExecutor) {
         super(nettyClientConfig, eventExecutorGroup, messageExecutor);
-        this.nettyClientConfig = nettyClientConfig;
+        this.tmClientConfig = nettyClientConfig;
     }
 
     /**
@@ -357,12 +357,12 @@ public final class TmRpcClient extends AbstractRpcRemotingClient {
     @Override
     protected Config getNettyPoolConfig() {
         Config poolConfig = new Config();
-        poolConfig.maxActive = nettyClientConfig.getMaxPoolActive();
-        poolConfig.minIdle = nettyClientConfig.getMinPoolIdle();
-        poolConfig.maxWait = nettyClientConfig.getMaxAcquireConnMills();
-        poolConfig.testOnBorrow = nettyClientConfig.isPoolTestBorrow();
-        poolConfig.testOnReturn = nettyClientConfig.isPoolTestReturn();
-        poolConfig.lifo = nettyClientConfig.isPoolFifo();
+        poolConfig.maxActive = tmClientConfig.getMaxPoolActive();
+        poolConfig.minIdle = tmClientConfig.getMinPoolIdle();
+        poolConfig.maxWait = tmClientConfig.getMaxAcquireConnMills();
+        poolConfig.testOnBorrow = tmClientConfig.isPoolTestBorrow();
+        poolConfig.testOnReturn = tmClientConfig.isPoolTestReturn();
+        poolConfig.lifo = tmClientConfig.isPoolLifo();
         return poolConfig;
     }
 
diff --git a/discovery/src/main/java/com/alibaba/fescar/discovery/loadbalance/RandomLoadBalance.java b/discovery/src/main/java/com/alibaba/fescar/discovery/loadbalance/RandomLoadBalance.java
new file mode 100644
index 000000000..0b0a4a963
--- /dev/null
+++ b/discovery/src/main/java/com/alibaba/fescar/discovery/loadbalance/RandomLoadBalance.java
@@ -0,0 +1,19 @@
+package com.alibaba.fescar.discovery.loadbalance;
+
+import java.util.List;
+import java.util.Random;
+
+/**
+ * @author: yuoyao
+ * @date 2019/02/14
+ */
+public class RandomLoadBalance extends AbstractLoadBalance {
+
+    private final Random random=new Random();
+
+    @Override
+    protected <T> T doSelect(List<T> invokers) {
+        int length=invokers.size();
+        return invokers.get(random.nextInt(length));
+    }
+}
diff --git a/discovery/src/main/java/com/alibaba/fescar/discovery/loadbalance/RoundRobinLoadBalance.java b/discovery/src/main/java/com/alibaba/fescar/discovery/loadbalance/RoundRobinLoadBalance.java
index 55a210ada..2c795c909 100644
--- a/discovery/src/main/java/com/alibaba/fescar/discovery/loadbalance/RoundRobinLoadBalance.java
+++ b/discovery/src/main/java/com/alibaba/fescar/discovery/loadbalance/RoundRobinLoadBalance.java
@@ -17,6 +17,7 @@
 package com.alibaba.fescar.discovery.loadbalance;
 
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * The type Round robin load balance.
@@ -25,9 +26,23 @@ import java.util.List;
  * @date 2019 /02/12
  */
 public class RoundRobinLoadBalance extends AbstractLoadBalance {
+
+    private final AtomicInteger sequence  = new AtomicInteger();
+
     @Override
     protected <T> T doSelect(List<T> invokers) {
-        //todo
-        return invokers.get(0);
+        int length=invokers.size();
+        return invokers.get(getPositiveSequence() % length);
     }
+
+    private int getPositiveSequence() {
+        for (;;) {
+            int current = sequence.get();
+            int next = (current >= Integer.MAX_VALUE ? 0 : current + 1);
+            if (sequence.compareAndSet(current, next)) {
+                return current;
+            }
+        }
+    }
+
 }
diff --git a/rm-datasource/src/main/java/com/alibaba/fescar/rm/datasource/sql/druid/MySQLUpdateRecognizer.java b/rm-datasource/src/main/java/com/alibaba/fescar/rm/datasource/sql/druid/MySQLUpdateRecognizer.java
index 20b061590..5a0cc15df 100644
--- a/rm-datasource/src/main/java/com/alibaba/fescar/rm/datasource/sql/druid/MySQLUpdateRecognizer.java
+++ b/rm-datasource/src/main/java/com/alibaba/fescar/rm/datasource/sql/druid/MySQLUpdateRecognizer.java
@@ -21,11 +21,7 @@ import java.util.List;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.SQLStatement;
-import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
-import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
-import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
-import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
-import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
+import com.alibaba.druid.sql.ast.expr.*;
 import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
 import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
 import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
@@ -124,9 +120,19 @@ public class MySQLUpdateRecognizer extends BaseRecognizer implements SQLUpdateRe
         if (where == null) {
             return "";
         }
+
+
         StringBuffer sb = new StringBuffer();
         MySqlOutputVisitor visitor = new MySqlOutputVisitor(sb);
-        visitor.visit((SQLBinaryOpExpr) where);
+
+        if(where instanceof SQLBetweenExpr){
+            visitor.visit((SQLBetweenExpr) where);
+        }else if(where instanceof SQLInListExpr){
+            visitor.visit((SQLInListExpr) where);
+        }else{
+            visitor.visit((SQLBinaryOpExpr) where);
+        }
+
         return sb.toString();
     }
 


Test patch:
diff --git a/core/src/test/java/com/alibaba/fescar/core/rpc/netty/TmRpcClientTest.java b/core/src/test/java/com/alibaba/fescar/core/rpc/netty/TmRpcClientTest.java
index 699edd43b..9f943a2a5 100644
--- a/core/src/test/java/com/alibaba/fescar/core/rpc/netty/TmRpcClientTest.java
+++ b/core/src/test/java/com/alibaba/fescar/core/rpc/netty/TmRpcClientTest.java
@@ -60,7 +60,7 @@ public class TmRpcClientTest {
         Assert.assertEquals(defaultNettyClientConfig.getMaxAcquireConnMills(), config.maxWait);
         Assert.assertEquals(defaultNettyClientConfig.isPoolTestBorrow(), config.testOnBorrow);
         Assert.assertEquals(defaultNettyClientConfig.isPoolTestReturn(), config.testOnReturn);
-        Assert.assertEquals(defaultNettyClientConfig.isPoolFifo(), config.lifo);
+        Assert.assertEquals(defaultNettyClientConfig.isPoolLifo(), config.lifo);
     }
 
     /**
diff --git a/discovery/src/test/java/com/alibaba/fescar/discovery/loadbalance/LoadBalanceTest.java b/discovery/src/test/java/com/alibaba/fescar/discovery/loadbalance/LoadBalanceTest.java
new file mode 100644
index 000000000..dfb0febda
--- /dev/null
+++ b/discovery/src/test/java/com/alibaba/fescar/discovery/loadbalance/LoadBalanceTest.java
@@ -0,0 +1,71 @@
+package com.alibaba.fescar.discovery.loadbalance;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.testng.collections.Lists;
+
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Created by guoyao on 2019/2/14.
+ */
+public class LoadBalanceTest {
+
+
+    @Test(dataProvider = "addressProvider")
+    public void testRandomLoadBalance_select(List<InetSocketAddress> addresses) {
+        int runs=10000;
+        Map<InetSocketAddress, AtomicLong> counter=getSelectedCounter(runs, addresses, new RandomLoadBalance());
+        for (InetSocketAddress address : counter.keySet()) {
+            Long count=counter.get(address).get();
+            Assert.assertTrue(count > 0, "selecte one time at last");
+        }
+    }
+
+    @Test(dataProvider = "addressProvider")
+    public void testRoundRobinLoadBalance_select(List<InetSocketAddress> addresses) {
+        int runs=10000;
+        Map<InetSocketAddress, AtomicLong> counter=getSelectedCounter(runs,addresses, new RoundRobinLoadBalance());
+        for (InetSocketAddress address : counter.keySet()) {
+            Long count=counter.get(address).get();
+            Assert.assertTrue(Math.abs(count - runs / (0f + addresses.size())) < 1f,"abs diff shoud < 1");
+        }
+    }
+
+    public Map<InetSocketAddress, AtomicLong> getSelectedCounter(int runs, List<InetSocketAddress> addresses, LoadBalance loadBalance) {
+        Assert.assertNotNull(loadBalance);
+        Map<InetSocketAddress, AtomicLong> counter=new ConcurrentHashMap<>();
+        for (InetSocketAddress address : addresses) {
+            counter.put(address, new AtomicLong(0));
+        }
+        try {
+            for (int i=0; i < runs; i++) {
+                InetSocketAddress selectAddress=loadBalance.select(addresses);
+                counter.get(selectAddress).incrementAndGet();
+            }
+        } catch (Exception e) {
+            //do nothing
+        }
+        return counter;
+    }
+
+    @DataProvider
+    public static Object[][] addressProvider() {
+        List<InetSocketAddress> addresses=Lists.newArrayList();
+        addresses.add(new InetSocketAddress("127.0.0.1", 8091));
+        addresses.add(new InetSocketAddress("127.0.0.1", 8092));
+        addresses.add(new InetSocketAddress("127.0.0.1", 8093));
+        addresses.add(new InetSocketAddress("127.0.0.1", 8094));
+        addresses.add(new InetSocketAddress("127.0.0.1", 8095));
+        return new Object[][]{{addresses}};
+    }
+
+
+
+
+}