@finos/legend-application-data-cube 0.2.7 → 0.3.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.
Files changed (65) hide show
  1. package/lib/components/builder/LegendDataCubeBuilder.d.ts.map +1 -1
  2. package/lib/components/builder/LegendDataCubeBuilder.js +4 -1
  3. package/lib/components/builder/LegendDataCubeBuilder.js.map +1 -1
  4. package/lib/components/builder/LegendDataCubeCreator.d.ts.map +1 -1
  5. package/lib/components/builder/LegendDataCubeCreator.js +12 -5
  6. package/lib/components/builder/LegendDataCubeCreator.js.map +1 -1
  7. package/lib/components/builder/LegendDataCubeLoader.js +6 -6
  8. package/lib/components/builder/LegendDataCubeLoader.js.map +1 -1
  9. package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.d.ts.map +1 -1
  10. package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.js +2 -3
  11. package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.js.map +1 -1
  12. package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder.js +6 -6
  13. package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder.js.map +1 -1
  14. package/lib/components/builder/source/LocalFileDataCubeSourceBuilder.d.ts +22 -0
  15. package/lib/components/builder/source/LocalFileDataCubeSourceBuilder.d.ts.map +1 -0
  16. package/lib/components/builder/source/LocalFileDataCubeSourceBuilder.js +29 -0
  17. package/lib/components/builder/source/LocalFileDataCubeSourceBuilder.js.map +1 -0
  18. package/lib/index.css +1 -1
  19. package/lib/package.json +3 -3
  20. package/lib/stores/LegendDataCubeDataCubeEngine.d.ts +5 -3
  21. package/lib/stores/LegendDataCubeDataCubeEngine.d.ts.map +1 -1
  22. package/lib/stores/LegendDataCubeDataCubeEngine.js +297 -120
  23. package/lib/stores/LegendDataCubeDataCubeEngine.js.map +1 -1
  24. package/lib/stores/{LegendDataCubeCacheManager.d.ts → LegendDataCubeDuckDBEngine.d.ts} +18 -6
  25. package/lib/stores/LegendDataCubeDuckDBEngine.d.ts.map +1 -0
  26. package/lib/stores/{LegendDataCubeCacheManager.js → LegendDataCubeDuckDBEngine.js} +81 -39
  27. package/lib/stores/LegendDataCubeDuckDBEngine.js.map +1 -0
  28. package/lib/stores/builder/LegendDataCubeBuilderStore.js +2 -2
  29. package/lib/stores/builder/LegendDataCubeBuilderStore.js.map +1 -1
  30. package/lib/stores/builder/LegendDataCubeCreatorState.d.ts.map +1 -1
  31. package/lib/stores/builder/LegendDataCubeCreatorState.js +3 -0
  32. package/lib/stores/builder/LegendDataCubeCreatorState.js.map +1 -1
  33. package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.d.ts +5 -1
  34. package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.d.ts.map +1 -1
  35. package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.js +4 -1
  36. package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.js.map +1 -1
  37. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.d.ts.map +1 -1
  38. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.js +1 -1
  39. package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.js.map +1 -1
  40. package/lib/stores/builder/source/LocalFileDataCubeSourceBuilderState.d.ts +38 -0
  41. package/lib/stores/builder/source/LocalFileDataCubeSourceBuilderState.d.ts.map +1 -0
  42. package/lib/stores/builder/source/LocalFileDataCubeSourceBuilderState.js +122 -0
  43. package/lib/stores/builder/source/LocalFileDataCubeSourceBuilderState.js.map +1 -0
  44. package/lib/stores/model/LocalFileDataCubeSource.d.ts +44 -0
  45. package/lib/stores/model/LocalFileDataCubeSource.d.ts.map +1 -0
  46. package/lib/stores/model/LocalFileDataCubeSource.js +57 -0
  47. package/lib/stores/model/LocalFileDataCubeSource.js.map +1 -0
  48. package/package.json +13 -13
  49. package/src/components/builder/LegendDataCubeBuilder.tsx +6 -1
  50. package/src/components/builder/LegendDataCubeCreator.tsx +23 -6
  51. package/src/components/builder/LegendDataCubeLoader.tsx +7 -7
  52. package/src/components/builder/source/AdhocQueryDataCubeSourceBuilder.tsx +2 -3
  53. package/src/components/builder/source/LegendQueryDataCubeSourceBuilder.tsx +8 -8
  54. package/src/components/builder/source/LocalFileDataCubeSourceBuilder.tsx +59 -0
  55. package/src/stores/LegendDataCubeDataCubeEngine.ts +407 -182
  56. package/src/stores/{LegendDataCubeCacheManager.ts → LegendDataCubeDuckDBEngine.ts} +86 -42
  57. package/src/stores/builder/LegendDataCubeBuilderStore.tsx +2 -2
  58. package/src/stores/builder/LegendDataCubeCreatorState.tsx +6 -0
  59. package/src/stores/builder/source/LegendDataCubeSourceBuilderState.ts +4 -1
  60. package/src/stores/builder/source/LegendQueryDataCubeSourceBuilderState.ts +3 -1
  61. package/src/stores/builder/source/LocalFileDataCubeSourceBuilderState.ts +179 -0
  62. package/src/stores/model/LocalFileDataCubeSource.ts +67 -0
  63. package/tsconfig.json +4 -1
  64. package/lib/stores/LegendDataCubeCacheManager.d.ts.map +0 -1
  65. package/lib/stores/LegendDataCubeCacheManager.js.map +0 -1
@@ -27,17 +27,27 @@ import {
27
27
  } from '@finos/legend-graph';
28
28
  import {
29
29
  assertNonNullable,
30
+ csvStringify,
30
31
  guaranteeNonNullable,
31
32
  UnsupportedOperationError,
32
33
  } from '@finos/legend-shared';
33
34
  import type { CachedDataCubeSource } from '@finos/legend-data-cube';
34
35
  import { Type } from 'apache-arrow';
35
36
 
36
- export class LegendDataCubeDataCubeCacheManager {
37
+ export class LegendDataCubeDuckDBEngine {
37
38
  private static readonly DUCKDB_DEFAULT_SCHEMA_NAME = 'main'; // See https://duckdb.org/docs/sql/statements/use.html
38
- private static readonly TABLE_NAME_PREFIX = 'cache';
39
- private static readonly CSV_FILE_NAME = 'data';
40
- private static tableCounter = 0;
39
+ private static readonly CACHE_TABLE_NAME_PREFIX = 'cache';
40
+ private static readonly INGEST_TABLE_NAME_PREFIX = 'ingest';
41
+ private static readonly CACHE_FILE_NAME = 'cacheData';
42
+ private static readonly INGEST_FILE_DATA_FILE_NAME = 'ingestData';
43
+ private static cacheTableCounter = 0;
44
+ private static ingestFileTableCounter = 0;
45
+ // https://duckdb.org/docs/guides/meta/describe.html
46
+ private static readonly COLUMN_NAME = 'column_name';
47
+ private static readonly COLUMN_TYPE = 'column_type';
48
+ // Options for creating csv using papa parser: https://www.papaparse.com/docs#config
49
+ private static readonly ESCAPE_CHAR = `'`;
50
+ private static readonly QUOTE_CHAR = `'`;
41
51
 
42
52
  private _database?: duckdb.AsyncDuckDB | undefined;
43
53
 
@@ -84,50 +94,79 @@ export class LegendDataCubeDataCubeCacheManager {
84
94
  }
85
95
 
86
96
  async cache(result: TDSExecutionResult) {
87
- const schema =
88
- LegendDataCubeDataCubeCacheManager.DUCKDB_DEFAULT_SCHEMA_NAME;
89
- LegendDataCubeDataCubeCacheManager.tableCounter += 1;
90
- const table = `${LegendDataCubeDataCubeCacheManager.TABLE_NAME_PREFIX}${LegendDataCubeDataCubeCacheManager.tableCounter}`;
91
- const csvFileName = `${LegendDataCubeDataCubeCacheManager.CSV_FILE_NAME}${LegendDataCubeDataCubeCacheManager.tableCounter}.csv`;
97
+ const schema = LegendDataCubeDuckDBEngine.DUCKDB_DEFAULT_SCHEMA_NAME;
98
+ LegendDataCubeDuckDBEngine.cacheTableCounter += 1;
99
+ const table = `${LegendDataCubeDuckDBEngine.CACHE_TABLE_NAME_PREFIX}${LegendDataCubeDuckDBEngine.cacheTableCounter}`;
100
+ const csvFileName = `${LegendDataCubeDuckDBEngine.CACHE_FILE_NAME}${LegendDataCubeDuckDBEngine.cacheTableCounter}.csv`;
92
101
 
93
- const connection = await this.database.connect();
94
-
95
- const columnString = result.builder.columns
96
- .map((col) => col.name)
97
- .join(',');
102
+ const columnNames: string[] = [];
103
+ result.builder.columns.forEach((col) => columnNames.push(col.name));
98
104
 
99
- const dataString: string[] = [columnString];
105
+ const data = result.result.rows.map((row) => row.values);
100
106
 
101
- result.result.rows.forEach((row) => {
102
- const updatedRows = row.values.map((val) => {
103
- if (val !== null && typeof val === 'string') {
104
- return `'${val.replaceAll(`'`, `''`)}'`;
105
- } else if (val === null) {
106
- return `NULL`;
107
- }
108
- return val;
109
- });
110
- dataString.push(`${updatedRows.join(',')}`);
107
+ const csvContent = csvStringify([columnNames, ...data], {
108
+ escapeChar: LegendDataCubeDuckDBEngine.ESCAPE_CHAR,
109
+ quoteChar: LegendDataCubeDuckDBEngine.QUOTE_CHAR,
111
110
  });
111
+ await this.database.registerFileText(csvFileName, csvContent);
112
112
 
113
- const csvString = dataString.join('\n');
114
-
115
- await this._database?.registerFileText(csvFileName, csvString);
116
-
113
+ const connection = await this.database.connect();
117
114
  await connection.insertCSVFromPath(csvFileName, {
118
115
  schema: schema,
119
116
  name: table,
120
- create: false,
117
+ create: true,
121
118
  header: true,
122
119
  detect: true,
123
- escape: `'`,
124
- quote: `'`,
125
- delimiter: ',',
120
+ dateFormat: 'YYYY-MM-DD',
121
+ timestampFormat: 'YYYY-MM-DD', // make sure Date is not auto-converted to timestamp
122
+ escape: LegendDataCubeDuckDBEngine.ESCAPE_CHAR,
123
+ quote: LegendDataCubeDuckDBEngine.QUOTE_CHAR,
126
124
  });
125
+ await connection.close();
126
+
127
+ return { schema, table, rowCount: result.result.rows.length };
128
+ }
127
129
 
130
+ async ingestLocalFileData(data: string, format: string) {
131
+ const schema = LegendDataCubeDuckDBEngine.DUCKDB_DEFAULT_SCHEMA_NAME;
132
+ LegendDataCubeDuckDBEngine.ingestFileTableCounter += 1;
133
+ const table = `${LegendDataCubeDuckDBEngine.INGEST_TABLE_NAME_PREFIX}${LegendDataCubeDuckDBEngine.ingestFileTableCounter}`;
134
+ const fileName = `${LegendDataCubeDuckDBEngine.INGEST_FILE_DATA_FILE_NAME}${LegendDataCubeDuckDBEngine.ingestFileTableCounter}`;
135
+
136
+ await this._database?.registerFileText(fileName, data);
137
+
138
+ const connection = await this.database.connect();
139
+
140
+ switch (format.toLowerCase()) {
141
+ case 'csv': {
142
+ await connection.insertCSVFromPath(fileName, {
143
+ schema: schema,
144
+ name: table,
145
+ header: true,
146
+ detect: true,
147
+ dateFormat: 'YYYY-MM-DD',
148
+ timestampFormat: 'YYYY-MM-DD', // make sure Date is not auto-converted to timestamp
149
+ escape: LegendDataCubeDuckDBEngine.ESCAPE_CHAR,
150
+ quote: LegendDataCubeDuckDBEngine.QUOTE_CHAR,
151
+ });
152
+ break;
153
+ }
154
+ default: {
155
+ throw new UnsupportedOperationError(
156
+ `Can't ingest local file data: unsupported format '${format}'`,
157
+ );
158
+ }
159
+ }
160
+
161
+ const tableSpec = (await connection.query(`DESCRIBE ${schema}.${table}`))
162
+ .toArray()
163
+ .map((spec) => [
164
+ spec[LegendDataCubeDuckDBEngine.COLUMN_NAME],
165
+ spec[LegendDataCubeDuckDBEngine.COLUMN_TYPE],
166
+ ]);
128
167
  await connection.close();
129
168
 
130
- return { table, schema, rowCount: result.result.rows.length };
169
+ return { schema, table, tableSpec };
131
170
  }
132
171
 
133
172
  async runSQLQuery(sql: string) {
@@ -139,14 +178,18 @@ export class LegendDataCubeDataCubeCacheManager {
139
178
  const columnNames = result.schema.fields.map((field) => field.name);
140
179
  const rows = data.map((row) => {
141
180
  const tdsRow = new TDSRow();
142
- tdsRow.values = columnNames.map(
143
- (column) =>
144
- // NOTE: DuckDB WASM returns ArrayBuffer for numeric value, such as for count(*)
145
- // so we need to convert it to number
146
- (ArrayBuffer.isView(row[column])
147
- ? row[column].valueOf()
148
- : row[column]) as string | number | boolean | null,
149
- );
181
+ tdsRow.values = columnNames.map((column) => {
182
+ const value = row[column] as unknown;
183
+ // NOTE: DuckDB WASM returns ArrayBuffer for numeric value, such as for count(*)
184
+ // so we need to convert it to number
185
+ if (ArrayBuffer.isView(value)) {
186
+ return row[column].valueOf() as number;
187
+ // BigInt is not supported by ag-grid, so we need to convert it to native number
188
+ } else if (typeof value === 'bigint') {
189
+ return Number(value);
190
+ }
191
+ return value as string | number | boolean | null;
192
+ });
150
193
  return tdsRow;
151
194
  });
152
195
  const tdsExecutionResult = new TDSExecutionResult();
@@ -167,6 +210,7 @@ export class LegendDataCubeDataCubeCacheManager {
167
210
  col.type = PRIMITIVE_TYPE.BOOLEAN;
168
211
  break;
169
212
  }
213
+ case Type.Timestamp:
170
214
  case Type.Date:
171
215
  case Type.DateDay:
172
216
  case Type.DateMillisecond: {
@@ -231,7 +231,7 @@ export class LegendDataCubeBuilderStore {
231
231
 
232
232
  this.initializeState.inProgress();
233
233
  try {
234
- await this.engine.initializeCacheManager();
234
+ await this.engine.initialize();
235
235
  this.initializeState.pass();
236
236
  } catch (error) {
237
237
  assertErrorThrown(error);
@@ -244,7 +244,7 @@ export class LegendDataCubeBuilderStore {
244
244
 
245
245
  async cleanUp() {
246
246
  try {
247
- await this.engine.disposeCacheManager();
247
+ await this.engine.dispose();
248
248
  } catch (error) {
249
249
  assertErrorThrown(error);
250
250
  this.alertService.alertError(error, {
@@ -41,6 +41,7 @@ import {
41
41
  type LegendDataCubeBuilderStore,
42
42
  } from './LegendDataCubeBuilderStore.js';
43
43
  import { generateBuilderRoute } from '../../__lib__/LegendDataCubeNavigation.js';
44
+ import { LocalFileDataCubeSourceBuilderState } from './source/LocalFileDataCubeSourceBuilderState.js';
44
45
 
45
46
  const DEFAULT_SOURCE_TYPE = LegendDataCubeSourceBuilderType.LEGEND_QUERY;
46
47
 
@@ -105,6 +106,11 @@ export class LegendDataCubeCreatorState {
105
106
  this._application,
106
107
  this._engine,
107
108
  );
109
+ case LegendDataCubeSourceBuilderType.LOCAL_FILE:
110
+ return new LocalFileDataCubeSourceBuilderState(
111
+ this._application,
112
+ this._engine,
113
+ );
108
114
  default:
109
115
  throw new UnsupportedOperationError(
110
116
  `Can't create source builder for unsupported type '${type}'`,
@@ -22,6 +22,7 @@ import type { DataCubeConfiguration } from '@finos/legend-data-cube';
22
22
  export enum LegendDataCubeSourceBuilderType {
23
23
  LEGEND_QUERY = 'Legend Query',
24
24
  ADHOC_QUERY = 'Ad hoc Query',
25
+ LOCAL_FILE = 'Local File',
25
26
  }
26
27
 
27
28
  export abstract class LegendDataCubeSourceBuilderState {
@@ -40,7 +41,9 @@ export abstract class LegendDataCubeSourceBuilderState {
40
41
  abstract get isValid(): boolean;
41
42
  abstract generateSourceData(): Promise<PlainObject>;
42
43
 
43
- /* Modifies the configuration of the finalized DataCube based on the source builder */
44
+ /**
45
+ * Modifies the configuration of the finalized DataCube based on the source builder.
46
+ */
44
47
  finalizeConfiguration(configuration: DataCubeConfiguration) {
45
48
  // do nothing
46
49
  }
@@ -137,7 +137,9 @@ export class LegendQueryDataCubeSourceBuilderState extends LegendDataCubeSourceB
137
137
 
138
138
  override async generateSourceData() {
139
139
  if (!this.query) {
140
- throw new IllegalStateError('Query is missing');
140
+ throw new IllegalStateError(
141
+ `Can't generate source data: query is not set`,
142
+ );
141
143
  }
142
144
  const source = new RawLegendQueryDataCubeSource();
143
145
  source.queryId = this.query.id;
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import {
18
+ ActionState,
19
+ csvStringify,
20
+ guaranteeType,
21
+ IllegalStateError,
22
+ parseCSVFile,
23
+ type PlainObject,
24
+ } from '@finos/legend-shared';
25
+ import {
26
+ LegendDataCubeSourceBuilderState,
27
+ LegendDataCubeSourceBuilderType,
28
+ } from './LegendDataCubeSourceBuilderState.js';
29
+ import type { LegendDataCubeApplicationStore } from '../../LegendDataCubeBaseStore.js';
30
+ import { action, makeObservable, observable } from 'mobx';
31
+ import type { LegendDataCubeDataCubeEngine } from '../../LegendDataCubeDataCubeEngine.js';
32
+ import {
33
+ LocalFileDataCubeSource,
34
+ LocalFileDataCubeSourceFormat,
35
+ RawLocalFileQueryDataCubeSource,
36
+ } from '../../model/LocalFileDataCubeSource.js';
37
+
38
+ export class LocalFileDataCubeSourceBuilderState extends LegendDataCubeSourceBuilderState {
39
+ readonly processState = ActionState.create();
40
+
41
+ fileName?: string | undefined;
42
+ fileFormat?: string | undefined;
43
+ // NOTE: type string is suitable for CSV/Excel, etc. but will not be appropriate
44
+ // for other format that we want to support, e.g. arrow/parquet
45
+ fileData?: string | undefined;
46
+ previewText?: string | undefined;
47
+ rowCount?: number | undefined;
48
+
49
+ constructor(
50
+ application: LegendDataCubeApplicationStore,
51
+ engine: LegendDataCubeDataCubeEngine,
52
+ ) {
53
+ super(application, engine);
54
+
55
+ makeObservable(this, {
56
+ fileName: observable,
57
+ setFileName: action,
58
+
59
+ fileFormat: observable,
60
+ setFileFormat: action,
61
+
62
+ fileData: observable,
63
+ setFileData: action,
64
+
65
+ previewText: observable,
66
+ setPreviewText: action,
67
+
68
+ rowCount: observable,
69
+ setRowCount: action,
70
+ });
71
+ }
72
+
73
+ setFileName(fileName: string | undefined) {
74
+ this.fileName = fileName;
75
+ }
76
+
77
+ setFileFormat(format: string | undefined) {
78
+ this.fileFormat = format;
79
+ }
80
+
81
+ setFileData(data: string | undefined) {
82
+ this.fileData = data;
83
+ }
84
+
85
+ setRowCount(count: number | undefined) {
86
+ this.rowCount = count;
87
+ }
88
+
89
+ setPreviewText(text: string | undefined) {
90
+ this.previewText = text;
91
+ }
92
+
93
+ processFile(file: File | undefined) {
94
+ this.setFileName(undefined);
95
+ this.setFileFormat(undefined);
96
+ this.setFileData(undefined);
97
+ this.setRowCount(undefined);
98
+ this.setPreviewText(undefined);
99
+
100
+ if (!file) {
101
+ return;
102
+ }
103
+
104
+ this.processState.inProgress();
105
+
106
+ const fileName = file.name;
107
+ const fileFormat = fileName.split('.').pop();
108
+
109
+ switch (fileFormat?.toLowerCase()) {
110
+ case LocalFileDataCubeSourceFormat.CSV.toLowerCase(): {
111
+ parseCSVFile(file, {
112
+ complete: (result) => {
113
+ this.setFileData(
114
+ csvStringify(result.data, { escapeChar: `'`, quoteChar: `'` }),
115
+ );
116
+ this.setFileName(fileName);
117
+ this.setFileFormat(fileFormat);
118
+ this.setRowCount(result.data.length);
119
+ this.setPreviewText(
120
+ csvStringify(result.data.slice(0, 100), {
121
+ escapeChar: `'`,
122
+ quoteChar: `'`,
123
+ }),
124
+ );
125
+ },
126
+ header: true,
127
+ dynamicTyping: false,
128
+ skipEmptyLines: true,
129
+ });
130
+ break;
131
+ }
132
+ default: {
133
+ this.processState.complete();
134
+ throw new IllegalStateError(
135
+ `Can't process file with format '${fileFormat}'`,
136
+ );
137
+ }
138
+ }
139
+
140
+ this.processState.complete();
141
+ }
142
+
143
+ override get label(): LegendDataCubeSourceBuilderType {
144
+ return LegendDataCubeSourceBuilderType.LOCAL_FILE;
145
+ }
146
+
147
+ override get isValid(): boolean {
148
+ return Boolean(this.fileData);
149
+ }
150
+
151
+ override async generateSourceData(): Promise<PlainObject> {
152
+ if (
153
+ !this.fileData ||
154
+ !this.fileName ||
155
+ !this.fileFormat ||
156
+ this.rowCount === undefined
157
+ ) {
158
+ throw new IllegalStateError(
159
+ `Can't generate source data: file data and information is not set`,
160
+ );
161
+ }
162
+
163
+ const source = guaranteeType(
164
+ await this._engine.ingestLocalFileData(this.fileData, this.fileFormat),
165
+ LocalFileDataCubeSource,
166
+ `Can't generate data source`,
167
+ );
168
+ const rawSource = new RawLocalFileQueryDataCubeSource();
169
+ rawSource.count = this.rowCount;
170
+ rawSource.fileName = this.fileName;
171
+ rawSource.db = source.db;
172
+ rawSource.model = source.model;
173
+ rawSource.schema = source.schema;
174
+ rawSource.table = source.table;
175
+ rawSource.runtime = source.runtime;
176
+
177
+ return RawLocalFileQueryDataCubeSource.serialization.toJson(rawSource);
178
+ }
179
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { DataCubeSource } from '@finos/legend-data-cube';
18
+ import { type V1_PureModelContextData } from '@finos/legend-graph';
19
+ import {
20
+ SerializationFactory,
21
+ usingConstantValueSchema,
22
+ type PlainObject,
23
+ } from '@finos/legend-shared';
24
+ import { createModelSchema, primitive, raw } from 'serializr';
25
+
26
+ export const LOCAL_FILE_QUERY_DATA_CUBE_SOURCE_TYPE = 'localFile';
27
+
28
+ export enum LocalFileDataCubeSourceFormat {
29
+ CSV = 'csv',
30
+ // TODO: arrow/parquet/excel, etc.
31
+ }
32
+
33
+ export class LocalFileDataCubeSource extends DataCubeSource {
34
+ model!: PlainObject<V1_PureModelContextData>;
35
+ runtime!: string;
36
+ db!: string;
37
+ schema!: string;
38
+ table!: string;
39
+ count!: number;
40
+ fileName!: string;
41
+ fileFormat!: LocalFileDataCubeSourceFormat;
42
+ }
43
+
44
+ export class RawLocalFileQueryDataCubeSource {
45
+ model!: PlainObject<V1_PureModelContextData>;
46
+ runtime!: string;
47
+ db!: string;
48
+ schema!: string;
49
+ table!: string;
50
+ count!: number;
51
+ fileName!: string;
52
+ fileFormat!: LocalFileDataCubeSourceFormat;
53
+
54
+ static readonly serialization = new SerializationFactory(
55
+ createModelSchema(RawLocalFileQueryDataCubeSource, {
56
+ _type: usingConstantValueSchema(LOCAL_FILE_QUERY_DATA_CUBE_SOURCE_TYPE),
57
+ count: primitive(),
58
+ db: primitive(),
59
+ fileFormat: primitive(),
60
+ fileName: primitive(),
61
+ model: raw(),
62
+ runtime: primitive(),
63
+ schema: primitive(),
64
+ table: primitive(),
65
+ }),
66
+ );
67
+ }
package/tsconfig.json CHANGED
@@ -62,12 +62,14 @@
62
62
  "./src/application/LegendDataCubePluginManager.ts",
63
63
  "./src/stores/DuckDBWASM.d.ts",
64
64
  "./src/stores/LegendDataCubeBaseStore.ts",
65
- "./src/stores/LegendDataCubeCacheManager.ts",
66
65
  "./src/stores/LegendDataCubeDataCubeEngine.ts",
66
+ "./src/stores/LegendDataCubeDuckDBEngine.ts",
67
67
  "./src/stores/builder/source/AdhocQueryDataCubeSourceBuilderState.ts",
68
68
  "./src/stores/builder/source/LegendDataCubeSourceBuilderState.ts",
69
69
  "./src/stores/builder/source/LegendQueryDataCubeSourceBuilderState.ts",
70
+ "./src/stores/builder/source/LocalFileDataCubeSourceBuilderState.ts",
70
71
  "./src/stores/model/LegendQueryDataCubeSource.ts",
72
+ "./src/stores/model/LocalFileDataCubeSource.ts",
71
73
  "./src/application/LegendDataCube.tsx",
72
74
  "./src/components/LegendDataCubeBlockingWindow.tsx",
73
75
  "./src/components/LegendDataCubeFrameworkProvider.tsx",
@@ -81,6 +83,7 @@
81
83
  "./src/components/builder/LegendDataCubeSourceViewer.tsx",
82
84
  "./src/components/builder/source/AdhocQueryDataCubeSourceBuilder.tsx",
83
85
  "./src/components/builder/source/LegendQueryDataCubeSourceBuilder.tsx",
86
+ "./src/components/builder/source/LocalFileDataCubeSourceBuilder.tsx",
84
87
  "./src/stores/builder/LegendDataCubeBuilderStore.tsx",
85
88
  "./src/stores/builder/LegendDataCubeCreatorState.tsx",
86
89
  "./src/stores/builder/LegendDataCubeLoaderState.tsx"
@@ -1 +0,0 @@
1
- {"version":3,"file":"LegendDataCubeCacheManager.d.ts","sourceRoot":"","sources":["../../src/stores/LegendDataCubeCacheManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,EAIL,kBAAkB,EAGnB,MAAM,qBAAqB,CAAC;AAM7B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAGpE,qBAAa,kCAAkC;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAU;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAW;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAU;IAC/C,OAAO,CAAC,MAAM,CAAC,YAAY,CAAK;IAEhC,OAAO,CAAC,SAAS,CAAC,CAAiC;IAEnD,OAAO,KAAK,QAAQ,GAKnB;IAEK,UAAU;IAmCV,KAAK,CAAC,MAAM,EAAE,kBAAkB;;;;;IA+ChC,WAAW,CAAC,GAAG,EAAE,MAAM;IAmFvB,YAAY,CAAC,MAAM,EAAE,oBAAoB;IAOzC,OAAO;CAId"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"LegendDataCubeCacheManager.js","sourceRoot":"","sources":["../../src/stores/LegendDataCubeCacheManager.ts"],"names":[],"mappings":"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"}