@finos/legend-application-data-cube 0.2.8 → 0.3.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.
- package/lib/components/builder/LegendDataCubeBuilder.d.ts.map +1 -1
- package/lib/components/builder/LegendDataCubeBuilder.js +4 -1
- package/lib/components/builder/LegendDataCubeBuilder.js.map +1 -1
- package/lib/components/builder/LegendDataCubeCreator.d.ts.map +1 -1
- package/lib/components/builder/LegendDataCubeCreator.js +12 -5
- package/lib/components/builder/LegendDataCubeCreator.js.map +1 -1
- package/lib/components/builder/LegendDataCubeLoader.js +6 -6
- package/lib/components/builder/LegendDataCubeLoader.js.map +1 -1
- package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.d.ts.map +1 -1
- package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.js +2 -3
- package/lib/components/builder/source/AdhocQueryDataCubeSourceBuilder.js.map +1 -1
- package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder.js +6 -6
- package/lib/components/builder/source/LegendQueryDataCubeSourceBuilder.js.map +1 -1
- package/lib/components/builder/source/LocalFileDataCubeSourceBuilder.d.ts +22 -0
- package/lib/components/builder/source/LocalFileDataCubeSourceBuilder.d.ts.map +1 -0
- package/lib/components/builder/source/LocalFileDataCubeSourceBuilder.js +29 -0
- package/lib/components/builder/source/LocalFileDataCubeSourceBuilder.js.map +1 -0
- package/lib/index.css +1 -1
- package/lib/package.json +5 -5
- package/lib/stores/LegendDataCubeDataCubeEngine.d.ts +5 -3
- package/lib/stores/LegendDataCubeDataCubeEngine.d.ts.map +1 -1
- package/lib/stores/LegendDataCubeDataCubeEngine.js +297 -120
- package/lib/stores/LegendDataCubeDataCubeEngine.js.map +1 -1
- package/lib/stores/{LegendDataCubeCacheManager.d.ts → LegendDataCubeDuckDBEngine.d.ts} +18 -6
- package/lib/stores/LegendDataCubeDuckDBEngine.d.ts.map +1 -0
- package/lib/stores/{LegendDataCubeCacheManager.js → LegendDataCubeDuckDBEngine.js} +76 -24
- package/lib/stores/LegendDataCubeDuckDBEngine.js.map +1 -0
- package/lib/stores/builder/LegendDataCubeBuilderStore.js +2 -2
- package/lib/stores/builder/LegendDataCubeBuilderStore.js.map +1 -1
- package/lib/stores/builder/LegendDataCubeCreatorState.d.ts.map +1 -1
- package/lib/stores/builder/LegendDataCubeCreatorState.js +3 -0
- package/lib/stores/builder/LegendDataCubeCreatorState.js.map +1 -1
- package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.d.ts +5 -1
- package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.d.ts.map +1 -1
- package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.js +4 -1
- package/lib/stores/builder/source/LegendDataCubeSourceBuilderState.js.map +1 -1
- package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.d.ts.map +1 -1
- package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.js +1 -1
- package/lib/stores/builder/source/LegendQueryDataCubeSourceBuilderState.js.map +1 -1
- package/lib/stores/builder/source/LocalFileDataCubeSourceBuilderState.d.ts +38 -0
- package/lib/stores/builder/source/LocalFileDataCubeSourceBuilderState.d.ts.map +1 -0
- package/lib/stores/builder/source/LocalFileDataCubeSourceBuilderState.js +122 -0
- package/lib/stores/builder/source/LocalFileDataCubeSourceBuilderState.js.map +1 -0
- package/lib/stores/model/LocalFileDataCubeSource.d.ts +44 -0
- package/lib/stores/model/LocalFileDataCubeSource.d.ts.map +1 -0
- package/lib/stores/model/LocalFileDataCubeSource.js +57 -0
- package/lib/stores/model/LocalFileDataCubeSource.js.map +1 -0
- package/package.json +15 -15
- package/src/components/builder/LegendDataCubeBuilder.tsx +6 -1
- package/src/components/builder/LegendDataCubeCreator.tsx +23 -6
- package/src/components/builder/LegendDataCubeLoader.tsx +7 -7
- package/src/components/builder/source/AdhocQueryDataCubeSourceBuilder.tsx +2 -3
- package/src/components/builder/source/LegendQueryDataCubeSourceBuilder.tsx +8 -8
- package/src/components/builder/source/LocalFileDataCubeSourceBuilder.tsx +59 -0
- package/src/stores/LegendDataCubeDataCubeEngine.ts +407 -182
- package/src/stores/{LegendDataCubeCacheManager.ts → LegendDataCubeDuckDBEngine.ts} +81 -28
- package/src/stores/builder/LegendDataCubeBuilderStore.tsx +2 -2
- package/src/stores/builder/LegendDataCubeCreatorState.tsx +6 -0
- package/src/stores/builder/source/LegendDataCubeSourceBuilderState.ts +4 -1
- package/src/stores/builder/source/LegendQueryDataCubeSourceBuilderState.ts +3 -1
- package/src/stores/builder/source/LocalFileDataCubeSourceBuilderState.ts +179 -0
- package/src/stores/model/LocalFileDataCubeSource.ts +67 -0
- package/tsconfig.json +4 -1
- package/lib/stores/LegendDataCubeCacheManager.d.ts.map +0 -1
- package/lib/stores/LegendDataCubeCacheManager.js.map +0 -1
|
@@ -34,11 +34,20 @@ import {
|
|
|
34
34
|
import type { CachedDataCubeSource } from '@finos/legend-data-cube';
|
|
35
35
|
import { Type } from 'apache-arrow';
|
|
36
36
|
|
|
37
|
-
export class
|
|
37
|
+
export class LegendDataCubeDuckDBEngine {
|
|
38
38
|
private static readonly DUCKDB_DEFAULT_SCHEMA_NAME = 'main'; // See https://duckdb.org/docs/sql/statements/use.html
|
|
39
|
-
private static readonly
|
|
40
|
-
private static readonly
|
|
41
|
-
private static
|
|
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 = `'`;
|
|
42
51
|
|
|
43
52
|
private _database?: duckdb.AsyncDuckDB | undefined;
|
|
44
53
|
|
|
@@ -85,40 +94,79 @@ export class LegendDataCubeDataCubeCacheManager {
|
|
|
85
94
|
}
|
|
86
95
|
|
|
87
96
|
async cache(result: TDSExecutionResult) {
|
|
88
|
-
const schema =
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
const csvFileName = `${LegendDataCubeDataCubeCacheManager.CSV_FILE_NAME}${LegendDataCubeDataCubeCacheManager.tableCounter}.csv`;
|
|
93
|
-
|
|
94
|
-
const connection = await this.database.connect();
|
|
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`;
|
|
95
101
|
|
|
96
102
|
const columnNames: string[] = [];
|
|
97
103
|
result.builder.columns.forEach((col) => columnNames.push(col.name));
|
|
98
104
|
|
|
99
105
|
const data = result.result.rows.map((row) => row.values);
|
|
100
106
|
|
|
101
|
-
const
|
|
102
|
-
escapeChar:
|
|
103
|
-
quoteChar:
|
|
107
|
+
const csvContent = csvStringify([columnNames, ...data], {
|
|
108
|
+
escapeChar: LegendDataCubeDuckDBEngine.ESCAPE_CHAR,
|
|
109
|
+
quoteChar: LegendDataCubeDuckDBEngine.QUOTE_CHAR,
|
|
104
110
|
});
|
|
111
|
+
await this.database.registerFileText(csvFileName, csvContent);
|
|
105
112
|
|
|
106
|
-
await this.
|
|
107
|
-
|
|
113
|
+
const connection = await this.database.connect();
|
|
108
114
|
await connection.insertCSVFromPath(csvFileName, {
|
|
109
115
|
schema: schema,
|
|
110
116
|
name: table,
|
|
111
117
|
create: true,
|
|
112
118
|
header: true,
|
|
113
119
|
detect: true,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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,
|
|
117
124
|
});
|
|
125
|
+
await connection.close();
|
|
126
|
+
|
|
127
|
+
return { schema, table, rowCount: result.result.rows.length };
|
|
128
|
+
}
|
|
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}`;
|
|
118
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
|
+
]);
|
|
119
167
|
await connection.close();
|
|
120
168
|
|
|
121
|
-
return {
|
|
169
|
+
return { schema, table, tableSpec };
|
|
122
170
|
}
|
|
123
171
|
|
|
124
172
|
async runSQLQuery(sql: string) {
|
|
@@ -130,14 +178,18 @@ export class LegendDataCubeDataCubeCacheManager {
|
|
|
130
178
|
const columnNames = result.schema.fields.map((field) => field.name);
|
|
131
179
|
const rows = data.map((row) => {
|
|
132
180
|
const tdsRow = new TDSRow();
|
|
133
|
-
tdsRow.values = columnNames.map(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
+
});
|
|
141
193
|
return tdsRow;
|
|
142
194
|
});
|
|
143
195
|
const tdsExecutionResult = new TDSExecutionResult();
|
|
@@ -158,6 +210,7 @@ export class LegendDataCubeDataCubeCacheManager {
|
|
|
158
210
|
col.type = PRIMITIVE_TYPE.BOOLEAN;
|
|
159
211
|
break;
|
|
160
212
|
}
|
|
213
|
+
case Type.Timestamp:
|
|
161
214
|
case Type.Date:
|
|
162
215
|
case Type.DateDay:
|
|
163
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.
|
|
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.
|
|
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
|
-
|
|
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(
|
|
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;AAO7B,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;;;;;IAqChC,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":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAC9C,OAAO,WAAW,MAAM,0CAA0C,CAAC;AACnE,OAAO,gBAAgB,MAAM,yCAAyC,CAAC;AACvE,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,MAAM,EACN,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,MAAM,OAAO,kCAAkC;IACrC,MAAM,CAAU,0BAA0B,GAAG,MAAM,CAAC,CAAC,sDAAsD;IAC3G,MAAM,CAAU,iBAAiB,GAAG,OAAO,CAAC;IAC5C,MAAM,CAAU,aAAa,GAAG,MAAM,CAAC;IACvC,MAAM,CAAC,YAAY,GAAG,CAAC,CAAC;IAExB,SAAS,CAAkC;IAEnD,IAAY,QAAQ;QAClB,OAAO,oBAAoB,CACzB,IAAI,CAAC,SAAS,EACd,wCAAwC,CACzC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU;QACd,8BAA8B;QAC9B,2DAA2D;QAC3D,MAAM,cAAc,GAAyB;YAC3C,GAAG,EAAE;gBACH,mEAAmE;gBACnE,UAAU,EAAE,WAAW;gBACvB,UAAU,EAAE,IAAI,GAAG,CACjB,uDAAuD,EACvD,MAAM,CAAC,IAAI,CAAC,GAAG,CAChB,CAAC,QAAQ,EAAE;aACb;YACD,EAAE,EAAE;gBACF,mEAAmE;gBACnE,UAAU,EAAE,gBAAgB;gBAC5B,UAAU,EAAE,IAAI,GAAG,CACjB,sDAAsD,EACtD,MAAM,CAAC,IAAI,CAAC,GAAG,CAChB,CAAC,QAAQ,EAAE;aACb;SACF,CAAC;QACF,0CAA0C;QAC1C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QACzD,qDAAqD;QACrD,iBAAiB,CACf,MAAM,CAAC,UAAU,EACjB,oEAAoE,CACrE,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC;QAClG,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACxD,MAAM,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACpE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAA0B;QACpC,MAAM,MAAM,GACV,kCAAkC,CAAC,0BAA0B,CAAC;QAChE,kCAAkC,CAAC,YAAY,IAAI,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,GAAG,kCAAkC,CAAC,iBAAiB,GAAG,kCAAkC,CAAC,YAAY,EAAE,CAAC;QAC1H,MAAM,WAAW,GAAG,GAAG,kCAAkC,CAAC,aAAa,GAAG,kCAAkC,CAAC,YAAY,MAAM,CAAC;QAEhI,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAEjD,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAEpE,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEzD,MAAM,GAAG,GAAG,YAAY,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,EAAE;YAC/C,UAAU,EAAE,GAAG;YACf,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAEzD,MAAM,UAAU,CAAC,iBAAiB,CAAC,WAAW,EAAE;YAC9C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,KAAK;YACX,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;QAEzB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,GAAW;QAC3B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;QAEzB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;QAC9B,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC5B,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,CAC7B,CAAC,MAAM,EAAE,EAAE;YACT,gFAAgF;YAChF,qCAAqC;YACrC,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC9B,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;gBACvB,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAqC,CACvD,CAAC;YACF,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,MAAM,kBAAkB,GAAG,IAAI,kBAAkB,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;QACjC,GAAG,CAAC,OAAO,GAAG,WAAW,CAAC;QAC1B,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAChB,kBAAkB,CAAC,MAAM,GAAG,GAAG,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,UAAU,EAAE,CAAC;QACjC,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACnD,MAAM,GAAG,GAAG,IAAI,mBAAmB,EAAE,CAAC;YACtC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YACtB,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;gBACrB,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;oBACjB,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC;oBACjC,MAAM;gBACR,CAAC;gBACD,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBACf,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC;oBAClC,MAAM;gBACR,CAAC;gBACD,KAAK,IAAI,CAAC,IAAI,CAAC;gBACf,KAAK,IAAI,CAAC,OAAO,CAAC;gBAClB,KAAK,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;oBAC1B,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC;oBAC/B,MAAM;gBACR,CAAC;gBACD,KAAK,IAAI,CAAC,IAAI,CAAC;gBACf,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;oBACpB,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC;oBACjC,MAAM;gBACR,CAAC;gBACD,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;oBAClB,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC;oBAClC,MAAM;gBACR,CAAC;gBACD,KAAK,IAAI,CAAC,GAAG,CAAC;gBACd,KAAK,IAAI,CAAC,IAAI,CAAC;gBACf,KAAK,IAAI,CAAC,KAAK,CAAC;gBAChB,KAAK,IAAI,CAAC,KAAK,CAAC;gBAChB,KAAK,IAAI,CAAC,MAAM,CAAC;gBACjB,KAAK,IAAI,CAAC,KAAK,CAAC;gBAChB,KAAK,IAAI,CAAC,MAAM,CAAC;gBACjB,KAAK,IAAI,CAAC,KAAK,CAAC;gBAChB,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;oBACjB,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC;oBAClC,MAAM;gBACR,CAAC;gBACD,KAAK,IAAI,CAAC,KAAK,CAAC;gBAChB,KAAK,IAAI,CAAC,OAAO,CAAC;gBAClB,KAAK,IAAI,CAAC,OAAO,CAAC;gBAClB,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;oBAClB,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC;oBAChC,MAAM;gBACR,CAAC;gBACD,OAAO,CAAC,CAAC,CAAC;oBACR,MAAM,IAAI,yBAAyB,CACjC,oDAAoD,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,EAAE,CACjF,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC,CAAC,CAAC;QACH,kBAAkB,CAAC,OAAO,GAAG,OAAO,CAAC;QACrC,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAA4B;QAC7C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACjD,MAAM,cAAc,GAAG,yBAAyB,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC;QACjF,MAAM,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACvC,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC;QACnC,MAAM,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC;IACpC,CAAC"}
|