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

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

20
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
T
terrymanu 已提交
21
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.dialect.oracle.OracleKeyword;
T
terrymanu 已提交
22
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword;
T
terrymanu 已提交
23
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Keyword;
T
terrymanu 已提交
24
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Symbol;
T
terrymanu 已提交
25
import com.dangdang.ddframe.rdb.sharding.parsing.parser.AbstractSQLParser;
T
terrymanu 已提交
26
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.selectitem.SelectItem;
27
import com.dangdang.ddframe.rdb.sharding.parsing.parser.exception.SQLParsingUnsupportedException;
T
terrymanu 已提交
28
import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.dql.select.AbstractSelectParser;
29
import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.dql.select.SelectStatement;
30

T
terrymanu 已提交
31 32 33
import java.util.Collection;
import java.util.Collections;

T
terrymanu 已提交
34 35 36 37 38 39
/**
 * Oracle Select语句解析器.
 *
 * @author zhangliang
 */
public final class OracleSelectParser extends AbstractSelectParser {
40
    
41 42
    public OracleSelectParser(final ShardingRule shardingRule, final AbstractSQLParser sqlParser) {
        super(shardingRule, sqlParser);
43 44
    }
    
T
terrymanu 已提交
45
    @Override
T
terrymanu 已提交
46 47
    protected Collection<Keyword> getCustomizedDistinctKeywords() {
        return Collections.<Keyword>singletonList(DefaultKeyword.UNIQUE);
T
terrymanu 已提交
48 49
    }
    
T
terrymanu 已提交
50
    @Override
T
terrymanu 已提交
51
    protected Keyword[] getSkippedKeywordsBeforeSelectItem() {
T
terrymanu 已提交
52 53 54
        return new Keyword[] {OracleKeyword.CONNECT_BY_ROOT};
    }
    
T
terrymanu 已提交
55
    @Override
T
terrymanu 已提交
56
    protected void parseBetweenWhereAndGroupBy(final SelectStatement selectStatement) {
57
        skipHierarchicalQueryClause(selectStatement);
T
terrymanu 已提交
58 59
    }
    
60 61 62 63
    private void skipHierarchicalQueryClause(final SelectStatement selectStatement) {
        skipConnect(selectStatement);
        skipStart(selectStatement);
        skipConnect(selectStatement);
64 65
    }
    
66
    private void skipStart(final SelectStatement selectStatement) {
T
terrymanu 已提交
67 68
        if (getSqlParser().skipIfEqual(OracleKeyword.START)) {
            getSqlParser().accept(DefaultKeyword.WITH);
69
            getSqlParser().parseComparisonCondition(getShardingRule(), selectStatement, Collections.<SelectItem>emptyList());
70 71 72
        }
    }
    
73
    private void skipConnect(final SelectStatement selectStatement) {
T
terrymanu 已提交
74 75 76 77 78
        if (getSqlParser().skipIfEqual(OracleKeyword.CONNECT)) {
            getSqlParser().accept(DefaultKeyword.BY);
            getSqlParser().skipIfEqual(OracleKeyword.PRIOR);
            if (getSqlParser().skipIfEqual(OracleKeyword.NOCYCLE)) {
                getSqlParser().skipIfEqual(OracleKeyword.PRIOR);
79
            }
80
            getSqlParser().parseComparisonCondition(getShardingRule(), selectStatement, Collections.<SelectItem>emptyList());
81 82 83
        }
    }
    
T
terrymanu 已提交
84
    @Override
T
terrymanu 已提交
85
    protected void parseBetweenGroupByAndOrderBy(final SelectStatement selectStatement) {
T
terrymanu 已提交
86 87 88
        skipModelClause();
    }
    
89
    private void skipModelClause() {
T
terrymanu 已提交
90
        if (!getSqlParser().skipIfEqual(OracleKeyword.MODEL)) {
91 92 93
            return;
        }
        skipCellReferenceOptions();
T
terrymanu 已提交
94 95 96 97 98 99 100 101
        getSqlParser().skipIfEqual(OracleKeyword.RETURN);
        getSqlParser().skipIfEqual(DefaultKeyword.ALL);
        getSqlParser().skipIfEqual(OracleKeyword.UPDATED);
        getSqlParser().skipIfEqual(OracleKeyword.ROWS);
        while (getSqlParser().skipIfEqual(OracleKeyword.REFERENCE)) {
            getSqlParser().getLexer().nextToken();
            getSqlParser().accept(DefaultKeyword.ON);
            getSqlParser().skipParentheses();
102 103 104 105 106 107 108
            skipModelColumnClause();
            skipCellReferenceOptions();
        }
        skipMainModelClause();
    }
    
    private void skipCellReferenceOptions() {
T
terrymanu 已提交
109 110 111 112
        if (getSqlParser().skipIfEqual(OracleKeyword.IGNORE)) {
            getSqlParser().accept(OracleKeyword.NAV);
        } else if (getSqlParser().skipIfEqual(OracleKeyword.KEEP)) {
            getSqlParser().accept(OracleKeyword.NAV);
113
        }
T
terrymanu 已提交
114 115 116
        if (getSqlParser().skipIfEqual(DefaultKeyword.UNIQUE)) {
            getSqlParser().skipIfEqual(OracleKeyword.DIMENSION, OracleKeyword.SINGLE);
            getSqlParser().skipIfEqual(OracleKeyword.REFERENCE);
117 118 119 120
        }
    }
    
    private void skipMainModelClause() {
T
terrymanu 已提交
121 122
        if (getSqlParser().skipIfEqual(OracleKeyword.MAIN)) {
            getSqlParser().getLexer().nextToken();
123 124
        }
        skipQueryPartitionClause();
T
terrymanu 已提交
125 126 127 128 129
        getSqlParser().accept(OracleKeyword.DIMENSION);
        getSqlParser().accept(DefaultKeyword.BY);
        getSqlParser().skipParentheses();
        getSqlParser().accept(OracleKeyword.MEASURES);
        getSqlParser().skipParentheses();
130 131 132
        skipCellReferenceOptions();
        skipModelRulesClause();
    }
T
terrymanu 已提交
133
    
134
    private void skipModelRulesClause() {
T
terrymanu 已提交
135 136 137 138 139 140 141
        if (getSqlParser().skipIfEqual(OracleKeyword.RULES)) {
            getSqlParser().skipIfEqual(DefaultKeyword.UPDATE);
            getSqlParser().skipIfEqual(OracleKeyword.UPSERT);
            if (getSqlParser().skipIfEqual(OracleKeyword.AUTOMATIC)) {
                getSqlParser().accept(DefaultKeyword.ORDER);
            } else if (getSqlParser().skipIfEqual(OracleKeyword.SEQUENTIAL)) {
                getSqlParser().accept(DefaultKeyword.ORDER);
142 143
            }
        }
T
terrymanu 已提交
144 145 146 147
        if (getSqlParser().skipIfEqual(DefaultKeyword.ITERATE)) {
            getSqlParser().skipParentheses();
            if (getSqlParser().skipIfEqual(DefaultKeyword.UNTIL)) {
                getSqlParser().skipParentheses();
148 149
            }
        }
T
terrymanu 已提交
150
        getSqlParser().skipParentheses();
151 152 153
    }
    
    private void skipQueryPartitionClause() {
T
terrymanu 已提交
154 155 156 157
        if (getSqlParser().skipIfEqual(OracleKeyword.PARTITION)) {
            getSqlParser().accept(DefaultKeyword.BY);
            if (getSqlParser().equalAny(Symbol.LEFT_PAREN)) {
                getSqlParser().skipParentheses();
158 159 160 161 162
            } else {
                throw new UnsupportedOperationException("Cannot support PARTITION BY without ()");
            }
        }
    }
T
terrymanu 已提交
163
    
164
    private void skipModelColumnClause() {
T
terrymanu 已提交
165
        throw new SQLParsingUnsupportedException(getSqlParser().getLexer().getCurrentToken().getType());
166 167
    }
    
T
terrymanu 已提交
168
    @Override
T
terrymanu 已提交
169
    protected void parseRest(final SelectStatement selectStatement) {
T
terrymanu 已提交
170 171 172
        if (getSqlParser().equalAny(DefaultKeyword.FOR)) {
            skipForUpdate();
        }
173 174
        if (selectStatement.getOrderByItems().isEmpty()) {
            parseOrderBy(selectStatement);
T
terrymanu 已提交
175 176 177
        }
    }
    
T
terrymanu 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    private void skipForUpdate() {
        getSqlParser().getLexer().nextToken();
        getSqlParser().accept(DefaultKeyword.UPDATE);
        if (getSqlParser().skipIfEqual(DefaultKeyword.OF)) {
            do {
                getSqlParser().parseExpression();
            } while (getSqlParser().skipIfEqual(Symbol.COMMA));
        }
        if (getSqlParser().equalAny(OracleKeyword.NOWAIT, OracleKeyword.WAIT)) {
            getSqlParser().getLexer().nextToken();
        } else if (getSqlParser().skipIfEqual(OracleKeyword.SKIP)) {
            getSqlParser().accept(OracleKeyword.LOCKED);
        }
    }
    
193
    @Override
T
terrymanu 已提交
194
    protected void parseTableFactor(final SelectStatement selectStatement) {
T
terrymanu 已提交
195 196
        if (getSqlParser().skipIfEqual(OracleKeyword.ONLY)) {
            getSqlParser().skipIfEqual(Symbol.LEFT_PAREN);
197
            parseQueryTableExpression(selectStatement);
T
terrymanu 已提交
198
            getSqlParser().skipIfEqual(Symbol.RIGHT_PAREN);
199 200
            skipFlashbackQueryClause();
        } else {
201
            parseQueryTableExpression(selectStatement);
202 203 204 205 206
            skipPivotClause();
            skipFlashbackQueryClause();
        }
    }
    
207
    private void parseQueryTableExpression(final SelectStatement selectStatement) {
T
terrymanu 已提交
208
        parseTableFactorInternal(selectStatement);
209 210 211 212 213
        parseSample();
        skipPartition();
    }
    
    private void parseSample() {
T
terrymanu 已提交
214 215 216 217 218
        if (getSqlParser().skipIfEqual(OracleKeyword.SAMPLE)) {
            getSqlParser().skipIfEqual(OracleKeyword.BLOCK);
            getSqlParser().skipParentheses();
            if (getSqlParser().skipIfEqual(OracleKeyword.SEED)) {
                getSqlParser().skipParentheses();
219 220 221 222 223 224 225 226 227 228
            }
        }
    }
    
    private void skipPartition() {
        skipPartition(OracleKeyword.PARTITION);
        skipPartition(OracleKeyword.SUBPARTITION);
    }
    
    private void skipPartition(final OracleKeyword keyword) {
T
terrymanu 已提交
229 230 231 232
        if (getSqlParser().skipIfEqual(keyword)) {
            getSqlParser().skipParentheses();
            if (getSqlParser().skipIfEqual(DefaultKeyword.FOR)) {
                getSqlParser().skipParentheses();
233 234 235 236 237
            }
        }
    }
    
    private void skipFlashbackQueryClause() {
T
terrymanu 已提交
238
        if (isFlashbackQueryClauseForVersions() || isFlashbackQueryClauseForAs()) {
239 240 241 242
            throw new UnsupportedOperationException("Cannot support Flashback Query");
        }
    }
    
T
terrymanu 已提交
243 244 245 246 247
    private boolean isFlashbackQueryClauseForVersions() {
        return getSqlParser().skipIfEqual(OracleKeyword.VERSIONS) && getSqlParser().skipIfEqual(DefaultKeyword.BETWEEN);
    }
    
    private boolean isFlashbackQueryClauseForAs() {
248
        return getSqlParser().skipIfEqual(DefaultKeyword.AS) && getSqlParser().skipIfEqual(DefaultKeyword.OF)
T
terrymanu 已提交
249 250 251
                && (getSqlParser().skipIfEqual(OracleKeyword.SCN) || getSqlParser().skipIfEqual(OracleKeyword.TIMESTAMP));
    }
    
T
terrymanu 已提交
252 253 254 255 256 257 258 259 260 261 262
    private void skipPivotClause() {
        if (getSqlParser().skipIfEqual(OracleKeyword.PIVOT)) {
            getSqlParser().skipIfEqual(OracleKeyword.XML);
            getSqlParser().skipParentheses();
        } else if (getSqlParser().skipIfEqual(OracleKeyword.UNPIVOT)) {
            if (getSqlParser().skipIfEqual(OracleKeyword.INCLUDE)) {
                getSqlParser().accept(OracleKeyword.NULLS);
            } else if (getSqlParser().skipIfEqual(OracleKeyword.EXCLUDE)) {
                getSqlParser().accept(OracleKeyword.NULLS);
            }
            getSqlParser().skipParentheses();
263 264
        }
    }
265
    
T
terrymanu 已提交
266
    @Override
T
terrymanu 已提交
267 268
    protected Keyword[] getUnsupportedKeywordBeforeGroupByItem() {
        return new Keyword[] {OracleKeyword.ROLLUP, OracleKeyword.CUBE, OracleKeyword.GROUPING};
T
terrymanu 已提交
269 270
    }
    
271
    @Override
272
    protected void skipAfterOrderByItem(final SelectStatement selectStatement) {
T
terrymanu 已提交
273 274 275 276
        if (getSqlParser().skipIfEqual(OracleKeyword.NULLS)) {
            getSqlParser().getLexer().nextToken();
            if (!getSqlParser().skipIfEqual(OracleKeyword.FIRST, OracleKeyword.LAST)) {
                throw new SQLParsingUnsupportedException(getSqlParser().getLexer().getCurrentToken().getType());
277 278 279
            }
        }
    }
280
}