dbgate-datalib 5.1.3 → 5.1.5
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/PerspectiveCache.d.ts +3 -0
- package/lib/PerspectiveCache.js +12 -2
- package/lib/PerspectiveConfig.d.ts +5 -0
- package/lib/PerspectiveDataLoader.d.ts +9 -1
- package/lib/PerspectiveDataLoader.js +158 -23
- package/lib/PerspectiveDataPattern.d.ts +17 -0
- package/lib/PerspectiveDataPattern.js +79 -0
- package/lib/PerspectiveDataProvider.d.ts +10 -8
- package/lib/PerspectiveDataProvider.js +3 -1
- package/lib/PerspectiveDisplay.d.ts +1 -0
- package/lib/PerspectiveDisplay.js +29 -9
- package/lib/PerspectiveTreeNode.d.ts +43 -11
- package/lib/PerspectiveTreeNode.js +235 -101
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/processPerspectiveDefaultColunns.d.ts +4 -3
- package/lib/processPerspectiveDefaultColunns.js +33 -14
- package/lib/tests/PerspectiveDisplay.test.js +3 -3
- package/lib/tests/PerspectiveDisplayNoSql.test.d.ts +1 -0
- package/lib/tests/PerspectiveDisplayNoSql.test.js +69 -0
- package/package.json +5 -5
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PerspectiveDataLoadProps } from './PerspectiveDataProvider';
|
|
2
|
+
import { PerspectiveDataPattern } from './PerspectiveDataPattern';
|
|
2
3
|
export declare class PerspectiveBindingGroup {
|
|
3
4
|
table: PerspectiveCacheTable;
|
|
4
5
|
constructor(table: PerspectiveCacheTable);
|
|
@@ -15,6 +16,7 @@ export declare class PerspectiveCacheTable {
|
|
|
15
16
|
pureName: string;
|
|
16
17
|
bindingColumns?: string[];
|
|
17
18
|
dataColumns: string[];
|
|
19
|
+
allColumns?: boolean;
|
|
18
20
|
loadedAll: boolean;
|
|
19
21
|
loadedRows: any[];
|
|
20
22
|
bindingGroups: {
|
|
@@ -35,6 +37,7 @@ export declare class PerspectiveCache {
|
|
|
35
37
|
tables: {
|
|
36
38
|
[tableKey: string]: PerspectiveCacheTable;
|
|
37
39
|
};
|
|
40
|
+
dataPatterns: PerspectiveDataPattern[];
|
|
38
41
|
getTableCache(props: PerspectiveDataLoadProps): PerspectiveCacheTable;
|
|
39
42
|
clear(): void;
|
|
40
43
|
}
|
package/lib/PerspectiveCache.js
CHANGED
|
@@ -75,11 +75,20 @@ exports.PerspectiveCacheTable = PerspectiveCacheTable;
|
|
|
75
75
|
class PerspectiveCache {
|
|
76
76
|
constructor() {
|
|
77
77
|
this.tables = {};
|
|
78
|
+
this.dataPatterns = [];
|
|
78
79
|
}
|
|
79
80
|
getTableCache(props) {
|
|
80
|
-
const tableKey = (0, json_stable_stringify_1.default)((0, pick_1.default)(props, [
|
|
81
|
+
const tableKey = (0, json_stable_stringify_1.default)((0, pick_1.default)(props, [
|
|
82
|
+
'schemaName',
|
|
83
|
+
'pureName',
|
|
84
|
+
'bindingColumns',
|
|
85
|
+
'databaseConfig',
|
|
86
|
+
'orderBy',
|
|
87
|
+
'sqlCondition',
|
|
88
|
+
'mongoCondition',
|
|
89
|
+
]));
|
|
81
90
|
let res = this.tables[tableKey];
|
|
82
|
-
if (res && (0, difference_1.default)(props.dataColumns, res.dataColumns).length > 0) {
|
|
91
|
+
if (res && (0, difference_1.default)(props.dataColumns, res.dataColumns).length > 0 && !res.allColumns) {
|
|
83
92
|
dbg('Delete cache because incomplete columns', props.pureName, res.dataColumns);
|
|
84
93
|
// we have incomplete cache
|
|
85
94
|
delete this.tables[tableKey];
|
|
@@ -95,6 +104,7 @@ class PerspectiveCache {
|
|
|
95
104
|
}
|
|
96
105
|
clear() {
|
|
97
106
|
this.tables = {};
|
|
107
|
+
this.dataPatterns = [];
|
|
98
108
|
}
|
|
99
109
|
}
|
|
100
110
|
exports.PerspectiveCache = PerspectiveCache;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { DatabaseInfo, ForeignKeyInfo } from 'dbgate-types';
|
|
2
|
+
export declare type PerspectiveDatabaseEngineType = 'sqldb' | 'docdb';
|
|
3
|
+
export interface PerspectiveDatabaseConfig {
|
|
4
|
+
conid: string;
|
|
5
|
+
database: string;
|
|
6
|
+
}
|
|
2
7
|
export interface PerspectiveCustomJoinConfig {
|
|
3
8
|
refNodeDesignerId: string;
|
|
4
9
|
referenceDesignerId: string;
|
|
@@ -3,8 +3,16 @@ import { PerspectiveDataLoadProps } from './PerspectiveDataProvider';
|
|
|
3
3
|
export declare class PerspectiveDataLoader {
|
|
4
4
|
apiCall: any;
|
|
5
5
|
constructor(apiCall: any);
|
|
6
|
-
|
|
6
|
+
buildSqlCondition(props: PerspectiveDataLoadProps): Condition;
|
|
7
|
+
buildMongoCondition(props: PerspectiveDataLoadProps): {};
|
|
8
|
+
loadGroupingSqlDb(props: PerspectiveDataLoadProps): Promise<any>;
|
|
9
|
+
loadGroupingDocDb(props: PerspectiveDataLoadProps): Promise<any>;
|
|
7
10
|
loadGrouping(props: PerspectiveDataLoadProps): Promise<any>;
|
|
11
|
+
loadDataSqlDb(props: PerspectiveDataLoadProps): Promise<any>;
|
|
12
|
+
getDocDbLoadOptions(props: PerspectiveDataLoadProps, useSort: boolean): any;
|
|
13
|
+
loadDataDocDb(props: PerspectiveDataLoadProps): Promise<any>;
|
|
8
14
|
loadData(props: PerspectiveDataLoadProps): Promise<any>;
|
|
15
|
+
loadRowCountSqlDb(props: PerspectiveDataLoadProps): Promise<any>;
|
|
16
|
+
loadRowCountDocDb(props: PerspectiveDataLoadProps): Promise<any>;
|
|
9
17
|
loadRowCount(props: PerspectiveDataLoadProps): Promise<any>;
|
|
10
18
|
}
|
|
@@ -14,16 +14,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.PerspectiveDataLoader = void 0;
|
|
16
16
|
const debug_1 = __importDefault(require("debug"));
|
|
17
|
+
const zipObject_1 = __importDefault(require("lodash/zipObject"));
|
|
18
|
+
const mapValues_1 = __importDefault(require("lodash/mapValues"));
|
|
19
|
+
const isArray_1 = __importDefault(require("lodash/isArray"));
|
|
20
|
+
const dbgate_tools_1 = require("dbgate-tools");
|
|
21
|
+
function normalizeLoadedRow(row) {
|
|
22
|
+
return (0, mapValues_1.default)(row, v => (0, dbgate_tools_1.safeJsonParse)(v) || v);
|
|
23
|
+
}
|
|
24
|
+
function normalizeResult(result) {
|
|
25
|
+
if ((0, isArray_1.default)(result)) {
|
|
26
|
+
return result.map(normalizeLoadedRow);
|
|
27
|
+
}
|
|
28
|
+
if (result.errorMessage) {
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
return Object.assign(Object.assign({}, result), { errorMessage: 'Unspecified error' });
|
|
32
|
+
}
|
|
17
33
|
const dbg = (0, debug_1.default)('dbgate:PerspectiveDataLoader');
|
|
18
34
|
class PerspectiveDataLoader {
|
|
19
35
|
constructor(apiCall) {
|
|
20
36
|
this.apiCall = apiCall;
|
|
21
37
|
}
|
|
22
|
-
|
|
23
|
-
const { schemaName, pureName, bindingColumns, bindingValues, dataColumns, orderBy,
|
|
38
|
+
buildSqlCondition(props) {
|
|
39
|
+
const { schemaName, pureName, bindingColumns, bindingValues, dataColumns, orderBy, sqlCondition } = props;
|
|
24
40
|
const conditions = [];
|
|
25
|
-
if (
|
|
26
|
-
conditions.push(
|
|
41
|
+
if (sqlCondition) {
|
|
42
|
+
conditions.push(sqlCondition);
|
|
27
43
|
}
|
|
28
44
|
if ((bindingColumns === null || bindingColumns === void 0 ? void 0 : bindingColumns.length) == 1) {
|
|
29
45
|
conditions.push({
|
|
@@ -45,10 +61,22 @@ class PerspectiveDataLoader {
|
|
|
45
61
|
}
|
|
46
62
|
: null;
|
|
47
63
|
}
|
|
48
|
-
|
|
49
|
-
|
|
64
|
+
buildMongoCondition(props) {
|
|
65
|
+
const { schemaName, pureName, bindingColumns, bindingValues, dataColumns, orderBy, mongoCondition } = props;
|
|
66
|
+
const conditions = [];
|
|
67
|
+
if (mongoCondition) {
|
|
68
|
+
conditions.push(mongoCondition);
|
|
69
|
+
}
|
|
70
|
+
if ((bindingColumns === null || bindingColumns === void 0 ? void 0 : bindingColumns.length) == 1) {
|
|
71
|
+
conditions.push({
|
|
72
|
+
[bindingColumns[0]]: { $in: bindingValues.map(x => x[0]) },
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return conditions.length == 1 ? conditions[0] : conditions.length > 0 ? { $and: conditions } : null;
|
|
76
|
+
}
|
|
77
|
+
loadGroupingSqlDb(props) {
|
|
50
78
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
-
const { schemaName, pureName, bindingColumns
|
|
79
|
+
const { schemaName, pureName, bindingColumns } = props;
|
|
52
80
|
const bindingColumnExpressions = bindingColumns.map(columnName => ({
|
|
53
81
|
exprType: 'column',
|
|
54
82
|
columnName,
|
|
@@ -75,11 +103,11 @@ class PerspectiveDataLoader {
|
|
|
75
103
|
},
|
|
76
104
|
...bindingColumnExpressions,
|
|
77
105
|
],
|
|
78
|
-
where: this.
|
|
106
|
+
where: this.buildSqlCondition(props),
|
|
79
107
|
};
|
|
80
108
|
select.groupBy = bindingColumnExpressions;
|
|
81
109
|
if (dbg === null || dbg === void 0 ? void 0 : dbg.enabled) {
|
|
82
|
-
dbg(`LOAD COUNTS, table=${props.pureName}, columns=${
|
|
110
|
+
dbg(`LOAD COUNTS, table=${props.pureName}, columns=${bindingColumns === null || bindingColumns === void 0 ? void 0 : bindingColumns.join(',')}`);
|
|
83
111
|
}
|
|
84
112
|
const response = yield this.apiCall('database-connections/sql-select', {
|
|
85
113
|
conid: props.databaseConfig.conid,
|
|
@@ -91,10 +119,49 @@ class PerspectiveDataLoader {
|
|
|
91
119
|
return response.rows.map(row => (Object.assign(Object.assign({}, row), { _perspective_group_size_: parseInt(row._perspective_group_size_) })));
|
|
92
120
|
});
|
|
93
121
|
}
|
|
94
|
-
|
|
122
|
+
loadGroupingDocDb(props) {
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
const { schemaName, pureName, bindingColumns } = props;
|
|
125
|
+
const aggregate = [
|
|
126
|
+
{ $match: this.buildMongoCondition(props) },
|
|
127
|
+
{
|
|
128
|
+
$group: {
|
|
129
|
+
_id: (0, zipObject_1.default)(bindingColumns, bindingColumns.map(col => '$' + col)),
|
|
130
|
+
count: { $sum: 1 },
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
];
|
|
134
|
+
if (dbg === null || dbg === void 0 ? void 0 : dbg.enabled) {
|
|
135
|
+
dbg(`LOAD COUNTS, table=${props.pureName}, columns=${bindingColumns === null || bindingColumns === void 0 ? void 0 : bindingColumns.join(',')}`);
|
|
136
|
+
}
|
|
137
|
+
const response = yield this.apiCall('database-connections/collection-data', {
|
|
138
|
+
conid: props.databaseConfig.conid,
|
|
139
|
+
database: props.databaseConfig.database,
|
|
140
|
+
options: {
|
|
141
|
+
pureName,
|
|
142
|
+
aggregate,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
if (response.errorMessage)
|
|
146
|
+
return response;
|
|
147
|
+
return response.rows.map(row => (Object.assign(Object.assign({}, row._id), { _perspective_group_size_: parseInt(row.count) })));
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
loadGrouping(props) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
const { engineType } = props;
|
|
153
|
+
switch (engineType) {
|
|
154
|
+
case 'sqldb':
|
|
155
|
+
return this.loadGroupingSqlDb(props);
|
|
156
|
+
case 'docdb':
|
|
157
|
+
return this.loadGroupingDocDb(props);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
loadDataSqlDb(props) {
|
|
95
162
|
var _a, _b, _c;
|
|
96
163
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
-
const { schemaName, pureName, bindingColumns, bindingValues, dataColumns, orderBy, condition } = props;
|
|
164
|
+
const { schemaName, pureName, bindingColumns, bindingValues, dataColumns, orderBy, sqlCondition: condition, engineType, } = props;
|
|
98
165
|
if ((dataColumns === null || dataColumns === void 0 ? void 0 : dataColumns.length) == 0) {
|
|
99
166
|
return [];
|
|
100
167
|
}
|
|
@@ -111,16 +178,18 @@ class PerspectiveDataLoader {
|
|
|
111
178
|
},
|
|
112
179
|
})),
|
|
113
180
|
selectAll: !dataColumns,
|
|
114
|
-
orderBy: orderBy === null || orderBy === void 0 ? void 0 : orderBy.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
181
|
+
orderBy: (orderBy === null || orderBy === void 0 ? void 0 : orderBy.length) > 0
|
|
182
|
+
? orderBy === null || orderBy === void 0 ? void 0 : orderBy.map(({ columnName, order }) => ({
|
|
183
|
+
exprType: 'column',
|
|
184
|
+
columnName,
|
|
185
|
+
direction: order,
|
|
186
|
+
source: {
|
|
187
|
+
name: { schemaName, pureName },
|
|
188
|
+
},
|
|
189
|
+
}))
|
|
190
|
+
: null,
|
|
122
191
|
range: props.range,
|
|
123
|
-
where: this.
|
|
192
|
+
where: this.buildSqlCondition(props),
|
|
124
193
|
};
|
|
125
194
|
if (dbg === null || dbg === void 0 ? void 0 : dbg.enabled) {
|
|
126
195
|
dbg(`LOAD DATA, table=${props.pureName}, columns=${(_a = props.dataColumns) === null || _a === void 0 ? void 0 : _a.join(',')}, range=${(_b = props.range) === null || _b === void 0 ? void 0 : _b.offset},${(_c = props.range) === null || _c === void 0 ? void 0 : _c.limit}`);
|
|
@@ -135,9 +204,52 @@ class PerspectiveDataLoader {
|
|
|
135
204
|
return response.rows;
|
|
136
205
|
});
|
|
137
206
|
}
|
|
138
|
-
|
|
207
|
+
getDocDbLoadOptions(props, useSort) {
|
|
208
|
+
var _a, _b, _c;
|
|
209
|
+
const { pureName } = props;
|
|
210
|
+
const res = {
|
|
211
|
+
pureName,
|
|
212
|
+
condition: this.buildMongoCondition(props),
|
|
213
|
+
skip: (_a = props.range) === null || _a === void 0 ? void 0 : _a.offset,
|
|
214
|
+
limit: (_b = props.range) === null || _b === void 0 ? void 0 : _b.limit,
|
|
215
|
+
};
|
|
216
|
+
if (useSort && ((_c = props.orderBy) === null || _c === void 0 ? void 0 : _c.length) > 0) {
|
|
217
|
+
res.sort = (0, zipObject_1.default)(props.orderBy.map(col => col.columnName), props.orderBy.map(col => (col.order == 'DESC' ? -1 : 1)));
|
|
218
|
+
}
|
|
219
|
+
return res;
|
|
220
|
+
}
|
|
221
|
+
loadDataDocDb(props) {
|
|
222
|
+
var _a, _b, _c;
|
|
223
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
224
|
+
const { schemaName, pureName, bindingColumns, bindingValues, dataColumns, orderBy, sqlCondition: condition, engineType, } = props;
|
|
225
|
+
if (dbg === null || dbg === void 0 ? void 0 : dbg.enabled) {
|
|
226
|
+
dbg(`LOAD DATA, collection=${props.pureName}, columns=${(_a = props.dataColumns) === null || _a === void 0 ? void 0 : _a.join(',')}, range=${(_b = props.range) === null || _b === void 0 ? void 0 : _b.offset},${(_c = props.range) === null || _c === void 0 ? void 0 : _c.limit}`);
|
|
227
|
+
}
|
|
228
|
+
const options = this.getDocDbLoadOptions(props, true);
|
|
229
|
+
const response = yield this.apiCall('database-connections/collection-data', {
|
|
230
|
+
conid: props.databaseConfig.conid,
|
|
231
|
+
database: props.databaseConfig.database,
|
|
232
|
+
options,
|
|
233
|
+
});
|
|
234
|
+
if (response.errorMessage)
|
|
235
|
+
return response;
|
|
236
|
+
return response.rows;
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
loadData(props) {
|
|
139
240
|
return __awaiter(this, void 0, void 0, function* () {
|
|
140
|
-
const {
|
|
241
|
+
const { engineType } = props;
|
|
242
|
+
switch (engineType) {
|
|
243
|
+
case 'sqldb':
|
|
244
|
+
return normalizeResult(yield this.loadDataSqlDb(props));
|
|
245
|
+
case 'docdb':
|
|
246
|
+
return normalizeResult(yield this.loadDataDocDb(props));
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
loadRowCountSqlDb(props) {
|
|
251
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
252
|
+
const { schemaName, pureName, bindingColumns, bindingValues, dataColumns, orderBy, sqlCondition: condition, } = props;
|
|
141
253
|
const select = {
|
|
142
254
|
commandType: 'select',
|
|
143
255
|
from: {
|
|
@@ -150,7 +262,7 @@ class PerspectiveDataLoader {
|
|
|
150
262
|
alias: 'count',
|
|
151
263
|
},
|
|
152
264
|
],
|
|
153
|
-
where: this.
|
|
265
|
+
where: this.buildSqlCondition(props),
|
|
154
266
|
};
|
|
155
267
|
const response = yield this.apiCall('database-connections/sql-select', {
|
|
156
268
|
conid: props.databaseConfig.conid,
|
|
@@ -162,5 +274,28 @@ class PerspectiveDataLoader {
|
|
|
162
274
|
return response.rows[0];
|
|
163
275
|
});
|
|
164
276
|
}
|
|
277
|
+
loadRowCountDocDb(props) {
|
|
278
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
279
|
+
const { schemaName, pureName, bindingColumns, bindingValues, dataColumns, orderBy, sqlCondition: condition, } = props;
|
|
280
|
+
const options = Object.assign(Object.assign({}, this.getDocDbLoadOptions(props, false)), { countDocuments: true });
|
|
281
|
+
const response = yield this.apiCall('database-connections/collection-data', {
|
|
282
|
+
conid: props.databaseConfig.conid,
|
|
283
|
+
database: props.databaseConfig.database,
|
|
284
|
+
options,
|
|
285
|
+
});
|
|
286
|
+
return response;
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
loadRowCount(props) {
|
|
290
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
291
|
+
const { engineType } = props;
|
|
292
|
+
switch (engineType) {
|
|
293
|
+
case 'sqldb':
|
|
294
|
+
return this.loadRowCountSqlDb(props);
|
|
295
|
+
case 'docdb':
|
|
296
|
+
return this.loadRowCountDocDb(props);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
165
300
|
}
|
|
166
301
|
exports.PerspectiveDataLoader = PerspectiveDataLoader;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare type PerspectiveDataPatternColumnType = 'null' | 'oid' | 'string' | 'number' | 'boolean' | 'json';
|
|
2
|
+
export interface PerspectiveDataPatternColumn {
|
|
3
|
+
name: string;
|
|
4
|
+
types: PerspectiveDataPatternColumnType[];
|
|
5
|
+
columns: PerspectiveDataPatternColumn[];
|
|
6
|
+
}
|
|
7
|
+
export interface PerspectiveDataPattern {
|
|
8
|
+
conid: string;
|
|
9
|
+
database: string;
|
|
10
|
+
schemaName?: string;
|
|
11
|
+
pureName: string;
|
|
12
|
+
columns: PerspectiveDataPatternColumn[];
|
|
13
|
+
}
|
|
14
|
+
export declare type PerspectiveDataPatternDict = {
|
|
15
|
+
[designerId: string]: PerspectiveDataPattern;
|
|
16
|
+
};
|
|
17
|
+
export declare function analyseDataPattern(patternBase: Omit<PerspectiveDataPattern, 'columns'>, rows: any[]): PerspectiveDataPattern;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.analyseDataPattern = void 0;
|
|
7
|
+
const isString_1 = __importDefault(require("lodash/isString"));
|
|
8
|
+
const isPlainObject_1 = __importDefault(require("lodash/isPlainObject"));
|
|
9
|
+
const isNumber_1 = __importDefault(require("lodash/isNumber"));
|
|
10
|
+
const isBoolean_1 = __importDefault(require("lodash/isBoolean"));
|
|
11
|
+
const isArray_1 = __importDefault(require("lodash/isArray"));
|
|
12
|
+
const dbgate_tools_1 = require("dbgate-tools");
|
|
13
|
+
function detectValueType(value) {
|
|
14
|
+
if ((0, isString_1.default)(value))
|
|
15
|
+
return 'string';
|
|
16
|
+
if ((0, isNumber_1.default)(value))
|
|
17
|
+
return 'number';
|
|
18
|
+
if ((0, isBoolean_1.default)(value))
|
|
19
|
+
return 'boolean';
|
|
20
|
+
if (value === null || value === void 0 ? void 0 : value.$oid)
|
|
21
|
+
return 'oid';
|
|
22
|
+
if ((0, isPlainObject_1.default)(value) || (0, isArray_1.default)(value))
|
|
23
|
+
return 'json';
|
|
24
|
+
if (value == null)
|
|
25
|
+
return 'null';
|
|
26
|
+
}
|
|
27
|
+
function addObjectToColumns(columns, row) {
|
|
28
|
+
if ((0, isPlainObject_1.default)(row)) {
|
|
29
|
+
for (const key of Object.keys(row)) {
|
|
30
|
+
let column = columns.find(x => x.name == key);
|
|
31
|
+
if (!column) {
|
|
32
|
+
column = {
|
|
33
|
+
name: key,
|
|
34
|
+
types: [],
|
|
35
|
+
columns: [],
|
|
36
|
+
};
|
|
37
|
+
columns.push(column);
|
|
38
|
+
}
|
|
39
|
+
const value = row[key];
|
|
40
|
+
const type = detectValueType(value);
|
|
41
|
+
if (!column.types.includes(type)) {
|
|
42
|
+
column.types.push(type);
|
|
43
|
+
}
|
|
44
|
+
if ((0, isPlainObject_1.default)(value)) {
|
|
45
|
+
addObjectToColumns(column.columns, value);
|
|
46
|
+
}
|
|
47
|
+
if ((0, isArray_1.default)(value)) {
|
|
48
|
+
for (const item of value) {
|
|
49
|
+
addObjectToColumns(column.columns, item);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if ((0, isString_1.default)(value)) {
|
|
53
|
+
const json = (0, dbgate_tools_1.safeJsonParse)(value);
|
|
54
|
+
if (json && ((0, isPlainObject_1.default)(json) || (0, isArray_1.default)(json))) {
|
|
55
|
+
if (!column.types.includes('json')) {
|
|
56
|
+
column.types.push('json');
|
|
57
|
+
}
|
|
58
|
+
if ((0, isPlainObject_1.default)(json)) {
|
|
59
|
+
addObjectToColumns(column.columns, json);
|
|
60
|
+
}
|
|
61
|
+
if ((0, isArray_1.default)(json)) {
|
|
62
|
+
for (const item of json) {
|
|
63
|
+
addObjectToColumns(column.columns, item);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function analyseDataPattern(patternBase, rows) {
|
|
72
|
+
const res = Object.assign(Object.assign({}, patternBase), { columns: [] });
|
|
73
|
+
// console.log('ROWS', rows);
|
|
74
|
+
for (const row of rows) {
|
|
75
|
+
addObjectToColumns(res.columns, row);
|
|
76
|
+
}
|
|
77
|
+
return res;
|
|
78
|
+
}
|
|
79
|
+
exports.analyseDataPattern = analyseDataPattern;
|
|
@@ -2,16 +2,15 @@ import { Condition } from 'dbgate-sqltree';
|
|
|
2
2
|
import { RangeDefinition } from 'dbgate-types';
|
|
3
3
|
import { PerspectiveCache } from './PerspectiveCache';
|
|
4
4
|
import { PerspectiveDataLoader } from './PerspectiveDataLoader';
|
|
5
|
+
import { PerspectiveDataPatternDict } from './PerspectiveDataPattern';
|
|
6
|
+
import { PerspectiveDatabaseConfig, PerspectiveDatabaseEngineType } from './PerspectiveConfig';
|
|
5
7
|
export declare const PERSPECTIVE_PAGE_SIZE = 100;
|
|
6
|
-
export interface PerspectiveDatabaseConfig {
|
|
7
|
-
conid: string;
|
|
8
|
-
database: string;
|
|
9
|
-
}
|
|
10
8
|
export interface PerspectiveDataLoadProps {
|
|
11
9
|
databaseConfig: PerspectiveDatabaseConfig;
|
|
12
|
-
schemaName
|
|
10
|
+
schemaName?: string;
|
|
13
11
|
pureName: string;
|
|
14
|
-
dataColumns
|
|
12
|
+
dataColumns?: string[];
|
|
13
|
+
allColumns?: boolean;
|
|
15
14
|
orderBy: {
|
|
16
15
|
columnName: string;
|
|
17
16
|
order: 'ASC' | 'DESC';
|
|
@@ -20,12 +19,15 @@ export interface PerspectiveDataLoadProps {
|
|
|
20
19
|
bindingValues?: any[][];
|
|
21
20
|
range?: RangeDefinition;
|
|
22
21
|
topCount?: number;
|
|
23
|
-
|
|
22
|
+
sqlCondition?: Condition;
|
|
23
|
+
mongoCondition?: any;
|
|
24
|
+
engineType: PerspectiveDatabaseEngineType;
|
|
24
25
|
}
|
|
25
26
|
export declare class PerspectiveDataProvider {
|
|
26
27
|
cache: PerspectiveCache;
|
|
27
28
|
loader: PerspectiveDataLoader;
|
|
28
|
-
|
|
29
|
+
dataPatterns: PerspectiveDataPatternDict;
|
|
30
|
+
constructor(cache: PerspectiveCache, loader: PerspectiveDataLoader, dataPatterns: PerspectiveDataPatternDict);
|
|
29
31
|
loadData(props: PerspectiveDataLoadProps): Promise<{
|
|
30
32
|
rows: any[];
|
|
31
33
|
incomplete: boolean;
|
|
@@ -28,9 +28,10 @@ const debug_1 = __importDefault(require("debug"));
|
|
|
28
28
|
exports.PERSPECTIVE_PAGE_SIZE = 100;
|
|
29
29
|
const dbg = (0, debug_1.default)('dbgate:PerspectiveDataProvider');
|
|
30
30
|
class PerspectiveDataProvider {
|
|
31
|
-
constructor(cache, loader) {
|
|
31
|
+
constructor(cache, loader, dataPatterns) {
|
|
32
32
|
this.cache = cache;
|
|
33
33
|
this.loader = loader;
|
|
34
|
+
this.dataPatterns = dataPatterns;
|
|
34
35
|
}
|
|
35
36
|
loadData(props) {
|
|
36
37
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -164,6 +165,7 @@ class PerspectiveDataProvider {
|
|
|
164
165
|
}
|
|
165
166
|
// load missing rows
|
|
166
167
|
tableCache.dataColumns = props.dataColumns;
|
|
168
|
+
tableCache.allColumns = props.allColumns;
|
|
167
169
|
const nextRows = yield this.loader.loadData(Object.assign(Object.assign({}, props), { topCount: null, range: {
|
|
168
170
|
offset: tableCache.loadedCount,
|
|
169
171
|
limit: props.topCount - tableCache.loadedCount,
|
|
@@ -48,6 +48,7 @@ export declare class PerspectiveDisplay {
|
|
|
48
48
|
fillColumns(children: PerspectiveTreeNode[], parentNodes: PerspectiveTreeNode[]): void;
|
|
49
49
|
processColumn(node: PerspectiveTreeNode, parentNodes: PerspectiveTreeNode[]): void;
|
|
50
50
|
findColumnIndexFromNode(node: PerspectiveTreeNode): number;
|
|
51
|
+
extractArray(value: any): any[];
|
|
51
52
|
collectRows(sourceRows: any[], nodes: PerspectiveTreeNode[]): CollectedPerspectiveDisplayRow[];
|
|
52
53
|
fillRowSpans(): void;
|
|
53
54
|
mergeRows(collectedRows: CollectedPerspectiveDisplayRow[]): void;
|
|
@@ -7,6 +7,8 @@ exports.PerspectiveDisplay = exports.PerspectiveDisplayRow = exports.Perspective
|
|
|
7
7
|
const max_1 = __importDefault(require("lodash/max"));
|
|
8
8
|
const fill_1 = __importDefault(require("lodash/fill"));
|
|
9
9
|
const findIndex_1 = __importDefault(require("lodash/findIndex"));
|
|
10
|
+
const isPlainObject_1 = __importDefault(require("lodash/isPlainObject"));
|
|
11
|
+
const isArray_1 = __importDefault(require("lodash/isArray"));
|
|
10
12
|
const debug_1 = __importDefault(require("debug"));
|
|
11
13
|
const dbg = (0, debug_1.default)('dbgate:PerspectiveDisplay');
|
|
12
14
|
let lastJoinId = 0;
|
|
@@ -99,14 +101,14 @@ class PerspectiveDisplay {
|
|
|
99
101
|
}
|
|
100
102
|
fillColumns(children, parentNodes) {
|
|
101
103
|
for (const child of children) {
|
|
102
|
-
if (child.
|
|
104
|
+
if (child.generatesHiearchicGridColumn || child.generatesDataGridColumn) {
|
|
103
105
|
this.processColumn(child, parentNodes);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
}
|
|
107
109
|
processColumn(node, parentNodes) {
|
|
108
110
|
var _a, _b;
|
|
109
|
-
if (node.
|
|
111
|
+
if (node.generatesDataGridColumn) {
|
|
110
112
|
const column = new PerspectiveDisplayColumn(this);
|
|
111
113
|
column.title = node.columnTitle;
|
|
112
114
|
column.dataField = node.dataField;
|
|
@@ -117,7 +119,7 @@ class PerspectiveDisplay {
|
|
|
117
119
|
column.displayType = (_b = (_a = node.parentNodeConfig) === null || _a === void 0 ? void 0 : _a.columnDisplays) === null || _b === void 0 ? void 0 : _b[node.columnName];
|
|
118
120
|
this.columns.push(column);
|
|
119
121
|
}
|
|
120
|
-
if (node.
|
|
122
|
+
if (node.generatesHiearchicGridColumn) {
|
|
121
123
|
const countBefore = this.columns.length;
|
|
122
124
|
this.fillColumns(node.childNodes, [...parentNodes, node]);
|
|
123
125
|
if (this.columns.length > countBefore) {
|
|
@@ -131,23 +133,41 @@ class PerspectiveDisplay {
|
|
|
131
133
|
// findColumnIndexFromNode(node: PerspectiveTreeNode) {
|
|
132
134
|
// return _findIndex(this.columns, x => x.dataNode.designerId == node.designerId);
|
|
133
135
|
// }
|
|
136
|
+
extractArray(value) {
|
|
137
|
+
if ((0, isArray_1.default)(value))
|
|
138
|
+
return value;
|
|
139
|
+
if ((0, isPlainObject_1.default)(value))
|
|
140
|
+
return [value];
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
134
143
|
collectRows(sourceRows, nodes) {
|
|
135
144
|
// console.log('********** COLLECT ROWS', sourceRows);
|
|
136
|
-
const columnNodes = nodes.filter(x => x.
|
|
137
|
-
const treeNodes = nodes.filter(x => x.
|
|
138
|
-
// console.log(
|
|
139
|
-
//
|
|
145
|
+
const columnNodes = nodes.filter(x => x.generatesDataGridColumn);
|
|
146
|
+
const treeNodes = nodes.filter(x => x.generatesHiearchicGridColumn);
|
|
147
|
+
// console.log(
|
|
148
|
+
// 'columnNodes',
|
|
149
|
+
// columnNodes.map(x => x.title)
|
|
150
|
+
// );
|
|
151
|
+
// console.log(
|
|
152
|
+
// 'treeNodes',
|
|
153
|
+
// treeNodes.map(x => x.title)
|
|
154
|
+
// );
|
|
155
|
+
// console.log(
|
|
156
|
+
// 'nodes',
|
|
157
|
+
// nodes.map(x => x.title)
|
|
158
|
+
// );
|
|
140
159
|
const columnIndexes = columnNodes.map(node => this.findColumnIndexFromNode(node));
|
|
141
160
|
const res = [];
|
|
142
161
|
for (const sourceRow of sourceRows) {
|
|
143
162
|
// console.log('PROCESS SOURCE', sourceRow);
|
|
144
163
|
// row.startIndex = startIndex;
|
|
145
|
-
const rowData = columnNodes.map(node => sourceRow[node.
|
|
164
|
+
const rowData = columnNodes.map(node => sourceRow[node.columnName]);
|
|
146
165
|
const subRowCollections = [];
|
|
147
166
|
for (const node of treeNodes) {
|
|
167
|
+
// console.log('sourceRow[node.fieldName]', node.fieldName, sourceRow[node.fieldName]);
|
|
148
168
|
if (sourceRow[node.fieldName]) {
|
|
149
169
|
const subrows = {
|
|
150
|
-
rows: this.collectRows(sourceRow[node.fieldName], node.childNodes),
|
|
170
|
+
rows: this.collectRows(this.extractArray(sourceRow[node.fieldName]), node.childNodes),
|
|
151
171
|
};
|
|
152
172
|
subRowCollections.push(subrows);
|
|
153
173
|
}
|