@uwdata/mosaic-sql
Version:
SQL query construction and analysis.
79 lines • 2.77 kB
JavaScript
import { WINDOW_EXTENT_EXPR, WINDOW_FRAME } from '../constants.js';
import { isParamLike } from '../util/type-check.js';
import { isNode, SQLNode } from './node.js';
import { ParamNode } from './param.js';
export const ROWS = 'ROWS';
export const RANGE = 'RANGE';
export const GROUPS = 'GROUPS';
export const PRECEDING = 'PRECEDING';
export const FOLLOWING = 'FOLLOWING';
export const CURRENT_ROW = 'CURRENT ROW';
export const UNBOUNDED = 'UNBOUNDED';
export class WindowFrameNode extends SQLNode {
/** The frame type, one of ROWS, RANGE, or GROUPS. */
frameType;
/** The window frame extent. */
extent;
/** The window frame exclusion criteria. */
exclude;
/**
* Instantiate a window frame definition node.
* @param frameType The frame type, one of ROWS, RANGE, or GROUPS.
* @param extent The window frame extent.
* @param exclude The window frame exclusion criteria.
*/
constructor(frameType, extent, exclude) {
super(WINDOW_FRAME);
this.frameType = frameType;
this.extent = isParamLike(extent) ? new ParamNode(extent) : extent;
this.exclude = exclude;
}
/**
* Generate a SQL query string for this node.
*/
toString() {
const { frameType, exclude, extent } = this;
const [prev, next] = isNode(extent)
? extent.value
: extent;
const a = asFrameExpr(prev, PRECEDING);
const b = asFrameExpr(next, FOLLOWING);
return `${frameType} BETWEEN ${a} AND ${b}${exclude ? ` ${exclude}` : ''}`;
}
}
function asFrameExpr(value, scope) {
return value instanceof WindowFrameExprNode ? value
: value != null && typeof value !== 'number' ? `${value} ${scope}`
: value === 0 ? CURRENT_ROW
: !(value && Number.isFinite(value)) ? `${UNBOUNDED} ${scope}`
: `${Math.abs(value)} ${scope}`;
}
export class WindowFrameExprNode extends SQLNode {
/** The window frame extent. */
scope;
/**
* The window frame extent expression. This value should be null
* in the case of current row or unbounded extent values.
*/
expr;
/**
* Instantiate a window frame definition node.
* @param scope The frame scope, one of PRECEDING, FOLLOWING, or CURRENT ROW.
* @param expr The window frame extent expression.
*/
constructor(scope, expr = null) {
super(WINDOW_EXTENT_EXPR);
this.scope = scope;
this.expr = expr;
}
/**
* Generate a SQL query string for this node.
*/
toString() {
const { scope, expr } = this;
return scope === CURRENT_ROW
? scope
: `${expr ?? UNBOUNDED} ${scope}`;
}
}
//# sourceMappingURL=window-frame.js.map