All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.lealone.sql.query.YieldableSelect Maven / Gradle / Ivy

/*
 * Copyright Lealone Database Group.
 * Licensed under the Server Side Public License, v 1.
 * Initial Developer: zhh
 */
package org.lealone.sql.query;

import org.lealone.db.PluginManager;
import org.lealone.db.async.AsyncHandler;
import org.lealone.db.async.AsyncResult;
import org.lealone.db.lock.DbObjectLock;
import org.lealone.db.result.LocalResult;
import org.lealone.db.result.Result;
import org.lealone.db.result.ResultTarget;
import org.lealone.db.session.SessionStatus;
import org.lealone.db.value.Value;
import org.lealone.db.value.ValueNull;
import org.lealone.sql.operator.Operator;
import org.lealone.sql.operator.OperatorFactory;

public class YieldableSelect extends YieldableQueryBase {

    private final Select select;
    private final ResultTarget target;
    private final int olapThreshold;
    private boolean olapDisabled;
    private Operator queryOperator;

    public YieldableSelect(Select select, int maxRows, boolean scrollable,
            AsyncHandler> asyncHandler, ResultTarget target) {
        super(select, maxRows, scrollable, asyncHandler);
        this.select = select;
        this.target = target;
        this.olapThreshold = session.getOlapThreshold();
    }

    @Override
    public boolean yieldIfNeeded(int rowNumber) {
        if (!olapDisabled && olapThreshold > 0 && rowNumber > olapThreshold) {
            olapDisabled = true;
            boolean yield = super.yieldIfNeeded(rowNumber);
            Operator olapOperator = createOlapOperator();
            if (olapOperator != null) {
                queryOperator = olapOperator;
                yield = true; // olapOperator创建成功后让出执行权
                session.setStatus(SessionStatus.STATEMENT_YIELDED);
            }
            return yield;
        }
        return super.yieldIfNeeded(rowNumber);
    }

    // 一些像QDistinct这样的Operator无需从oltp转到olap,可以禁用olap
    public void disableOlap() {
        olapDisabled = true;
    }

    private Operator createOlapOperator() {
        Operator olapOperator = null;
        String olapOperatorFactoryName = session.getOlapOperatorFactoryName();
        if (olapOperatorFactoryName == null) {
            olapOperatorFactoryName = "olap";
        }
        OperatorFactory operatorFactory = PluginManager.getPlugin(OperatorFactory.class,
                olapOperatorFactoryName);
        if (operatorFactory != null) {
            olapOperator = operatorFactory.createOperator(select, queryOperator.getLocalResult());
            olapOperator.start();
            olapOperator.copyStatus(queryOperator);
        }
        return olapOperator;
    }

    @Override
    protected boolean startInternal() {
        // select.getTopTableFilter().lock(session, select.isForUpdate);
        select.fireBeforeSelectTriggers();
        queryOperator = createQueryOperator();
        queryOperator.start();
        return false;
    }

    @Override
    protected void stopInternal() {
        // 执行startInternal抛异常时queryOperator可能为null
        if (queryOperator != null)
            queryOperator.stop();
    }

    @Override
    protected void executeInternal() {
        while (true) {
            session.setStatus(SessionStatus.STATEMENT_RUNNING);
            try {
                queryOperator.run();
            } catch (RuntimeException e) {
                if (DbObjectLock.LOCKED_EXCEPTION == e) {
                    queryOperator.onLockedException();
                } else {
                    throw e;
                }
            }
            if (queryOperator.isStopped()) {
                // 查询结果已经增加到target了
                if (target != null) {
                    session.setStatus(SessionStatus.STATEMENT_COMPLETED);
                } else if (queryOperator.getLocalResult() != null) {
                    LocalResult r = queryOperator.getLocalResult();
                    setResult(r, r.getRowCount());
                    select.resultCache.setResult(r);
                    session.setStatus(SessionStatus.STATEMENT_COMPLETED);
                }
                break;
            }
            if (session.getStatus() == SessionStatus.STATEMENT_YIELDED
                    || session.getStatus() == SessionStatus.WAITING) {
                return;
            }
        }
    }

    private QOperator createQueryOperator() {
        LocalResult result;
        ResultTarget to;
        QOperator queryOperator;
        int limitRows = getLimitRows(maxRows);
        LocalResult cachedResult = select.resultCache.getResult(maxRows); // 不直接用limitRows
        if (cachedResult != null) {
            result = cachedResult;
            to = cachedResult;
            queryOperator = new QCache(select, cachedResult);
        } else {
            result = createLocalResultIfNeeded(limitRows);
            to = result != null ? result : target;
            if (limitRows != 0) {
                if (select.isQuickAggregateQuery) {
                    queryOperator = new QAggregateQuick(select);
                } else if (select.isGroupQuery) {
                    if (select.isGroupSortedQuery) {
                        queryOperator = new QGroupSorted(select);
                    } else {
                        if (select.groupIndex == null) { // 忽视select.havingIndex
                            queryOperator = new QAggregate(select);
                        } else {
                            queryOperator = new QGroup(select);
                        }
                    }
                } else if (select.isDistinctQuery) {
                    queryOperator = new QDistinct(select);
                } else {
                    queryOperator = new QFlat(select);
                }
            } else {
                queryOperator = new QEmpty(select);
            }
        }
        queryOperator.columnCount = select.expressions.size();
        queryOperator.maxRows = limitRows;
        queryOperator.target = target;
        queryOperator.result = to;
        queryOperator.localResult = result;
        queryOperator.yieldableSelect = this;
        return queryOperator;
    }

    private int getLimitRows(int maxRows) {
        // 按JDBC规范的要求,当调用java.sql.Statement.setMaxRows时,
        // 如果maxRows是0,表示不限制行数,相当于没有调用过setMaxRows一样,
        // 如果小余0,已经在客户端抛了无效参数异常,所以这里统一处理: 当limitRows小于0时表示不限制行数。
        int limitRows = maxRows == 0 ? -1 : maxRows;
        if (select.limitExpr != null) {
            // 如果在select语句中又指定了limit子句,那么用它覆盖maxRows
            // 注意limit 0表示不取任何记录,跟maxRows为0时刚好相反
            Value v = select.limitExpr.getValue(session);
            int l = v == ValueNull.INSTANCE ? -1 : v.getInt();
            if (limitRows < 0) {
                limitRows = l;
            } else if (l >= 0) {
                limitRows = Math.min(l, limitRows);
            }
        }
        return limitRows;
    }

    private LocalResult createLocalResultIfNeeded(int limitRows) {
        LocalResult result = null;
        if (target == null || !session.getDatabase().getSettings().optimizeInsertFromSelect) {
            result = createLocalResult(result);
        }
        if (select.sort != null && (!select.sortUsingIndex || select.distinct)) {
            result = createLocalResult(result);
            result.setSortOrder(select.sort);
        }
        if (select.distinct && !select.isDistinctQuery) {
            result = createLocalResult(result);
            result.setDistinct();
        }
        if (select.isGroupQuery && !select.isGroupSortedQuery) {
            result = createLocalResult(result);
        }
        if (limitRows >= 0 || select.offsetExpr != null) {
            result = createLocalResult(result);
        }
        return result;
    }

    private LocalResult createLocalResult(LocalResult old) {
        return old != null ? old
                : new LocalResult(session, select.expressionArray, select.visibleColumnCount,
                        select.rawExpressionInfoList);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy