Commit 1cbb074d authored by terrymanu's avatar terrymanu
Browse files

fix #490

parent 97d12149
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -17,11 +17,15 @@

package io.shardingjdbc.core.merger;

import io.shardingjdbc.core.constant.DatabaseType;
import io.shardingjdbc.core.merger.groupby.GroupByMemoryResultSetMerger;
import io.shardingjdbc.core.merger.groupby.GroupByStreamResultSetMerger;
import io.shardingjdbc.core.merger.iterator.IteratorStreamResultSetMerger;
import io.shardingjdbc.core.merger.limit.LimitDecoratorResultSetMerger;
import io.shardingjdbc.core.merger.limit.RowNumberDecoratorResultSetMerger;
import io.shardingjdbc.core.merger.limit.TopAndRowNumberDecoratorResultSetMerger;
import io.shardingjdbc.core.merger.orderby.OrderByStreamResultSetMerger;
import io.shardingjdbc.core.parsing.parser.context.limit.Limit;
import io.shardingjdbc.core.parsing.parser.sql.dql.select.SelectStatement;
import io.shardingjdbc.core.util.SQLUtil;

@@ -86,10 +90,19 @@ public final class MergeEngine {
    }
    
    private ResultSetMerger decorate(final ResultSetMerger resultSetMerger) throws SQLException {
        ResultSetMerger result = resultSetMerger;
        if (null != selectStatement.getLimit()) {
            result = new LimitDecoratorResultSetMerger(result, selectStatement.getLimit());
        Limit limit = selectStatement.getLimit();
        if (null == limit) {
            return resultSetMerger;
        }
        return result;
        if (DatabaseType.MySQL == limit.getDatabaseType() || DatabaseType.PostgreSQL == limit.getDatabaseType() || DatabaseType.H2 == limit.getDatabaseType()) {
            return new LimitDecoratorResultSetMerger(resultSetMerger, selectStatement.getLimit());
        }
        if (DatabaseType.Oracle == limit.getDatabaseType()) {
            return new RowNumberDecoratorResultSetMerger(resultSetMerger, selectStatement.getLimit());
        }
        if (DatabaseType.SQLServer == limit.getDatabaseType()) {
            return new TopAndRowNumberDecoratorResultSetMerger(resultSetMerger, selectStatement.getLimit());
        }
        return resultSetMerger;
    }
}
+4 −4
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ import io.shardingjdbc.core.parsing.parser.context.limit.Limit;
import java.sql.SQLException;

/**
 * Decorator merger for limit.
 * Decorator merger for limit pagination.
 *
 * @author zhangliang
 */
@@ -57,9 +57,9 @@ public final class LimitDecoratorResultSetMerger extends AbstractDecoratorResult
        if (skipAll) {
            return false;
        }
        if (limit.getRowCountValue() > -1) {
            return ++rowNumber <= limit.getRowCountValue() && getResultSetMerger().next();
        }
        if (limit.getRowCountValue() < 0) {
            return getResultSetMerger().next();
        }
        return ++rowNumber <= limit.getRowCountValue() && getResultSetMerger().next();
    }
}
+69 −0
Original line number Diff line number Diff line
/*
 * 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>
 */

package io.shardingjdbc.core.merger.limit;

import io.shardingjdbc.core.merger.ResultSetMerger;
import io.shardingjdbc.core.merger.common.AbstractDecoratorResultSetMerger;
import io.shardingjdbc.core.parsing.parser.context.limit.Limit;

import java.sql.SQLException;

/**
 * Decorator merger for rownum pagination.
 *
 * @author zhangliang
 */
public final class RowNumberDecoratorResultSetMerger extends AbstractDecoratorResultSetMerger {
    
    private final Limit limit;
    
    private final boolean skipAll;
    
    private int rowNumber;
    
    public RowNumberDecoratorResultSetMerger(final ResultSetMerger resultSetMerger, final Limit limit) throws SQLException {
        super(resultSetMerger);
        this.limit = limit;
        skipAll = skipOffset();
    }
    
    private boolean skipOffset() throws SQLException {
        int end = limit.isIncludeOffset() ? limit.getOffsetValue() - 1 : limit.getOffsetValue();
        for (int i = 0; i < end; i++) {
            if (!getResultSetMerger().next()) {
                return true;
            }
        }
        rowNumber = limit.isRowCountRewriteFlag() ? 0 : end + 1;
        return false;
    }
    
    @Override
    public boolean next() throws SQLException {
        if (skipAll) {
            return false;
        }
        if (limit.getRowCountValue() < 0) {
            return getResultSetMerger().next();
        }
        if (limit.isIncludeRowCount()) {
            return rowNumber++ <= limit.getRowCountValue() && getResultSetMerger().next();
        }
        return rowNumber++ < limit.getRowCountValue() && getResultSetMerger().next();
    }
}
+66 −0
Original line number Diff line number Diff line
/*
 * 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>
 */

package io.shardingjdbc.core.merger.limit;

import io.shardingjdbc.core.merger.ResultSetMerger;
import io.shardingjdbc.core.merger.common.AbstractDecoratorResultSetMerger;
import io.shardingjdbc.core.parsing.parser.context.limit.Limit;

import java.sql.SQLException;

/**
 * Decorator merger for rownum pagination.
 *
 * @author zhangliang
 */
public final class TopAndRowNumberDecoratorResultSetMerger extends AbstractDecoratorResultSetMerger {
    
    private final Limit limit;
    
    private final boolean skipAll;
    
    private int rowNumber;
    
    public TopAndRowNumberDecoratorResultSetMerger(final ResultSetMerger resultSetMerger, final Limit limit) throws SQLException {
        super(resultSetMerger);
        this.limit = limit;
        skipAll = skipOffset();
    }
    
    private boolean skipOffset() throws SQLException {
        int end = limit.isIncludeOffset() ? limit.getOffsetValue() - 1 : limit.getOffsetValue();
        for (int i = 0; i < end; i++) {
            if (!getResultSetMerger().next()) {
                return true;
            }
        }
        rowNumber = limit.isRowCountRewriteFlag() ? 0 : end + 1;
        return false;
    }
    
    @Override
    public boolean next() throws SQLException {
        if (skipAll) {
            return false;
        }
        if (limit.getRowCountValue() < 0) {
            return getResultSetMerger().next();
        }
        return rowNumber++ <= limit.getRowCountValue() && getResultSetMerger().next();
    }
}
+23 −9
Original line number Diff line number Diff line
package io.shardingjdbc.core.parsing.parser.clause;

import io.shardingjdbc.core.constant.DatabaseType;
import io.shardingjdbc.core.rule.ShardingRule;
import io.shardingjdbc.core.parsing.lexer.LexerEngine;
import io.shardingjdbc.core.parsing.lexer.token.DefaultKeyword;
@@ -36,13 +37,16 @@ import java.util.List;
 */
public class WhereClauseParser implements SQLClauseParser {
    
    private final DatabaseType databaseType;
    
    private final LexerEngine lexerEngine;
    
    private final AliasClauseParser aliasClauseParser;
    
    private final ExpressionClauseParser expressionClauseParser;
    
    public WhereClauseParser(final LexerEngine lexerEngine) {
    public WhereClauseParser(final DatabaseType databaseType, final LexerEngine lexerEngine) {
        this.databaseType = databaseType;
        this.lexerEngine = lexerEngine;
        aliasClauseParser = new AliasClauseParser(lexerEngine);
        expressionClauseParser = new ExpressionClauseParser(lexerEngine);
@@ -88,12 +92,20 @@ public class WhereClauseParser implements SQLClauseParser {
            return;
        }
        if (sqlStatement instanceof SelectStatement && isRowNumberCondition(items, left)) {
            if (lexerEngine.skipIfEqual(Symbol.LT, Symbol.LT_EQ)) {
                parseRowCountCondition((SelectStatement) sqlStatement);
            if (lexerEngine.skipIfEqual(Symbol.LT)) {
                parseRowCountCondition((SelectStatement) sqlStatement, false);
                return;
            }
            if (lexerEngine.skipIfEqual(Symbol.LT_EQ)) {
                parseRowCountCondition((SelectStatement) sqlStatement, true);
                return;
            }
            if (lexerEngine.skipIfEqual(Symbol.GT)) {
                parseOffsetCondition((SelectStatement) sqlStatement, false);
                return;
            }
            if (lexerEngine.skipIfEqual(Symbol.GT, Symbol.GT_EQ)) {
                parseOffsetCondition((SelectStatement) sqlStatement);
            if (lexerEngine.skipIfEqual(Symbol.GT_EQ)) {
                parseOffsetCondition((SelectStatement) sqlStatement, true);
                return;
            }
        }
@@ -163,10 +175,10 @@ public class WhereClauseParser implements SQLClauseParser {
        return false;
    }
    
    private void parseRowCountCondition(final SelectStatement selectStatement) {
    private void parseRowCountCondition(final SelectStatement selectStatement, final boolean includeRowCount) {
        SQLExpression sqlExpression = expressionClauseParser.parse(selectStatement);
        if (null == selectStatement.getLimit()) {
            selectStatement.setLimit(new Limit(false));
            selectStatement.setLimit(new Limit(databaseType, false));
        }
        if (sqlExpression instanceof SQLNumberExpression) {
            int rowCount = ((SQLNumberExpression) sqlExpression).getNumber().intValue();
@@ -176,12 +188,13 @@ public class WhereClauseParser implements SQLClauseParser {
        } else if (sqlExpression instanceof SQLPlaceholderExpression) {
            selectStatement.getLimit().setRowCount(new LimitValue(-1, ((SQLPlaceholderExpression) sqlExpression).getIndex()));
        }
        selectStatement.getLimit().setIncludeRowCount(includeRowCount);
    }
    
    private void parseOffsetCondition(final SelectStatement selectStatement) {
    private void parseOffsetCondition(final SelectStatement selectStatement, final boolean includeOffset) {
        SQLExpression sqlExpression = expressionClauseParser.parse(selectStatement);
        if (null == selectStatement.getLimit()) {
            selectStatement.setLimit(new Limit(false));
            selectStatement.setLimit(new Limit(databaseType, false));
        }
        if (sqlExpression instanceof SQLNumberExpression) {
            int offset = ((SQLNumberExpression) sqlExpression).getNumber().intValue();
@@ -191,6 +204,7 @@ public class WhereClauseParser implements SQLClauseParser {
        } else if (sqlExpression instanceof SQLPlaceholderExpression) {
            selectStatement.getLimit().setOffset(new LimitValue(-1, ((SQLPlaceholderExpression) sqlExpression).getIndex()));
        }
        selectStatement.getLimit().setIncludeOffset(includeOffset);
    }
    
    protected Keyword[] getCustomizedOtherConditionOperators() {
Loading