
io.questdb.griffin.model.WindowColumn Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of questdb Show documentation
Show all versions of questdb Show documentation
QuestDB is high performance SQL time series database
The newest version!
/*******************************************************************************
* ___ _ ____ ____
* / _ \ _ _ ___ ___| |_| _ \| __ )
* | | | | | | |/ _ \/ __| __| | | | _ \
* | |_| | |_| | __/\__ \ |_| |_| | |_) |
* \__\_\\__,_|\___||___/\__|____/|____/
*
* Copyright (c) 2014-2019 Appsicle
* Copyright (c) 2019-2024 QuestDB
*
* 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.
*
******************************************************************************/
package io.questdb.griffin.model;
import io.questdb.griffin.engine.functions.window.DenseRankFunctionFactory;
import io.questdb.griffin.engine.functions.window.FirstValueDoubleWindowFunctionFactory;
import io.questdb.griffin.engine.functions.window.LastValueDoubleWindowFunctionFactory;
import io.questdb.griffin.engine.functions.window.LeadLagWindowFunctionFactoryHelper;
import io.questdb.griffin.engine.functions.window.RankFunctionFactory;
import io.questdb.griffin.engine.functions.window.RowNumberFunctionFactory;
import io.questdb.std.Chars;
import io.questdb.std.IntList;
import io.questdb.std.ObjList;
import io.questdb.std.ObjectFactory;
public final class WindowColumn extends QueryColumn {
public static final int CURRENT = 3;
public static final int EXCLUDE_CURRENT_ROW = 1;
public static final int EXCLUDE_GROUP = 2;
public static final int EXCLUDE_NO_OTHERS = 4;
public static final int EXCLUDE_TIES = 3;
public final static ObjectFactory FACTORY = WindowColumn::new;
public static final int FOLLOWING = 2;
public static final int FRAMING_RANGE = 1;//1
public static final int FRAMING_ROWS = FRAMING_RANGE + 1;//2
public static final int FRAMING_GROUPS = FRAMING_ROWS + 1;//3
public static final int PRECEDING = 1;
public static final long TIME_UNIT_MICROSECOND = 1L;
public static final long TIME_UNIT_MILLISECOND = 1000 * TIME_UNIT_MICROSECOND;
public static final long TIME_UNIT_SECOND = 1000L * TIME_UNIT_MILLISECOND;
public static final long TIME_UNIT_MINUTE = 60 * TIME_UNIT_SECOND;
public static final long TIME_UNIT_HOUR = 60 * TIME_UNIT_MINUTE;
public static final long TIME_UNIT_DAY = 24 * TIME_UNIT_HOUR;
public static int ITME_UNIT_MICROSECOND = 1;
private final ObjList orderBy = new ObjList<>(2);
private final IntList orderByDirection = new IntList(2);
private final ObjList partitionBy = new ObjList<>(2);
private int exclusionKind = EXCLUDE_NO_OTHERS;
private int exclusionKindPos;
private int framingMode = FRAMING_RANGE;//default mode is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT
private boolean ignoreNulls = false;
private int nullsDescPos = 0;
private long rowsHi = Long.MAX_VALUE;
private ExpressionNode rowsHiExpr;
private int rowsHiExprPos;
private long rowsHiExprTimeUnit;
private int rowsHiExprTimeUnitPos;
private int rowsHiKind = CURRENT;
private int rowsHiKindPos = 0;
private long rowsLo = Long.MIN_VALUE;
private ExpressionNode rowsLoExpr;
private int rowsLoExprPos;
private long rowsLoExprTimeUnit;
private int rowsLoExprTimeUnitPos;
private int rowsLoKind = PRECEDING;
private int rowsLoKindPos = 0;
private WindowColumn() {
}
public void addOrderBy(ExpressionNode node, int direction) {
orderBy.add(node);
orderByDirection.add(direction);
}
@Override
public void clear() {
super.clear();
partitionBy.clear();
orderBy.clear();
orderByDirection.clear();
rowsLoExpr = null;
rowsLoExprPos = 0;
rowsLoExprTimeUnit = 1;
rowsLoExprTimeUnitPos = 0;
rowsHiExpr = null;
rowsHiExprPos = 0;
rowsHiExprTimeUnit = 1;
rowsHiExprTimeUnitPos = 0;
rowsLoKind = PRECEDING;
rowsLoKindPos = 0;
rowsHiKind = CURRENT;
rowsHiKindPos = 0;
framingMode = FRAMING_RANGE;
rowsLo = Long.MIN_VALUE;
rowsHi = Long.MAX_VALUE;
exclusionKind = EXCLUDE_NO_OTHERS;
exclusionKindPos = 0;
ignoreNulls = false;
nullsDescPos = 0;
}
public int getExclusionKind() {
return exclusionKind;
}
public int getExclusionKindPos() {
return exclusionKindPos;
}
public int getFramingMode() {
return framingMode;
}
public int getNullsDescPos() {
return nullsDescPos;
}
public ObjList getOrderBy() {
return orderBy;
}
public IntList getOrderByDirection() {
return orderByDirection;
}
public ObjList getPartitionBy() {
return partitionBy;
}
public long getRowsHi() {
return rowsHi;
}
public ExpressionNode getRowsHiExpr() {
return rowsHiExpr;
}
public int getRowsHiExprPos() {
return rowsHiExprPos;
}
public long getRowsHiExprTimeUnit() {
return rowsHiExprTimeUnit;
}
public int getRowsHiExprTimeUnitPos() {
return rowsHiExprTimeUnitPos;
}
public int getRowsHiKind() {
return rowsHiKind;
}
public int getRowsHiKindPos() {
return rowsHiKindPos;
}
public long getRowsLo() {
return rowsLo;
}
public ExpressionNode getRowsLoExpr() {
return rowsLoExpr;
}
public int getRowsLoExprPos() {
return rowsLoExprPos;
}
public long getRowsLoExprTimeUnit() {
return rowsLoExprTimeUnit;
}
public int getRowsLoExprTimeUnitPos() {
return rowsLoExprTimeUnitPos;
}
public int getRowsLoKind() {
return rowsLoKind;
}
public int getRowsLoKindPos() {
return rowsLoKindPos;
}
public boolean isIgnoreNulls() {
return ignoreNulls;
}
public boolean isNonDefaultFrame() {
// default mode is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT
// anything other than that is custom
return framingMode != FRAMING_RANGE || rowsLoKind != PRECEDING || rowsHiKind != CURRENT || rowsHiExpr != null || rowsLoExpr != null;
}
@Override
public boolean isWindowColumn() {
return true;
}
@Override
public WindowColumn of(CharSequence alias, ExpressionNode ast) {
return (WindowColumn) super.of(alias, ast);
}
public boolean requiresOrderBy() {
return framingMode == FRAMING_RANGE && (rowsLoKind != PRECEDING || (rowsHiKind != CURRENT && rowsHiKind != FOLLOWING) || rowsHiExpr != null || rowsLoExpr != null) ||
framingMode == FRAMING_GROUPS;
}
public void setExclusionKind(int exclusionKind, int exclusionKindPos) {
this.exclusionKind = exclusionKind;
this.exclusionKindPos = exclusionKindPos;
}
public void setFramingMode(int framingMode) {
this.framingMode = framingMode;
}
public void setIgnoreNulls(boolean ignoreNulls) {
this.ignoreNulls = ignoreNulls;
}
public void setNullsDescPos(int nullsDescPos) {
this.nullsDescPos = nullsDescPos;
}
public void setRowsHi(long rowsHi) {
this.rowsHi = rowsHi;
}
public void setRowsHiExpr(ExpressionNode rowsHiExpr, int rowsHiExprPos) {
this.rowsHiExpr = rowsHiExpr;
this.rowsHiExprPos = rowsHiExprPos;
}
public void setRowsHiExprTimeUnit(long unit) {
this.rowsHiExprTimeUnit = unit;
}
public void setRowsHiExprTimeUnit(long rowsHiExprTimeUnit, int rowsHiExprTimeUnitPos) {
this.rowsHiExprTimeUnit = rowsHiExprTimeUnit;
this.rowsHiExprTimeUnitPos = rowsHiExprTimeUnitPos;
}
public void setRowsHiExprTimeUnitPos(int rowsHiExprTimeUnitPos) {
this.rowsHiExprTimeUnitPos = rowsHiExprTimeUnitPos;
}
public void setRowsHiKind(int rowsHiKind, int rowsHiKindPos) {
this.rowsHiKind = rowsHiKind;
this.rowsHiKindPos = rowsHiKindPos;
}
public void setRowsLo(long rowsLo) {
this.rowsLo = rowsLo;
}
public void setRowsLoExpr(ExpressionNode rowsLoExpr, int rowsLoExprPos) {
this.rowsLoExpr = rowsLoExpr;
this.rowsLoExprPos = rowsLoExprPos;
}
public void setRowsLoExprTimeUnit(long rowsLoExprTimeUnit, int rowsLoExprTimeUnitPos) {
this.rowsLoExprTimeUnit = rowsLoExprTimeUnit;
this.rowsLoExprTimeUnitPos = rowsLoExprTimeUnitPos;
}
public void setRowsLoExprTimeUnitPos(int rowsLoExprTimeUnitPos) {
this.rowsLoExprTimeUnitPos = rowsLoExprTimeUnitPos;
}
public void setRowsLoKind(int rowsLoKind, int rowsLoKindPos) {
this.rowsLoKind = rowsLoKind;
this.rowsLoKindPos = rowsLoKindPos;
}
public boolean stopOrderByPropagate(ObjList modelOrder, IntList modelOrderDirection) {
CharSequence token = getAst().token;
// If this is an 'order' sensitive window function and there is no ORDER BY, it may depend on its child's ORDER BY clause.
if ((Chars.equalsIgnoreCase(token, FirstValueDoubleWindowFunctionFactory.NAME) ||
Chars.equalsIgnoreCase(token, LastValueDoubleWindowFunctionFactory.NAME)) &&
orderBy.size() == 0 && modelOrder.size() == 0) {
return true;
}
// Range frames work correctly depending on the ORDER BY clause of the subquery, which cannot be removed by the optimizer.
boolean stopOrderBy = framingMode == FRAMING_RANGE && isRangeFrameDependOnSubqueryOrderBy(getAst().token) &&
orderBy.size() > 0 && ((rowsHi != 0 || rowsLo != Long.MIN_VALUE) && !(rowsHi == Long.MAX_VALUE && rowsLo == Long.MIN_VALUE));
// Heuristic. If current recordCursor has orderBy column exactly same as orderBy of window frame, we continue to push the order.
if (stopOrderBy) {
boolean sameOrder = true;
if (modelOrder.size() < orderBy.size()) {
sameOrder = false;
} else {
for (int i = 0, max = orderBy.size(); i < max; i++) {
if (!Chars.equalsIgnoreCase(modelOrder.getQuick(i).token, orderBy.getQuick(i).token) ||
modelOrderDirection.getQuick(i) != orderByDirection.getQuick(i)) {
sameOrder = false;
break;
}
}
}
stopOrderBy = !sameOrder;
}
return stopOrderBy;
}
private static boolean isRangeFrameDependOnSubqueryOrderBy(CharSequence funName) {
return !Chars.equalsIgnoreCase(funName, RowNumberFunctionFactory.NAME)
&& !Chars.equalsIgnoreCase(funName, RankFunctionFactory.NAME)
&& !Chars.equalsIgnoreCase(funName, DenseRankFunctionFactory.NAME)
&& !Chars.equalsIgnoreCase(funName, LeadLagWindowFunctionFactoryHelper.LEAD_NAME)
&& !Chars.equalsIgnoreCase(funName, LeadLagWindowFunctionFactoryHelper.LAG_NAME);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy