DeleteStatementParserTest.java 10.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * 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>
 */
17

T
terrymanu 已提交
18
package com.dangdang.ddframe.rdb.sharding.parsing.parser.statement;
19

T
terrymanu 已提交
20
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
T
terrymanu 已提交
21
import com.dangdang.ddframe.rdb.sharding.constant.DatabaseType;
T
terrymanu 已提交
22
import com.dangdang.ddframe.rdb.sharding.parsing.SQLParsingEngine;
T
terrymanu 已提交
23
import com.dangdang.ddframe.rdb.sharding.constant.ShardingOperator;
T
terrymanu 已提交
24 25
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.ConditionContext;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.DeleteSQLContext;
26 27 28 29 30
import org.junit.Test;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
T
terrymanu 已提交
31
import java.util.List;
32 33 34 35

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
T
terrymanu 已提交
36
import static org.junit.Assert.assertTrue;
37 38 39 40 41

public final class DeleteStatementParserTest extends AbstractStatementParserTest {
    
    @Test
    public void parseWithoutCondition() throws SQLException {
T
terrymanu 已提交
42 43
        ShardingRule shardingRule = createShardingRule();
        List<Object> parameters = Collections.emptyList();
T
terrymanu 已提交
44
        SQLParsingEngine statementParser = new SQLParsingEngine(DatabaseType.MySQL, "DELETE FROM TABLE_XXX", shardingRule, parameters);
T
terrymanu 已提交
45 46
        DeleteSQLContext sqlContext = (DeleteSQLContext) statementParser.parseStatement();
        assertThat(sqlContext.getTables().get(0).getName(), is("TABLE_XXX"));
T
terrymanu 已提交
47
        assertThat(sqlContext.getSqlBuilder().toString(), is("DELETE FROM [Token(TABLE_XXX)]"));
48 49 50 51
    }
    
    @Test
    public void parseWithoutParameter() throws SQLException {
T
terrymanu 已提交
52 53
        ShardingRule shardingRule = createShardingRule();
        List<Object> parameters = Collections.emptyList();
T
terrymanu 已提交
54
        SQLParsingEngine statementParser = new SQLParsingEngine(DatabaseType.MySQL,
55
                "DELETE FROM TABLE_XXX xxx WHERE field4<10 AND TABLE_XXX.field1=1 AND field5>10 AND xxx.field2 IN (1,3) AND field6<=10 AND field3 BETWEEN 5 AND 20 AND field7>=10",
T
terrymanu 已提交
56
                shardingRule, parameters);
T
terrymanu 已提交
57
        DeleteSQLContext sqlContext = (DeleteSQLContext) statementParser.parseStatement();
T
terrymanu 已提交
58
        assertDeleteStatementWithoutParameter(sqlContext);
T
terrymanu 已提交
59
        assertThat(sqlContext.getSqlBuilder().toString(), is(
T
terrymanu 已提交
60
                "DELETE FROM [Token(TABLE_XXX)] xxx WHERE field4<10 AND [Token(TABLE_XXX)].field1=1 AND field5>10 AND xxx.field2 IN (1,3) AND field6<=10 AND field3 BETWEEN 5 AND 20 AND field7>=10"));
61 62
    }
    
T
terrymanu 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
    private void assertDeleteStatementWithoutParameter(final DeleteSQLContext sqlContext) {
        assertThat(sqlContext.getTables().get(0).getName(), is("TABLE_XXX"));
        assertThat(sqlContext.getTables().get(0).getAlias().get(), is("xxx"));
        ConditionContext.Condition condition1 = sqlContext.getConditionContext().find("TABLE_XXX", "field1").get();
        assertThat(condition1.getOperator(), is(ShardingOperator.EQUAL));
        assertThat(condition1.getValues().size(), is(1));
        assertThat(condition1.getValues().get(0), is((Comparable) 1));
        ConditionContext.Condition condition2 = sqlContext.getConditionContext().find("TABLE_XXX", "field2").get();
        assertThat(condition2.getOperator(), is(ShardingOperator.IN));
        assertThat(condition2.getValues().size(), is(2));
        assertThat(condition2.getValues().get(0), is((Comparable) 1));
        assertThat(condition2.getValues().get(1), is((Comparable) 3));
        ConditionContext.Condition condition3 = sqlContext.getConditionContext().find("TABLE_XXX", "field3").get();
        assertThat(condition3.getOperator(), is(ShardingOperator.BETWEEN));
        assertThat(condition3.getValues().size(), is(2));
        assertThat(condition3.getValues().get(0), is((Comparable) 5));
        assertThat(condition3.getValues().get(1), is((Comparable) 20));
    }
    
82 83
    @Test
    public void parseWithParameter() throws SQLException {
T
terrymanu 已提交
84 85
        ShardingRule shardingRule = createShardingRule();
        List<Object> parameters = Arrays.<Object>asList(10, 1, 10, 1, 3, 10, 5, 20, 10);
T
terrymanu 已提交
86
        SQLParsingEngine statementParser = new SQLParsingEngine(DatabaseType.MySQL, 
T
terrymanu 已提交
87
                "DELETE FROM TABLE_XXX xxx WHERE field4<? AND field1=? AND field5>? AND field2 IN (?,?) AND field6<=? AND field3 BETWEEN ? AND ? AND field7>=?", shardingRule, parameters);
T
terrymanu 已提交
88
        DeleteSQLContext sqlContext = (DeleteSQLContext) statementParser.parseStatement();
T
terrymanu 已提交
89
        assertDeleteStatementWithParameter(sqlContext);
T
terrymanu 已提交
90
        assertThat(sqlContext.getSqlBuilder().toString(), is(
91 92 93
                "DELETE FROM [Token(TABLE_XXX)] xxx WHERE field4<? AND field1=? AND field5>? AND field2 IN (?,?) AND field6<=? AND field3 BETWEEN ? AND ? AND field7>=?"));
    }
    
T
terrymanu 已提交
94
    private void assertDeleteStatementWithParameter(final DeleteSQLContext sqlContext) {
T
terrymanu 已提交
95 96
        assertThat(sqlContext.getTables().get(0).getName(), is("TABLE_XXX"));
        assertThat(sqlContext.getTables().get(0).getAlias().get(), is("xxx"));
T
terrymanu 已提交
97
        ConditionContext.Condition condition1 = sqlContext.getConditionContext().find("TABLE_XXX", "field1").get();
98
        assertThat(condition1.getOperator(), is(ShardingOperator.EQUAL));
T
terrymanu 已提交
99 100 101
        assertTrue(condition1.getValues().isEmpty());
        assertThat(condition1.getValueIndices().size(), is(1));
        assertThat(condition1.getValueIndices().get(0), is(1));
T
terrymanu 已提交
102
        ConditionContext.Condition condition2 = sqlContext.getConditionContext().find("TABLE_XXX", "field2").get();
103
        assertThat(condition2.getOperator(), is(ShardingOperator.IN));
T
terrymanu 已提交
104 105 106 107
        assertTrue(condition2.getValues().isEmpty());
        assertThat(condition2.getValueIndices().size(), is(2));
        assertThat(condition2.getValueIndices().get(0), is(3));
        assertThat(condition2.getValueIndices().get(1), is(4));
T
terrymanu 已提交
108
        ConditionContext.Condition condition3 = sqlContext.getConditionContext().find("TABLE_XXX", "field3").get();
109
        assertThat(condition3.getOperator(), is(ShardingOperator.BETWEEN));
T
terrymanu 已提交
110 111 112 113
        assertTrue(condition3.getValues().isEmpty());
        assertThat(condition3.getValueIndices().size(), is(2));
        assertThat(condition3.getValueIndices().get(0), is(6));
        assertThat(condition3.getValueIndices().get(1), is(7));
114 115 116 117
    }
    
    @Test(expected = UnsupportedOperationException.class)
    public void parseStatementWithDeleteMultipleTable() {
T
terrymanu 已提交
118 119
        ShardingRule shardingRule = createShardingRule();
        List<Object> parameters = Collections.emptyList();
T
terrymanu 已提交
120
        new SQLParsingEngine(DatabaseType.MySQL, "DELETE TABLE_XXX1, TABLE_xxx2 FROM TABLE_XXX1 JOIN TABLE_XXX2", shardingRule, parameters)
T
terrymanu 已提交
121
                .parseStatement();
122 123 124 125
    }
    
    @Test(expected = UnsupportedOperationException.class)
    public void parseStatementWithDeleteMultipleTableWithUsing() {
T
terrymanu 已提交
126 127
        ShardingRule shardingRule = createShardingRule();
        List<Object> parameters = Collections.emptyList();
T
terrymanu 已提交
128
        new SQLParsingEngine(DatabaseType.MySQL, "DELETE FROM TABLE_XXX1, TABLE_xxx2 USING TABLE_XXX1 JOIN TABLE_XXX2", shardingRule, parameters).parseStatement();
129 130 131 132
    }
    
    @Test
    public void parseWithSpecialSyntax() throws SQLException {
T
terrymanu 已提交
133 134
        parseWithSpecialSyntax(DatabaseType.MySQL, "DELETE `TABLE_XXX` WHERE `field1`=1", "DELETE [Token(TABLE_XXX)] WHERE `field1`=1");
        parseWithSpecialSyntax(DatabaseType.MySQL, "DELETE LOW_PRIORITY QUICK IGNORE TABLE_XXX PARTITION (partition_1) WHERE field1=1 ORDER BY field1 LIMIT 10",
135
                "DELETE LOW_PRIORITY QUICK IGNORE [Token(TABLE_XXX)] PARTITION (partition_1) WHERE field1=1 ORDER BY field1 LIMIT 10");
T
terrymanu 已提交
136
        parseWithSpecialSyntax(DatabaseType.MySQL, "DELETE FROM TABLE_XXX PARTITION (partition_1, partition_2,partition_3) WHERE field1=1",
137
                "DELETE FROM [Token(TABLE_XXX)] PARTITION (partition_1, partition_2,partition_3) WHERE field1=1");
T
terrymanu 已提交
138
        parseWithSpecialSyntax(DatabaseType.Oracle, "DELETE /*+ index(field1) */ ONLY (TABLE_XXX) WHERE field1=1 RETURN * LOG ERRORS INTO TABLE_LOG",
139
                "DELETE /*+ index(field1) */ ONLY ([Token(TABLE_XXX)]) WHERE field1=1 RETURN * LOG ERRORS INTO TABLE_LOG");
T
terrymanu 已提交
140
        parseWithSpecialSyntax(DatabaseType.Oracle, "DELETE /*+ index(field1) */ ONLY (TABLE_XXX) WHERE field1=1 RETURNING *",
141
                "DELETE /*+ index(field1) */ ONLY ([Token(TABLE_XXX)]) WHERE field1=1 RETURNING *");
142
        /* // TODO 不支持
T
terrymanu 已提交
143
        parseWithSpecialSyntax(DatabaseType.SQLServer,
144 145
                "WITH field_query (field1, field2) AS (SELECT field1, field2 FROM TABLE_XXX AS xxx GROUP BY field1) DELETE TOP(10) OUTPUT (inserted.field1) FROM TABLE_XXX WHERE field1=1",
                "WITH field_query (field1, field2) AS (SELECT field1, field2 FROM TABLE_XXX AS xxx GROUP BY field1) DELETE TOP(10) OUTPUT (inserted.field1) FROM [Token(TABLE_XXX)] WHERE field1=1");
146
                */
T
terrymanu 已提交
147
        parseWithSpecialSyntax(DatabaseType.PostgreSQL,
148 149
                "WITH RECURSIVE field_query (field1) AS (SELECT field1 FROM TABLE_XXX AS xxx ORDER BY field1 DESC) DELETE FROM ONLY TABLE_XXX USING producers WHERE field1=1 RETURNING *",
                "WITH RECURSIVE field_query (field1) AS (SELECT field1 FROM TABLE_XXX AS xxx ORDER BY field1 DESC) DELETE FROM ONLY [Token(TABLE_XXX)] USING producers WHERE field1=1 RETURNING *");
T
terrymanu 已提交
150
        parseWithSpecialSyntax(DatabaseType.PostgreSQL,
151 152
                "WITH field1_query AS (SELECT field1 FROM TABLE_XXX), field2_query AS (SELECT field2 FROM TABLE_XXX) DELETE FROM ONLY TABLE_XXX USING producers WHERE field1=1 OUTPUT *",
                "WITH field1_query AS (SELECT field1 FROM TABLE_XXX), field2_query AS (SELECT field2 FROM TABLE_XXX) DELETE FROM ONLY [Token(TABLE_XXX)] USING producers WHERE field1=1 OUTPUT *");
153 154
    }
    
T
terrymanu 已提交
155
    private void parseWithSpecialSyntax(final DatabaseType dbType, final String actualSQL, final String expectedSQL) {
T
terrymanu 已提交
156
        DeleteSQLContext sqlContext = (DeleteSQLContext) new SQLParsingEngine(dbType, actualSQL, createShardingRule(), Collections.emptyList()).parseStatement();
T
terrymanu 已提交
157 158
        assertThat(sqlContext.getTables().get(0).getName(), is("TABLE_XXX"));
        assertFalse(sqlContext.getTables().get(0).getAlias().isPresent());
T
terrymanu 已提交
159
        ConditionContext.Condition condition = sqlContext.getConditionContext().find("TABLE_XXX", "field1").get();
160
        assertThat(condition.getOperator(), is(ShardingOperator.EQUAL));
161 162
        assertThat(condition.getValues().size(), is(1));
        assertThat(condition.getValues().get(0), is((Comparable) 1));
T
terrymanu 已提交
163
        assertThat(sqlContext.getSqlBuilder().toString().replace("([Token(TABLE_XXX)] )", "([Token(TABLE_XXX)])"), is(expectedSQL));
164 165
    }
}