flowquery 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/npm-publish.yml +30 -0
- package/.github/workflows/release.yml +84 -0
- package/CODE_OF_CONDUCT.md +10 -0
- package/FlowQueryLogoIcon.png +0 -0
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/SECURITY.md +14 -0
- package/SUPPORT.md +13 -0
- package/docs/flowquery.min.js +1 -0
- package/docs/index.html +105 -0
- package/flowquery-vscode/.vscode-test.mjs +5 -0
- package/flowquery-vscode/.vscodeignore +13 -0
- package/flowquery-vscode/LICENSE +21 -0
- package/flowquery-vscode/README.md +11 -0
- package/flowquery-vscode/demo/FlowQueryVSCodeDemo.gif +0 -0
- package/flowquery-vscode/eslint.config.mjs +25 -0
- package/flowquery-vscode/extension.js +508 -0
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -0
- package/flowquery-vscode/flowquery-worker.js +66 -0
- package/flowquery-vscode/images/FlowQueryLogoIcon.png +0 -0
- package/flowquery-vscode/jsconfig.json +13 -0
- package/flowquery-vscode/libs/page.css +53 -0
- package/flowquery-vscode/libs/table.css +13 -0
- package/flowquery-vscode/libs/tabs.css +66 -0
- package/flowquery-vscode/package-lock.json +2917 -0
- package/flowquery-vscode/package.json +51 -0
- package/flowquery-vscode/test/extension.test.js +196 -0
- package/flowquery-vscode/test/worker.test.js +25 -0
- package/flowquery-vscode/vsc-extension-quickstart.md +42 -0
- package/jest.config.js +11 -0
- package/package.json +28 -0
- package/queries/analyze_catfacts.cql +75 -0
- package/queries/azure_openai_completions.cql +13 -0
- package/queries/azure_openai_models.cql +9 -0
- package/queries/mock_pipeline.cql +84 -0
- package/queries/openai_completions.cql +15 -0
- package/queries/openai_models.cql +13 -0
- package/queries/test.cql +6 -0
- package/queries/tool_inference.cql +24 -0
- package/queries/wisdom.cql +6 -0
- package/queries/wisdom_letter_histogram.cql +8 -0
- package/src/compute/runner.ts +65 -0
- package/src/index.browser.ts +11 -0
- package/src/index.ts +12 -0
- package/src/io/command_line.ts +74 -0
- package/src/parsing/alias.ts +23 -0
- package/src/parsing/alias_option.ts +5 -0
- package/src/parsing/ast_node.ts +153 -0
- package/src/parsing/base_parser.ts +92 -0
- package/src/parsing/components/csv.ts +9 -0
- package/src/parsing/components/from.ts +12 -0
- package/src/parsing/components/headers.ts +12 -0
- package/src/parsing/components/json.ts +9 -0
- package/src/parsing/components/null.ts +9 -0
- package/src/parsing/components/post.ts +9 -0
- package/src/parsing/components/text.ts +9 -0
- package/src/parsing/context.ts +48 -0
- package/src/parsing/data_structures/associative_array.ts +43 -0
- package/src/parsing/data_structures/json_array.ts +31 -0
- package/src/parsing/data_structures/key_value_pair.ts +37 -0
- package/src/parsing/data_structures/lookup.ts +40 -0
- package/src/parsing/data_structures/range_lookup.ts +36 -0
- package/src/parsing/expressions/expression.ts +142 -0
- package/src/parsing/expressions/f_string.ts +26 -0
- package/src/parsing/expressions/identifier.ts +22 -0
- package/src/parsing/expressions/number.ts +40 -0
- package/src/parsing/expressions/operator.ts +179 -0
- package/src/parsing/expressions/reference.ts +42 -0
- package/src/parsing/expressions/string.ts +34 -0
- package/src/parsing/functions/aggregate_function.ts +58 -0
- package/src/parsing/functions/avg.ts +37 -0
- package/src/parsing/functions/collect.ts +44 -0
- package/src/parsing/functions/function.ts +60 -0
- package/src/parsing/functions/function_factory.ts +66 -0
- package/src/parsing/functions/join.ts +26 -0
- package/src/parsing/functions/predicate_function.ts +44 -0
- package/src/parsing/functions/predicate_function_factory.ts +15 -0
- package/src/parsing/functions/predicate_sum.ts +29 -0
- package/src/parsing/functions/rand.ts +13 -0
- package/src/parsing/functions/range.ts +18 -0
- package/src/parsing/functions/reducer_element.ts +10 -0
- package/src/parsing/functions/replace.ts +19 -0
- package/src/parsing/functions/round.ts +17 -0
- package/src/parsing/functions/size.ts +17 -0
- package/src/parsing/functions/split.ts +26 -0
- package/src/parsing/functions/stringify.ts +26 -0
- package/src/parsing/functions/sum.ts +31 -0
- package/src/parsing/functions/to_json.ts +17 -0
- package/src/parsing/functions/value_holder.ts +13 -0
- package/src/parsing/logic/case.ts +26 -0
- package/src/parsing/logic/else.ts +12 -0
- package/src/parsing/logic/end.ts +9 -0
- package/src/parsing/logic/then.ts +12 -0
- package/src/parsing/logic/when.ts +12 -0
- package/src/parsing/operations/aggregated_return.ts +18 -0
- package/src/parsing/operations/aggregated_with.ts +18 -0
- package/src/parsing/operations/group_by.ts +124 -0
- package/src/parsing/operations/limit.ts +22 -0
- package/src/parsing/operations/load.ts +92 -0
- package/src/parsing/operations/operation.ts +65 -0
- package/src/parsing/operations/projection.ts +18 -0
- package/src/parsing/operations/return.ts +43 -0
- package/src/parsing/operations/unwind.ts +32 -0
- package/src/parsing/operations/where.ts +38 -0
- package/src/parsing/operations/with.ts +20 -0
- package/src/parsing/parser.ts +762 -0
- package/src/parsing/token_to_node.ts +91 -0
- package/src/tokenization/keyword.ts +43 -0
- package/src/tokenization/operator.ts +25 -0
- package/src/tokenization/string_walker.ts +194 -0
- package/src/tokenization/symbol.ts +15 -0
- package/src/tokenization/token.ts +633 -0
- package/src/tokenization/token_mapper.ts +53 -0
- package/src/tokenization/token_type.ts +15 -0
- package/src/tokenization/tokenizer.ts +229 -0
- package/src/tokenization/trie.ts +117 -0
- package/src/utils/object_utils.ts +17 -0
- package/src/utils/string_utils.ts +114 -0
- package/tests/compute/runner.test.ts +498 -0
- package/tests/parsing/context.test.ts +27 -0
- package/tests/parsing/expression.test.ts +40 -0
- package/tests/parsing/parser.test.ts +434 -0
- package/tests/tokenization/token_mapper.test.ts +47 -0
- package/tests/tokenization/tokenizer.test.ts +67 -0
- package/tests/tokenization/trie.test.ts +20 -0
- package/tsconfig.json +15 -0
- package/typedoc.json +16 -0
- package/webpack.config.js +26 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import ASTNode from "../ast_node";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a lookup operation (array/object indexing) in the AST.
|
|
5
|
+
*
|
|
6
|
+
* Lookups access elements from arrays or properties from objects using an index or key.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // For array[0] or obj.property or obj["key"]
|
|
11
|
+
* const lookup = new Lookup();
|
|
12
|
+
* lookup.variable = arrayOrObjNode;
|
|
13
|
+
* lookup.index = indexNode;
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
class Lookup extends ASTNode {
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
}
|
|
20
|
+
public set index(index: ASTNode) {
|
|
21
|
+
this.addChild(index);
|
|
22
|
+
}
|
|
23
|
+
public get index(): ASTNode {
|
|
24
|
+
return this.children[0];
|
|
25
|
+
}
|
|
26
|
+
public set variable(variable: ASTNode) {
|
|
27
|
+
this.addChild(variable);
|
|
28
|
+
}
|
|
29
|
+
public get variable(): ASTNode {
|
|
30
|
+
return this.children[1];
|
|
31
|
+
}
|
|
32
|
+
public isOperand(): boolean {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
public value(): any {
|
|
36
|
+
return this.variable.value()[this.index.value()];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default Lookup;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import ASTNode from "../ast_node";
|
|
2
|
+
|
|
3
|
+
class RangeLookup extends ASTNode {
|
|
4
|
+
constructor() {
|
|
5
|
+
super();
|
|
6
|
+
}
|
|
7
|
+
public set from(from: ASTNode) {
|
|
8
|
+
this.addChild(from);
|
|
9
|
+
}
|
|
10
|
+
public get from(): ASTNode {
|
|
11
|
+
return this.children[0];
|
|
12
|
+
}
|
|
13
|
+
public set to(to: ASTNode) {
|
|
14
|
+
this.addChild(to);
|
|
15
|
+
}
|
|
16
|
+
public get to(): ASTNode {
|
|
17
|
+
return this.children[1];
|
|
18
|
+
}
|
|
19
|
+
public set variable(variable: ASTNode) {
|
|
20
|
+
this.addChild(variable);
|
|
21
|
+
}
|
|
22
|
+
public get variable(): ASTNode {
|
|
23
|
+
return this.children[2];
|
|
24
|
+
}
|
|
25
|
+
public isOperand(): boolean {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
public value(): any {
|
|
29
|
+
const array: any[] = this.variable.value();
|
|
30
|
+
const from = this.from.value() || 0;
|
|
31
|
+
const to = this.to.value() || array.length;
|
|
32
|
+
return this.variable.value().slice(from, to);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default RangeLookup;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import ASTNode from "../ast_node";
|
|
2
|
+
import AggregateFunction from "../functions/aggregate_function";
|
|
3
|
+
import Reference from "./reference";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Represents an expression in the FlowQuery AST.
|
|
7
|
+
*
|
|
8
|
+
* Expressions are built using the Shunting Yard algorithm to handle operator
|
|
9
|
+
* precedence and associativity. They can contain operands (numbers, strings, identifiers)
|
|
10
|
+
* and operators (arithmetic, logical, comparison).
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const expr = new Expression();
|
|
15
|
+
* expr.addNode(numberNode);
|
|
16
|
+
* expr.addNode(plusOperator);
|
|
17
|
+
* expr.addNode(anotherNumberNode);
|
|
18
|
+
* expr.finish();
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
class Expression extends ASTNode {
|
|
22
|
+
private operators: ASTNode[] = <ASTNode[]>[];
|
|
23
|
+
private output: ASTNode[] = <ASTNode[]>[];
|
|
24
|
+
private _alias: string | null = null;
|
|
25
|
+
private _overridden: any | null = null;
|
|
26
|
+
private _reducers: AggregateFunction[] | null = null;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Adds a node (operand or operator) to the expression.
|
|
30
|
+
*
|
|
31
|
+
* Uses the Shunting Yard algorithm to maintain correct operator precedence.
|
|
32
|
+
*
|
|
33
|
+
* @param node - The AST node to add (operand or operator)
|
|
34
|
+
*/
|
|
35
|
+
public addNode(node: ASTNode): void {
|
|
36
|
+
/* Implements the Shunting Yard algorithm */
|
|
37
|
+
if(node.isOperand()) {
|
|
38
|
+
this.output.push(node);
|
|
39
|
+
} else if(node.isOperator()) {
|
|
40
|
+
const operator1: ASTNode = node;
|
|
41
|
+
while(this.operators.length > 0) {
|
|
42
|
+
let operator2 = this.operators[this.operators.length - 1];
|
|
43
|
+
if(
|
|
44
|
+
operator2.precedence > operator1.precedence ||
|
|
45
|
+
(operator2.precedence === operator1.precedence && operator1.leftAssociative)
|
|
46
|
+
) {
|
|
47
|
+
this.output.push(operator2);
|
|
48
|
+
this.operators.pop();
|
|
49
|
+
} else {
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
this.operators.push(operator1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Finalizes the expression by converting it to a tree structure.
|
|
59
|
+
*
|
|
60
|
+
* Should be called after all nodes have been added.
|
|
61
|
+
*/
|
|
62
|
+
public finish(): void {
|
|
63
|
+
let last: ASTNode | undefined;
|
|
64
|
+
while(last = this.operators.pop()) {
|
|
65
|
+
this.output.push(last);
|
|
66
|
+
};
|
|
67
|
+
this.addChild(this.toTree());
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private toTree(): ASTNode {
|
|
71
|
+
const node = this.output.pop() || new ASTNode();
|
|
72
|
+
if(node.isOperator()) {
|
|
73
|
+
const rhs = this.toTree();
|
|
74
|
+
const lhs = this.toTree();
|
|
75
|
+
node.addChild(lhs);
|
|
76
|
+
node.addChild(rhs);
|
|
77
|
+
}
|
|
78
|
+
return node;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public nodesAdded(): boolean {
|
|
82
|
+
return this.operators.length > 0 || this.output.length > 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public value(): any {
|
|
86
|
+
if(this._overridden !== null) {
|
|
87
|
+
return this._overridden;
|
|
88
|
+
}
|
|
89
|
+
if(this.childCount() !== 1) {
|
|
90
|
+
throw new Error('Expected one child');
|
|
91
|
+
}
|
|
92
|
+
return this.children[0].value();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public setAlias(alias: string): void {
|
|
96
|
+
this._alias = alias;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public set alias(alias: string) {
|
|
100
|
+
this._alias = alias;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public get alias(): string | null {
|
|
104
|
+
if(this.firstChild() instanceof Reference && this._alias === null) {
|
|
105
|
+
return (<Reference>this.firstChild()).identifier;
|
|
106
|
+
}
|
|
107
|
+
return this._alias;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public toString(): string {
|
|
111
|
+
if(this._alias !== null) {
|
|
112
|
+
return `Expression (${this._alias})`;
|
|
113
|
+
} else {
|
|
114
|
+
return 'Expression';
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
public reducers(): AggregateFunction[] {
|
|
118
|
+
if(this._reducers === null) {
|
|
119
|
+
this._reducers = [...this._extract_reducers()];
|
|
120
|
+
}
|
|
121
|
+
return this._reducers;
|
|
122
|
+
}
|
|
123
|
+
private *_extract_reducers(node: ASTNode = this): Generator<AggregateFunction> {
|
|
124
|
+
if(node instanceof AggregateFunction) {
|
|
125
|
+
yield node;
|
|
126
|
+
}
|
|
127
|
+
for(const child of node.getChildren()) {
|
|
128
|
+
yield* this._extract_reducers(child);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
public mappable(): boolean {
|
|
132
|
+
return this.reducers().length === 0;
|
|
133
|
+
}
|
|
134
|
+
public has_reducers(): boolean {
|
|
135
|
+
return this.reducers().length > 0;
|
|
136
|
+
}
|
|
137
|
+
public set overridden(value: any) {
|
|
138
|
+
this._overridden = value;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export default Expression;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import ASTNode from "../ast_node";
|
|
2
|
+
import Expression from "./expression";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Represents a formatted string (f-string) in the AST.
|
|
6
|
+
*
|
|
7
|
+
* F-strings allow embedding expressions within string literals.
|
|
8
|
+
* Child nodes represent the parts of the f-string (literal strings and expressions).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // For f"Hello {name}!"
|
|
13
|
+
* const fstr = new FString();
|
|
14
|
+
* fstr.addChild(new String("Hello "));
|
|
15
|
+
* fstr.addChild(nameExpression);
|
|
16
|
+
* fstr.addChild(new String("!"));
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
class FString extends ASTNode {
|
|
20
|
+
public value(): string {
|
|
21
|
+
const parts: Expression[] = this.getChildren() as Array<Expression>;
|
|
22
|
+
return parts.map((part) => part.value()).join("");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default FString;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import String from "./string";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents an identifier in the AST.
|
|
5
|
+
*
|
|
6
|
+
* Identifiers are used for variable names, property names, and similar constructs.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const id = new Identifier("myVariable");
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
class Identifier extends String {
|
|
14
|
+
public toString(): string {
|
|
15
|
+
return `Identifier (${this._value})`;
|
|
16
|
+
}
|
|
17
|
+
public value(): any {
|
|
18
|
+
return super.value();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default Identifier;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import ASTNode from "../ast_node";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a numeric literal in the AST.
|
|
5
|
+
*
|
|
6
|
+
* Parses string representations of numbers into integer or float values.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const num = new Number("42");
|
|
11
|
+
* console.log(num.value()); // 42
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
class Number extends ASTNode {
|
|
15
|
+
private _value: number;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Creates a new Number node by parsing the string value.
|
|
19
|
+
*
|
|
20
|
+
* @param value - The string representation of the number
|
|
21
|
+
*/
|
|
22
|
+
constructor(value: string) {
|
|
23
|
+
super();
|
|
24
|
+
if(value.indexOf('.') !== -1) {
|
|
25
|
+
this._value = parseFloat(value);
|
|
26
|
+
} else {
|
|
27
|
+
this._value = parseInt(value);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public value(): number {
|
|
32
|
+
return this._value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
protected toString(): string {
|
|
36
|
+
return `${this.constructor.name} (${this._value})`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default Number;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import ASTNode from "../ast_node";
|
|
2
|
+
|
|
3
|
+
abstract class Operator extends ASTNode {
|
|
4
|
+
private _precedence: number = 0;
|
|
5
|
+
private _leftAssociative: boolean = true;
|
|
6
|
+
|
|
7
|
+
constructor(precedence: number, leftAssociative: boolean) {
|
|
8
|
+
super();
|
|
9
|
+
this._precedence = precedence;
|
|
10
|
+
this._leftAssociative = leftAssociative;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public isOperator(): boolean {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public get precedence(): number {
|
|
18
|
+
return this._precedence;
|
|
19
|
+
}
|
|
20
|
+
public get leftAssociative(): boolean {
|
|
21
|
+
return this._leftAssociative;
|
|
22
|
+
}
|
|
23
|
+
public abstract value(): number;
|
|
24
|
+
public get lhs(): ASTNode {
|
|
25
|
+
return this.getChildren()[0];
|
|
26
|
+
}
|
|
27
|
+
public get rhs(): ASTNode {
|
|
28
|
+
return this.getChildren()[1];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class Add extends Operator {
|
|
33
|
+
constructor() {
|
|
34
|
+
super(1, true);
|
|
35
|
+
}
|
|
36
|
+
public value(): number {
|
|
37
|
+
return this.lhs.value() + this.rhs.value();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class Subtract extends Operator {
|
|
42
|
+
constructor() {
|
|
43
|
+
super(1, true);
|
|
44
|
+
}
|
|
45
|
+
public value(): number {
|
|
46
|
+
return this.lhs.value() - this.rhs.value();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
class Multiply extends Operator {
|
|
51
|
+
constructor() {
|
|
52
|
+
super(2, true);
|
|
53
|
+
}
|
|
54
|
+
public value(): number {
|
|
55
|
+
return this.lhs.value() * this.rhs.value();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
class Divide extends Operator {
|
|
60
|
+
constructor() {
|
|
61
|
+
super(2, true);
|
|
62
|
+
}
|
|
63
|
+
public value(): number {
|
|
64
|
+
return this.lhs.value() / this.rhs.value();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
class Modulo extends Operator {
|
|
69
|
+
constructor() {
|
|
70
|
+
super(2, true);
|
|
71
|
+
}
|
|
72
|
+
public value(): number {
|
|
73
|
+
return this.lhs.value() % this.rhs.value();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
class Power extends Operator {
|
|
78
|
+
constructor() {
|
|
79
|
+
super(3, false);
|
|
80
|
+
}
|
|
81
|
+
public value(): number {
|
|
82
|
+
return Math.pow(this.lhs.value(), this.rhs.value());
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
class Equals extends Operator {
|
|
87
|
+
constructor() {
|
|
88
|
+
super(0, true);
|
|
89
|
+
}
|
|
90
|
+
public value(): number {
|
|
91
|
+
return this.lhs.value() === this.rhs.value() ? 1 : 0;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
class NotEquals extends Operator {
|
|
96
|
+
constructor() {
|
|
97
|
+
super(0, true);
|
|
98
|
+
}
|
|
99
|
+
public value(): number {
|
|
100
|
+
return this.lhs.value() !== this.rhs.value() ? 1 : 0;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
class GreaterThan extends Operator {
|
|
105
|
+
constructor() {
|
|
106
|
+
super(0, true);
|
|
107
|
+
}
|
|
108
|
+
public value(): number {
|
|
109
|
+
return this.lhs.value() > this.rhs.value() ? 1 : 0;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
class LessThan extends Operator {
|
|
114
|
+
constructor() {
|
|
115
|
+
super(0, true);
|
|
116
|
+
}
|
|
117
|
+
public value(): number {
|
|
118
|
+
return this.lhs.value() < this.rhs.value() ? 1 : 0;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
class GreaterThanOrEqual extends Operator {
|
|
123
|
+
constructor() {
|
|
124
|
+
super(0, true);
|
|
125
|
+
}
|
|
126
|
+
public value(): number {
|
|
127
|
+
return this.lhs.value() >= this.rhs.value() ? 1 : 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
class LessThanOrEqual extends Operator {
|
|
132
|
+
constructor() {
|
|
133
|
+
super(0, true);
|
|
134
|
+
}
|
|
135
|
+
public value(): number {
|
|
136
|
+
return this.lhs.value() <= this.rhs.value() ? 1 : 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
class And extends Operator {
|
|
141
|
+
constructor() {
|
|
142
|
+
super(-1, true);
|
|
143
|
+
}
|
|
144
|
+
public value(): number {
|
|
145
|
+
return this.lhs.value() && this.rhs.value() ? 1 : 0;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
class Or extends Operator {
|
|
150
|
+
constructor() {
|
|
151
|
+
super(-1, true);
|
|
152
|
+
}
|
|
153
|
+
public value(): number {
|
|
154
|
+
return this.lhs.value() || this.rhs.value() ? 1 : 0;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
class Not extends Operator {
|
|
159
|
+
constructor() {
|
|
160
|
+
super(0, true);
|
|
161
|
+
}
|
|
162
|
+
public isOperator(): boolean {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
public value(): number {
|
|
166
|
+
return !this.lhs.value() ? 1 : 0;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
class Is extends Operator {
|
|
171
|
+
constructor() {
|
|
172
|
+
super(-1, true);
|
|
173
|
+
}
|
|
174
|
+
public value(): number {
|
|
175
|
+
return this.lhs.value() === this.rhs.value() ? 1 : 0;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export { Operator, Add, Subtract, Multiply, Divide, Modulo, Power, Equals, NotEquals, GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual, And, Or, Not, Is };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import ASTNode from "../ast_node";
|
|
2
|
+
import Identifier from "./identifier";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Represents a reference to a previously defined variable or expression.
|
|
6
|
+
*
|
|
7
|
+
* References point to values defined earlier in the query (e.g., in WITH or LOAD statements).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const ref = new Reference("myVar", previousNode);
|
|
12
|
+
* console.log(ref.value()); // Gets value from referred node
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
class Reference extends Identifier {
|
|
16
|
+
private _referred: ASTNode | undefined = undefined;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new Reference to a variable.
|
|
20
|
+
*
|
|
21
|
+
* @param value - The identifier name
|
|
22
|
+
* @param referred - The node this reference points to (optional)
|
|
23
|
+
*/
|
|
24
|
+
constructor(value: string, referred: ASTNode | undefined = undefined) {
|
|
25
|
+
super(value);
|
|
26
|
+
this._referred = referred;
|
|
27
|
+
}
|
|
28
|
+
public set referred(node: ASTNode) {
|
|
29
|
+
this._referred = node;
|
|
30
|
+
}
|
|
31
|
+
public toString(): string {
|
|
32
|
+
return `Reference (${this._value})`;
|
|
33
|
+
}
|
|
34
|
+
public value(): any {
|
|
35
|
+
return this._referred?.value();
|
|
36
|
+
}
|
|
37
|
+
public get identifier(): string {
|
|
38
|
+
return this._value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default Reference;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import ASTNode from "../ast_node";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a string literal in the AST.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* const str = new String("hello");
|
|
9
|
+
* console.log(str.value()); // "hello"
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
class String extends ASTNode {
|
|
13
|
+
protected _value: string;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new String node with the given value.
|
|
17
|
+
*
|
|
18
|
+
* @param value - The string value
|
|
19
|
+
*/
|
|
20
|
+
constructor(value: string) {
|
|
21
|
+
super();
|
|
22
|
+
this._value = value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public value(): string {
|
|
26
|
+
return this._value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public toString(): string {
|
|
30
|
+
return `String (${this._value})`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default String;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Function from "./function";
|
|
2
|
+
import ReducerElement from "./reducer_element";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base class for aggregate functions that reduce multiple values to a single value.
|
|
6
|
+
*
|
|
7
|
+
* Aggregate functions like SUM, AVG, and COLLECT process multiple input values
|
|
8
|
+
* and produce a single output. They cannot be nested within other aggregate functions.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const sumFunc = new Sum();
|
|
13
|
+
* // Used in: RETURN SUM(values)
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
class AggregateFunction extends Function {
|
|
17
|
+
private _overridden: any | null = null;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new AggregateFunction with the given name.
|
|
21
|
+
*
|
|
22
|
+
* @param name - The function name
|
|
23
|
+
*/
|
|
24
|
+
constructor(name: string) {
|
|
25
|
+
super(name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Processes a value during the aggregation phase.
|
|
30
|
+
*
|
|
31
|
+
* @param value - The element to aggregate
|
|
32
|
+
* @throws {Error} If not implemented by subclass
|
|
33
|
+
*/
|
|
34
|
+
public reduce(value: ReducerElement): void {
|
|
35
|
+
throw new Error("Method not implemented.");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Creates a reducer element for this aggregate function.
|
|
40
|
+
*
|
|
41
|
+
* @returns A ReducerElement instance
|
|
42
|
+
* @throws {Error} If not implemented by subclass
|
|
43
|
+
*/
|
|
44
|
+
public element(): ReducerElement {
|
|
45
|
+
throw new Error("Method not implemented.");
|
|
46
|
+
}
|
|
47
|
+
public get overridden(): any | null {
|
|
48
|
+
return this._overridden;
|
|
49
|
+
}
|
|
50
|
+
public set overridden(value: any | null) {
|
|
51
|
+
this._overridden = value;
|
|
52
|
+
}
|
|
53
|
+
public value(): any {
|
|
54
|
+
return this._overridden;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default AggregateFunction;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import AggregateFunction from "./aggregate_function";
|
|
2
|
+
import ASTNode from "../ast_node";
|
|
3
|
+
import ReducerElement from "./reducer_element";
|
|
4
|
+
|
|
5
|
+
class AvgReducerElement extends ReducerElement {
|
|
6
|
+
private _count: number = 0;
|
|
7
|
+
private _sum: number | null = null;
|
|
8
|
+
public get value(): number | null {
|
|
9
|
+
if(this._sum === null) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return this._sum / this._count;
|
|
13
|
+
}
|
|
14
|
+
public set value(value: number) {
|
|
15
|
+
this._count += 1;
|
|
16
|
+
if(this._sum !== null) {
|
|
17
|
+
this._sum += value;
|
|
18
|
+
} else {
|
|
19
|
+
this._sum = value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
class Avg extends AggregateFunction {
|
|
25
|
+
constructor() {
|
|
26
|
+
super("avg");
|
|
27
|
+
this._expectedParameterCount = 1;
|
|
28
|
+
}
|
|
29
|
+
public reduce(element: AvgReducerElement): void {
|
|
30
|
+
element.value = this.firstChild().value();
|
|
31
|
+
}
|
|
32
|
+
public element(): AvgReducerElement {
|
|
33
|
+
return new AvgReducerElement();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default Avg;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import AggregateFunction from "./aggregate_function";
|
|
2
|
+
import ReducerElement from "./reducer_element";
|
|
3
|
+
|
|
4
|
+
class CollectReducerElement extends ReducerElement {
|
|
5
|
+
private _value: any[] = [];
|
|
6
|
+
public get value(): any {
|
|
7
|
+
return this._value;
|
|
8
|
+
}
|
|
9
|
+
public set value(value: any) {
|
|
10
|
+
this._value.push(value);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class DistinctCollectReducerElement extends ReducerElement {
|
|
15
|
+
private _value: Map<any, any> = new Map();
|
|
16
|
+
public get value(): any {
|
|
17
|
+
return Array.from(this._value.values());
|
|
18
|
+
}
|
|
19
|
+
public set value(value: any) {
|
|
20
|
+
const key: string = JSON.stringify(value);
|
|
21
|
+
if (!this._value.has(key)) {
|
|
22
|
+
this._value.set(key, value);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class Collect extends AggregateFunction {
|
|
28
|
+
private _distinct: boolean = false;
|
|
29
|
+
constructor() {
|
|
30
|
+
super("collect");
|
|
31
|
+
this._expectedParameterCount = 1;
|
|
32
|
+
}
|
|
33
|
+
public reduce(element: CollectReducerElement): void {
|
|
34
|
+
element.value = this.firstChild().value();
|
|
35
|
+
}
|
|
36
|
+
public element(): CollectReducerElement | DistinctCollectReducerElement {
|
|
37
|
+
return this._distinct ? new DistinctCollectReducerElement() : new CollectReducerElement();
|
|
38
|
+
}
|
|
39
|
+
public set distinct(distinct: boolean) {
|
|
40
|
+
this._distinct = distinct;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default Collect;
|