metal-orm 1.0.83 → 1.0.86
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/dist/index.cjs +299 -233
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -13
- package/dist/index.d.ts +28 -13
- package/dist/index.js +297 -233
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ast/ast-validation.ts +11 -180
- package/src/core/ast/expression-nodes.ts +35 -25
- package/src/core/ast/expression-visitor.ts +53 -25
- package/src/core/ast/query-visitor.ts +273 -0
- package/src/core/dialect/abstract.ts +11 -7
- package/src/orm/execute.ts +60 -46
- package/src/query-builder/query-ast-service.ts +13 -0
- package/src/query-builder/select/select-operations.ts +32 -24
- package/src/query-builder/select.ts +49 -35
package/package.json
CHANGED
|
@@ -1,188 +1,19 @@
|
|
|
1
|
-
import type { ExpressionNode, OperandNode } from './expression-nodes.js';
|
|
2
|
-
import { visitExpression, visitOperand } from './expression-visitor.js';
|
|
3
1
|
import type { SelectQueryNode } from './query.js';
|
|
2
|
+
import { visitSelectQuery } from './query-visitor.js';
|
|
4
3
|
|
|
5
|
-
const
|
|
6
|
-
let
|
|
4
|
+
export const findFirstParamOperandName = (ast: SelectQueryNode): string | undefined => {
|
|
5
|
+
let name: string | undefined;
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
otherwise: () => {}
|
|
13
|
-
});
|
|
14
|
-
visitOperand(node.right, {
|
|
15
|
-
visitParam: () => { hasParams = true; },
|
|
16
|
-
otherwise: () => {}
|
|
17
|
-
});
|
|
18
|
-
if (node.escape) {
|
|
19
|
-
visitOperand(node.escape, {
|
|
20
|
-
visitParam: () => { hasParams = true; },
|
|
21
|
-
otherwise: () => {}
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
visitLogicalExpression: (node) => {
|
|
26
|
-
node.operands.forEach(operand => {
|
|
27
|
-
if (hasParamOperandsInExpression(operand)) {
|
|
28
|
-
hasParams = true;
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
},
|
|
32
|
-
visitNullExpression: () => {},
|
|
33
|
-
visitInExpression: (node) => {
|
|
34
|
-
visitOperand(node.left, {
|
|
35
|
-
visitParam: () => { hasParams = true; },
|
|
36
|
-
otherwise: () => {}
|
|
37
|
-
});
|
|
38
|
-
if (Array.isArray(node.right)) {
|
|
39
|
-
node.right.forEach(operand => visitOperand(operand, {
|
|
40
|
-
visitParam: () => { hasParams = true; },
|
|
41
|
-
otherwise: () => {}
|
|
42
|
-
}));
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
visitExistsExpression: () => {},
|
|
46
|
-
visitBetweenExpression: (node) => {
|
|
47
|
-
visitOperand(node.left, {
|
|
48
|
-
visitParam: () => { hasParams = true; },
|
|
49
|
-
otherwise: () => {}
|
|
50
|
-
});
|
|
51
|
-
visitOperand(node.lower, {
|
|
52
|
-
visitParam: () => { hasParams = true; },
|
|
53
|
-
otherwise: () => {}
|
|
54
|
-
});
|
|
55
|
-
visitOperand(node.upper, {
|
|
56
|
-
visitParam: () => { hasParams = true; },
|
|
57
|
-
otherwise: () => {}
|
|
58
|
-
});
|
|
59
|
-
},
|
|
60
|
-
visitArithmeticExpression: (node) => {
|
|
61
|
-
visitOperand(node.left, {
|
|
62
|
-
visitParam: () => { hasParams = true; },
|
|
63
|
-
otherwise: () => {}
|
|
64
|
-
});
|
|
65
|
-
visitOperand(node.right, {
|
|
66
|
-
visitParam: () => { hasParams = true; },
|
|
67
|
-
otherwise: () => {}
|
|
68
|
-
});
|
|
69
|
-
},
|
|
70
|
-
visitBitwiseExpression: (node) => {
|
|
71
|
-
visitOperand(node.left, {
|
|
72
|
-
visitParam: () => { hasParams = true; },
|
|
73
|
-
otherwise: () => {}
|
|
74
|
-
});
|
|
75
|
-
visitOperand(node.right, {
|
|
76
|
-
visitParam: () => { hasParams = true; },
|
|
77
|
-
otherwise: () => {}
|
|
78
|
-
});
|
|
79
|
-
},
|
|
80
|
-
otherwise: () => {}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return hasParams;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const hasParamOperandsInOperand = (operand: OperandNode): boolean => {
|
|
87
|
-
let hasParams = false;
|
|
88
|
-
|
|
89
|
-
visitOperand(operand, {
|
|
90
|
-
visitColumn: () => {},
|
|
91
|
-
visitLiteral: () => {},
|
|
92
|
-
visitParam: () => { hasParams = true; },
|
|
93
|
-
visitFunction: (node) => {
|
|
94
|
-
node.args?.forEach(arg => {
|
|
95
|
-
if (hasParamOperandsInOperand(arg)) {
|
|
96
|
-
hasParams = true;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
},
|
|
100
|
-
visitJsonPath: () => {},
|
|
101
|
-
visitScalarSubquery: () => {},
|
|
102
|
-
visitCaseExpression: (node) => {
|
|
103
|
-
node.conditions.forEach(cond => {
|
|
104
|
-
if (hasParamOperandsInExpression(cond.when)) {
|
|
105
|
-
hasParams = true;
|
|
106
|
-
}
|
|
107
|
-
if (hasParamOperandsInOperand(cond.then)) {
|
|
108
|
-
hasParams = true;
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
if (node.else && hasParamOperandsInOperand(node.else)) {
|
|
112
|
-
hasParams = true;
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
visitCast: (node) => {
|
|
116
|
-
if (hasParamOperandsInOperand(node.expression)) {
|
|
117
|
-
hasParams = true;
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
visitWindowFunction: (node) => {
|
|
121
|
-
node.args?.forEach(arg => {
|
|
122
|
-
if (hasParamOperandsInOperand(arg)) {
|
|
123
|
-
hasParams = true;
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
node.orderBy?.forEach(ord => {
|
|
127
|
-
if (ord.term) {
|
|
128
|
-
if (hasParamOperandsInOperand(ord.term as OperandNode)) {
|
|
129
|
-
hasParams = true;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
},
|
|
134
|
-
visitCollate: (node) => {
|
|
135
|
-
if (hasParamOperandsInOperand(node.expression)) {
|
|
136
|
-
hasParams = true;
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
visitAliasRef: () => {},
|
|
140
|
-
otherwise: () => {}
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
return hasParams;
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
export const hasParamOperandsInQuery = (ast: SelectQueryNode): boolean => {
|
|
147
|
-
if (ast.where && hasParamOperandsInExpression(ast.where)) {
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (ast.having && hasParamOperandsInExpression(ast.having)) {
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
ast.columns?.forEach(col => {
|
|
156
|
-
if (typeof col === 'object' && col !== null && 'type' in col) {
|
|
157
|
-
if (hasParamOperandsInOperand(col as OperandNode)) {
|
|
158
|
-
return true;
|
|
7
|
+
visitSelectQuery(ast, {
|
|
8
|
+
visitParam: (node) => {
|
|
9
|
+
if (!name) {
|
|
10
|
+
name = node.name;
|
|
159
11
|
}
|
|
160
12
|
}
|
|
161
13
|
});
|
|
162
14
|
|
|
163
|
-
|
|
164
|
-
if (ord.term) {
|
|
165
|
-
if (hasParamOperandsInOperand(ord.term as OperandNode)) {
|
|
166
|
-
return true;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
if (ast.ctes) {
|
|
172
|
-
for (const cte of ast.ctes) {
|
|
173
|
-
if (cte.query.where && hasParamOperandsInExpression(cte.query.where)) {
|
|
174
|
-
return true;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (ast.setOps) {
|
|
180
|
-
for (const op of ast.setOps) {
|
|
181
|
-
if (hasParamOperandsInQuery(op.query)) {
|
|
182
|
-
return true;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return false;
|
|
15
|
+
return name;
|
|
188
16
|
};
|
|
17
|
+
|
|
18
|
+
export const hasParamOperandsInQuery = (ast: SelectQueryNode): boolean =>
|
|
19
|
+
!!findFirstParamOperandName(ast);
|
|
@@ -183,31 +183,41 @@ const operandTypes = new Set<OperandNode['type']>([
|
|
|
183
183
|
'ScalarSubquery',
|
|
184
184
|
'CaseExpression',
|
|
185
185
|
'Cast',
|
|
186
|
-
'WindowFunction',
|
|
187
|
-
'ArithmeticExpression',
|
|
188
|
-
'BitwiseExpression',
|
|
189
|
-
'Collate'
|
|
190
|
-
]);
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
typeof value
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
export const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
186
|
+
'WindowFunction',
|
|
187
|
+
'ArithmeticExpression',
|
|
188
|
+
'BitwiseExpression',
|
|
189
|
+
'Collate'
|
|
190
|
+
]);
|
|
191
|
+
|
|
192
|
+
const getNodeType = (value: unknown): string | undefined => {
|
|
193
|
+
if (typeof value !== 'object' || value === null) return undefined;
|
|
194
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, 'type');
|
|
195
|
+
if (descriptor && typeof descriptor.value === 'string') {
|
|
196
|
+
return descriptor.value;
|
|
197
|
+
}
|
|
198
|
+
if ('type' in value) {
|
|
199
|
+
const type = (value as { type?: unknown }).type;
|
|
200
|
+
return typeof type === 'string' ? type : undefined;
|
|
201
|
+
}
|
|
202
|
+
return undefined;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export const isOperandNode = (node: unknown): node is OperandNode => {
|
|
206
|
+
const type = getNodeType(node);
|
|
207
|
+
return type !== undefined && operandTypes.has(type as OperandNode['type']);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export const isFunctionNode = (node: unknown): node is FunctionNode =>
|
|
211
|
+
isOperandNode(node) && getNodeType(node) === 'Function';
|
|
212
|
+
export const isCaseExpressionNode = (node: unknown): node is CaseExpressionNode =>
|
|
213
|
+
isOperandNode(node) && getNodeType(node) === 'CaseExpression';
|
|
214
|
+
|
|
215
|
+
export const isCastExpressionNode = (node: unknown): node is CastExpressionNode =>
|
|
216
|
+
isOperandNode(node) && getNodeType(node) === 'Cast';
|
|
217
|
+
export const isCollateExpressionNode = (node: unknown): node is CollateExpressionNode =>
|
|
218
|
+
isOperandNode(node) && getNodeType(node) === 'Collate';
|
|
219
|
+
export const isWindowFunctionNode = (node: unknown): node is WindowFunctionNode =>
|
|
220
|
+
isOperandNode(node) && getNodeType(node) === 'WindowFunction';
|
|
211
221
|
export const isExpressionSelectionNode = (
|
|
212
222
|
node: ColumnRef | FunctionNode | CaseExpressionNode | CastExpressionNode | WindowFunctionNode
|
|
213
223
|
): node is FunctionNode | CaseExpressionNode | CastExpressionNode | WindowFunctionNode =>
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
BitwiseExpressionNode,
|
|
22
22
|
ParamNode
|
|
23
23
|
} from './expression-nodes.js';
|
|
24
|
+
import type { SelectQueryNode } from './query.js';
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Visitor for expression nodes
|
|
@@ -34,6 +35,8 @@ export interface ExpressionVisitor<R> {
|
|
|
34
35
|
visitBetweenExpression?(node: BetweenExpressionNode): R;
|
|
35
36
|
visitArithmeticExpression?(node: ArithmeticExpressionNode): R;
|
|
36
37
|
visitBitwiseExpression?(node: BitwiseExpressionNode): R;
|
|
38
|
+
visitOperand?(node: OperandNode): R;
|
|
39
|
+
visitSelectQuery?(node: SelectQueryNode): R;
|
|
37
40
|
otherwise?(node: ExpressionNode): R;
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -50,6 +53,10 @@ export interface OperandVisitor<R> {
|
|
|
50
53
|
visitCaseExpression?(node: CaseExpressionNode): R;
|
|
51
54
|
visitCast?(node: CastExpressionNode): R;
|
|
52
55
|
visitWindowFunction?(node: WindowFunctionNode): R;
|
|
56
|
+
visitArithmeticExpression?(node: ArithmeticExpressionNode): R;
|
|
57
|
+
visitBitwiseExpression?(node: BitwiseExpressionNode): R;
|
|
58
|
+
visitExpression?(node: ExpressionNode): R;
|
|
59
|
+
visitSelectQuery?(node: SelectQueryNode): R;
|
|
53
60
|
visitCollate?(node: CollateExpressionNode): R;
|
|
54
61
|
visitAliasRef?(node: AliasRefNode): R;
|
|
55
62
|
otherwise?(node: OperandNode): R;
|
|
@@ -111,6 +118,12 @@ export const registerOperandDispatcher = (type: string, dispatcher: OperandDispa
|
|
|
111
118
|
operandRegistry = operandRegistry.register(type, dispatcher);
|
|
112
119
|
};
|
|
113
120
|
|
|
121
|
+
export const hasExpressionDispatcher = (type: string): boolean =>
|
|
122
|
+
expressionRegistry.get(type) !== undefined;
|
|
123
|
+
|
|
124
|
+
export const hasOperandDispatcher = (type: string): boolean =>
|
|
125
|
+
operandRegistry.get(type) !== undefined;
|
|
126
|
+
|
|
114
127
|
/**
|
|
115
128
|
* Clears all registered dispatchers. Primarily for tests.
|
|
116
129
|
*/
|
|
@@ -122,8 +135,15 @@ export const clearOperandDispatchers = (): void => {
|
|
|
122
135
|
operandRegistry = operandRegistry.clear();
|
|
123
136
|
};
|
|
124
137
|
|
|
125
|
-
const getNodeType = (node: { type?: string } | null | undefined): string | undefined =>
|
|
126
|
-
typeof node
|
|
138
|
+
const getNodeType = (node: { type?: string } | null | undefined): string | undefined => {
|
|
139
|
+
if (typeof node !== 'object' || node === null) return undefined;
|
|
140
|
+
const descriptor = Object.getOwnPropertyDescriptor(node, 'type');
|
|
141
|
+
if (descriptor && typeof descriptor.value === 'string') {
|
|
142
|
+
return descriptor.value;
|
|
143
|
+
}
|
|
144
|
+
const type = node.type;
|
|
145
|
+
return typeof type === 'string' ? type : undefined;
|
|
146
|
+
};
|
|
127
147
|
|
|
128
148
|
const unsupportedExpression = (node: ExpressionNode): never => {
|
|
129
149
|
throw new Error(`Unsupported expression type "${getNodeType(node) ?? 'unknown'}"`);
|
|
@@ -138,33 +158,34 @@ const unsupportedOperand = (node: OperandNode): never => {
|
|
|
138
158
|
* @param visitor - Visitor implementation
|
|
139
159
|
*/
|
|
140
160
|
export const visitExpression = <R>(node: ExpressionNode, visitor: ExpressionVisitor<R>): R => {
|
|
141
|
-
const
|
|
161
|
+
const type = getNodeType(node);
|
|
162
|
+
const dynamic = type ? expressionRegistry.get(type) : undefined;
|
|
142
163
|
if (dynamic) return dynamic(node, visitor);
|
|
143
164
|
|
|
144
|
-
switch (
|
|
165
|
+
switch (type) {
|
|
145
166
|
case 'BinaryExpression':
|
|
146
|
-
if (visitor.visitBinaryExpression) return visitor.visitBinaryExpression(node);
|
|
167
|
+
if (visitor.visitBinaryExpression) return visitor.visitBinaryExpression(node as BinaryExpressionNode);
|
|
147
168
|
break;
|
|
148
169
|
case 'LogicalExpression':
|
|
149
|
-
if (visitor.visitLogicalExpression) return visitor.visitLogicalExpression(node);
|
|
170
|
+
if (visitor.visitLogicalExpression) return visitor.visitLogicalExpression(node as LogicalExpressionNode);
|
|
150
171
|
break;
|
|
151
172
|
case 'NullExpression':
|
|
152
|
-
if (visitor.visitNullExpression) return visitor.visitNullExpression(node);
|
|
173
|
+
if (visitor.visitNullExpression) return visitor.visitNullExpression(node as NullExpressionNode);
|
|
153
174
|
break;
|
|
154
175
|
case 'InExpression':
|
|
155
|
-
if (visitor.visitInExpression) return visitor.visitInExpression(node);
|
|
176
|
+
if (visitor.visitInExpression) return visitor.visitInExpression(node as InExpressionNode);
|
|
156
177
|
break;
|
|
157
178
|
case 'ExistsExpression':
|
|
158
|
-
if (visitor.visitExistsExpression) return visitor.visitExistsExpression(node);
|
|
179
|
+
if (visitor.visitExistsExpression) return visitor.visitExistsExpression(node as ExistsExpressionNode);
|
|
159
180
|
break;
|
|
160
181
|
case 'BetweenExpression':
|
|
161
|
-
if (visitor.visitBetweenExpression) return visitor.visitBetweenExpression(node);
|
|
182
|
+
if (visitor.visitBetweenExpression) return visitor.visitBetweenExpression(node as BetweenExpressionNode);
|
|
162
183
|
break;
|
|
163
184
|
case 'ArithmeticExpression':
|
|
164
|
-
if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node);
|
|
185
|
+
if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node as ArithmeticExpressionNode);
|
|
165
186
|
break;
|
|
166
187
|
case 'BitwiseExpression':
|
|
167
|
-
if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node);
|
|
188
|
+
if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node as BitwiseExpressionNode);
|
|
168
189
|
break;
|
|
169
190
|
default:
|
|
170
191
|
break;
|
|
@@ -179,42 +200,49 @@ export const visitExpression = <R>(node: ExpressionNode, visitor: ExpressionVisi
|
|
|
179
200
|
* @param visitor - Visitor implementation
|
|
180
201
|
*/
|
|
181
202
|
export const visitOperand = <R>(node: OperandNode, visitor: OperandVisitor<R>): R => {
|
|
182
|
-
const
|
|
203
|
+
const type = getNodeType(node);
|
|
204
|
+
const dynamic = type ? operandRegistry.get(type) : undefined;
|
|
183
205
|
if (dynamic) return dynamic(node, visitor);
|
|
184
206
|
|
|
185
|
-
switch (
|
|
207
|
+
switch (type) {
|
|
186
208
|
case 'Column':
|
|
187
|
-
if (visitor.visitColumn) return visitor.visitColumn(node);
|
|
209
|
+
if (visitor.visitColumn) return visitor.visitColumn(node as ColumnNode);
|
|
188
210
|
break;
|
|
189
211
|
case 'Literal':
|
|
190
|
-
if (visitor.visitLiteral) return visitor.visitLiteral(node);
|
|
212
|
+
if (visitor.visitLiteral) return visitor.visitLiteral(node as LiteralNode);
|
|
191
213
|
break;
|
|
192
214
|
case 'Param':
|
|
193
|
-
if (visitor.visitParam) return visitor.visitParam(node);
|
|
215
|
+
if (visitor.visitParam) return visitor.visitParam(node as ParamNode);
|
|
194
216
|
break;
|
|
195
217
|
case 'Function':
|
|
196
|
-
if (visitor.visitFunction) return visitor.visitFunction(node);
|
|
218
|
+
if (visitor.visitFunction) return visitor.visitFunction(node as FunctionNode);
|
|
197
219
|
break;
|
|
198
220
|
case 'JsonPath':
|
|
199
|
-
if (visitor.visitJsonPath) return visitor.visitJsonPath(node);
|
|
221
|
+
if (visitor.visitJsonPath) return visitor.visitJsonPath(node as JsonPathNode);
|
|
200
222
|
break;
|
|
201
223
|
case 'ScalarSubquery':
|
|
202
|
-
if (visitor.visitScalarSubquery) return visitor.visitScalarSubquery(node);
|
|
224
|
+
if (visitor.visitScalarSubquery) return visitor.visitScalarSubquery(node as ScalarSubqueryNode);
|
|
203
225
|
break;
|
|
204
226
|
case 'CaseExpression':
|
|
205
|
-
if (visitor.visitCaseExpression) return visitor.visitCaseExpression(node);
|
|
227
|
+
if (visitor.visitCaseExpression) return visitor.visitCaseExpression(node as CaseExpressionNode);
|
|
206
228
|
break;
|
|
207
229
|
case 'WindowFunction':
|
|
208
|
-
if (visitor.visitWindowFunction) return visitor.visitWindowFunction(node);
|
|
230
|
+
if (visitor.visitWindowFunction) return visitor.visitWindowFunction(node as WindowFunctionNode);
|
|
209
231
|
break;
|
|
210
232
|
case 'AliasRef':
|
|
211
|
-
if (visitor.visitAliasRef) return visitor.visitAliasRef(node);
|
|
233
|
+
if (visitor.visitAliasRef) return visitor.visitAliasRef(node as AliasRefNode);
|
|
212
234
|
break;
|
|
213
235
|
case 'Cast':
|
|
214
|
-
if (visitor.visitCast) return visitor.visitCast(node);
|
|
236
|
+
if (visitor.visitCast) return visitor.visitCast(node as CastExpressionNode);
|
|
215
237
|
break;
|
|
216
238
|
case 'Collate':
|
|
217
|
-
if (visitor.visitCollate) return visitor.visitCollate(node);
|
|
239
|
+
if (visitor.visitCollate) return visitor.visitCollate(node as CollateExpressionNode);
|
|
240
|
+
break;
|
|
241
|
+
case 'ArithmeticExpression':
|
|
242
|
+
if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node as ArithmeticExpressionNode);
|
|
243
|
+
break;
|
|
244
|
+
case 'BitwiseExpression':
|
|
245
|
+
if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node as BitwiseExpressionNode);
|
|
218
246
|
break;
|
|
219
247
|
default:
|
|
220
248
|
break;
|