DeleteStatementParserTest.java 9.3 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 21
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.constants.DatabaseType;
T
terrymanu 已提交
22
import com.dangdang.ddframe.rdb.sharding.parsing.SQLParsingEngine;
T
terrymanu 已提交
23 24 25
import com.dangdang.ddframe.rdb.sharding.parsing.parser.contstant.ShardingOperator;
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 36 37 38 39 40

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;

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