@finos/legend-query-builder 4.12.0 → 4.13.1

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.
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
  }