@finos/legend-query-builder 4.12.0 → 4.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
  2. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +28 -2
  3. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  4. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  5. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +1 -1
  6. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  7. package/lib/graph/QueryBuilderMetaModelConst.d.ts +2 -1
  8. package/lib/graph/QueryBuilderMetaModelConst.d.ts.map +1 -1
  9. package/lib/graph/QueryBuilderMetaModelConst.js +2 -0
  10. package/lib/graph/QueryBuilderMetaModelConst.js.map +1 -1
  11. package/lib/index.css +17 -1
  12. package/lib/index.css.map +1 -1
  13. package/lib/package.json +1 -1
  14. package/lib/stores/QueryBuilderStateBuilder.d.ts.map +1 -1
  15. package/lib/stores/QueryBuilderStateBuilder.js +5 -1
  16. package/lib/stores/QueryBuilderStateBuilder.js.map +1 -1
  17. package/lib/stores/fetch-structure/tds/QueryResultSetModifierState.d.ts +2 -0
  18. package/lib/stores/fetch-structure/tds/QueryResultSetModifierState.d.ts.map +1 -1
  19. package/lib/stores/fetch-structure/tds/QueryResultSetModifierState.js +6 -0
  20. package/lib/stores/fetch-structure/tds/QueryResultSetModifierState.js.map +1 -1
  21. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.d.ts +1 -0
  22. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.d.ts.map +1 -1
  23. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.js +26 -2
  24. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.js.map +1 -1
  25. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
  26. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +16 -0
  27. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
  28. package/package.json +4 -4
  29. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +84 -0
  30. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +13 -0
  31. package/src/graph/QueryBuilderMetaModelConst.ts +3 -0
  32. package/src/stores/QueryBuilderStateBuilder.ts +10 -0
  33. package/src/stores/fetch-structure/tds/QueryResultSetModifierState.ts +7 -0
  34. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionStateBuilder.ts +64 -0
  35. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +27 -0
@@ -202,6 +202,40 @@ export const QueryResultModifierModal = observer(
202
202
  );
203
203
  };
204
204
 
205
+ const handleSliceStartChange = (start: number, end: number): void => {
206
+ const slice: [number, number] = [start, end];
207
+ resultSetModifierState.setSlice(slice);
208
+ };
209
+
210
+ const clearSlice = (): void => {
211
+ resultSetModifierState.setSlice(undefined);
212
+ };
213
+
214
+ const addSlice = (): void => {
215
+ resultSetModifierState.setSlice([0, 1]);
216
+ };
217
+
218
+ const changeSliceStart: React.ChangeEventHandler<HTMLInputElement> = (
219
+ event,
220
+ ) => {
221
+ const currentSlice = resultSetModifierState.slice;
222
+ const val = event.target.value;
223
+ const start = typeof val === 'number' ? val : parseInt(val, 10);
224
+ if (currentSlice) {
225
+ handleSliceStartChange(start, currentSlice[1]);
226
+ }
227
+ };
228
+ const changeSliceEnd: React.ChangeEventHandler<HTMLInputElement> = (
229
+ event,
230
+ ) => {
231
+ const currentSlice = resultSetModifierState.slice;
232
+ const val = event.target.value;
233
+ const end = typeof val === 'number' ? val : parseInt(val, 10);
234
+ if (currentSlice) {
235
+ handleSliceStartChange(currentSlice[0], end);
236
+ }
237
+ };
238
+
205
239
  return (
206
240
  <Dialog
207
241
  open={Boolean(resultSetModifierState.showModal)}
@@ -258,6 +292,56 @@ export const QueryResultModifierModal = observer(
258
292
  onChange={changeValue}
259
293
  />
260
294
  </div>
295
+ <div className="panel__content__form__section">
296
+ <div className="panel__content__form__section__header__label">
297
+ Slice
298
+ </div>
299
+ <div className="panel__content__form__section__header__prompt">
300
+ Reduce the number of rows in the provided TDS, selecting the
301
+ set of rows in the specified range between start and stop
302
+ </div>
303
+ {resultSetModifierState.slice ? (
304
+ <>
305
+ <div className="query-builder__result__slice">
306
+ <input
307
+ className="input--dark query-builder__result__slice__input"
308
+ spellCheck={false}
309
+ value={resultSetModifierState.slice[0]}
310
+ onChange={changeSliceStart}
311
+ type="number"
312
+ />
313
+ <div className="query-builder__result__slice__range">
314
+ ..
315
+ </div>
316
+ <input
317
+ className="input--dark query-builder__result__slice__input"
318
+ spellCheck={false}
319
+ value={resultSetModifierState.slice[1]}
320
+ onChange={changeSliceEnd}
321
+ type="number"
322
+ />
323
+ <button
324
+ className="query-builder__projection__options__sort__remove-btn btn--dark btn--caution"
325
+ onClick={clearSlice}
326
+ tabIndex={-1}
327
+ title="Remove"
328
+ >
329
+ <TimesIcon />
330
+ </button>
331
+ </div>
332
+ </>
333
+ ) : (
334
+ <div className="panel__content__form__section__list__new-item__add">
335
+ <button
336
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
337
+ onClick={addSlice}
338
+ tabIndex={-1}
339
+ >
340
+ Add Slice
341
+ </button>
342
+ </div>
343
+ )}
344
+ </div>
261
345
  </div>
262
346
  </ModalBody>
263
347
  <ModalFooter>
@@ -1142,6 +1142,19 @@ export const QueryBuilderTDSPanel = observer(
1142
1142
  )}
1143
1143
  </div>
1144
1144
  )}
1145
+ {tdsState.resultSetModifierState.slice && (
1146
+ <div className="query-builder__projection__result-modifier-prompt__group">
1147
+ <div className="query-builder__projection__result-modifier-prompt__group__label">
1148
+ Slice
1149
+ </div>
1150
+ <div
1151
+ className="query-builder__projection__result-modifier-prompt__group__content"
1152
+ onClick={openResultSetModifierEditor}
1153
+ >
1154
+ {`${tdsState.resultSetModifierState.slice[0]},${tdsState.resultSetModifierState.slice[1]}`}
1155
+ </div>
1156
+ </div>
1157
+ )}
1145
1158
  </div>
1146
1159
  <div className="query-builder__projection__toolbar__actions">
1147
1160
  <button
@@ -158,6 +158,9 @@ export enum QUERY_BUILDER_SUPPORTED_FUNCTIONS {
158
158
  // TOTDS
159
159
  TABLE_TO_TDS = 'meta::pure::tds::tableToTDS',
160
160
  TABLE_REFERENCE = 'meta::relational::functions::database::tableReference',
161
+
162
+ // SLICE
163
+ SLICE = 'meta::pure::functions::collection::slice',
161
164
  }
162
165
 
163
166
  export enum TDS_COLUMN_GETTER {
@@ -71,6 +71,7 @@ import {
71
71
  processTDSProjectExpression,
72
72
  processTDSProjectionColumnPropertyExpression,
73
73
  processTDSProjectionDerivationExpression,
74
+ processTDSSliceExpression,
74
75
  processTDSSortDirectionExpression,
75
76
  processTDSSortExpression,
76
77
  processTDSTakeExpression,
@@ -641,6 +642,15 @@ export class QueryBuilderValueSpecificationProcessor
641
642
  this.parentLambda,
642
643
  );
643
644
  return;
645
+ } else if (
646
+ matchFunctionName(functionName, QUERY_BUILDER_SUPPORTED_FUNCTIONS.SLICE)
647
+ ) {
648
+ processTDSSliceExpression(
649
+ valueSpecification,
650
+ this.queryBuilderState,
651
+ this.parentLambda,
652
+ );
653
+ return;
644
654
  } else if (
645
655
  matchFunctionName(functionName, [
646
656
  QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_ASC,
@@ -65,6 +65,7 @@ export class QueryResultSetModifierState implements Hashable {
65
65
  limit?: number | undefined;
66
66
  distinct = false;
67
67
  sortColumns: SortColumnState[] = [];
68
+ slice: [number, number] | undefined;
68
69
 
69
70
  constructor(tdsState: QueryBuilderTDSState) {
70
71
  makeObservable(this, {
@@ -72,12 +73,14 @@ export class QueryResultSetModifierState implements Hashable {
72
73
  limit: observable,
73
74
  distinct: observable,
74
75
  sortColumns: observable,
76
+ slice: observable.ref,
75
77
  setShowModal: action,
76
78
  setLimit: action,
77
79
  toggleDistinct: action,
78
80
  deleteSortColumn: action,
79
81
  addSortColumn: action,
80
82
  updateSortColumns: action,
83
+ setSlice: action,
81
84
  reset: action,
82
85
  hashCode: computed,
83
86
  });
@@ -111,6 +114,10 @@ export class QueryResultSetModifierState implements Hashable {
111
114
  );
112
115
  }
113
116
 
117
+ setSlice(slice: [number, number] | undefined): void {
118
+ this.slice = slice;
119
+ }
120
+
114
121
  reset(): void {
115
122
  this.sortColumns = [];
116
123
  this.distinct = false;
@@ -27,11 +27,13 @@ import {
27
27
  V1_deserializeRawValueSpecification,
28
28
  V1_RawLambda,
29
29
  VariableExpression,
30
+ PrimitiveInstanceValue,
30
31
  } from '@finos/legend-graph';
31
32
  import {
32
33
  assertNonNullable,
33
34
  assertTrue,
34
35
  assertType,
36
+ guaranteeIsNumber,
35
37
  guaranteeNonNullable,
36
38
  guaranteeType,
37
39
  isNonNullable,
@@ -385,6 +387,68 @@ export const processTDSSortExpression = (
385
387
  );
386
388
  };
387
389
 
390
+ export const processTDSSliceExpression = (
391
+ exp: SimpleFunctionExpression,
392
+ queryBuilderState: QueryBuilderState,
393
+ parentLambda: LambdaFunction,
394
+ ): void => {
395
+ // check parameters
396
+ assertTrue(
397
+ exp.parametersValues.length === 3,
398
+ `Can't process slice() expression: slice() expects 2 argument`,
399
+ );
400
+
401
+ // check preceding expression
402
+ const precedingExpression = guaranteeType(
403
+ exp.parametersValues[0],
404
+ SimpleFunctionExpression,
405
+ `Can't process slice() expression: only support slice() immediately following an expression`,
406
+ );
407
+ assertTrue(
408
+ matchFunctionName(precedingExpression.functionName, [
409
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_TAKE,
410
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_DISTINCT,
411
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_SORT,
412
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_PROJECT,
413
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_GROUP_BY,
414
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_FILTER,
415
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.OLAP_GROUPBY,
416
+ ]),
417
+ `Can't process slice() expression: only support slice() in TDS expression`,
418
+ );
419
+ QueryBuilderValueSpecificationProcessor.process(
420
+ precedingExpression,
421
+ parentLambda,
422
+ queryBuilderState,
423
+ );
424
+
425
+ // build state
426
+ if (
427
+ queryBuilderState.fetchStructureState.implementation instanceof
428
+ QueryBuilderTDSState
429
+ ) {
430
+ const tdsState = queryBuilderState.fetchStructureState.implementation;
431
+ const start = guaranteeIsNumber(
432
+ guaranteeType(
433
+ exp.parametersValues[1],
434
+ PrimitiveInstanceValue,
435
+ 'Can`t process slice() function: first param should be a primitive instance value',
436
+ ).values[0],
437
+ 'Can`t process slice() function: first param should be a number primitive instance value',
438
+ );
439
+
440
+ const end = guaranteeIsNumber(
441
+ guaranteeType(
442
+ exp.parametersValues[2],
443
+ PrimitiveInstanceValue,
444
+ 'Can`t process slice() function: first param should be a primitive instance value',
445
+ ).values[0],
446
+ 'Can`t process slice() function: first param should be a number primitive instance value',
447
+ );
448
+ tdsState.resultSetModifierState.setSlice([start, end]);
449
+ }
450
+ };
451
+
388
452
  export const processTDSSortDirectionExpression = (
389
453
  expression: SimpleFunctionExpression,
390
454
  parentExpression: SimpleFunctionExpression | undefined,
@@ -136,6 +136,33 @@ const appendResultSetModifier = (
136
136
  takeFunction.parametersValues[1] = limit;
137
137
  currentExpression = takeFunction;
138
138
  }
139
+ // build slice()
140
+ if (resultModifierState.slice) {
141
+ const sliceStart = resultModifierState.slice[0];
142
+ const sliceEnd = resultModifierState.slice[1];
143
+ const startVal = new PrimitiveInstanceValue(
144
+ GenericTypeExplicitReference.create(
145
+ new GenericType(PrimitiveType.INTEGER),
146
+ ),
147
+ );
148
+ const endVal = new PrimitiveInstanceValue(
149
+ GenericTypeExplicitReference.create(
150
+ new GenericType(PrimitiveType.INTEGER),
151
+ ),
152
+ );
153
+ startVal.values = [sliceStart];
154
+ endVal.values = [sliceEnd];
155
+ const sliceFunction = new SimpleFunctionExpression(
156
+ extractElementNameFromPath(QUERY_BUILDER_SUPPORTED_FUNCTIONS.SLICE),
157
+ );
158
+ sliceFunction.parametersValues = [
159
+ currentExpression,
160
+ startVal,
161
+ endVal,
162
+ ];
163
+ currentExpression = sliceFunction;
164
+ }
165
+
139
166
  lambdaFunction.expressionSequence[0] = currentExpression;
140
167
  return lambdaFunction;
141
168
  }