@milaboratories/pf-driver 1.0.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.
- package/README.md +1 -0
- package/dist/__external/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.7.0_typescript@5.6.3/__external/tslib/tslib.es6.cjs +77 -0
- package/dist/__external/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.7.0_typescript@5.6.3/__external/tslib/tslib.es6.cjs.map +1 -0
- package/dist/__external/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.7.0_typescript@5.6.3/__external/tslib/tslib.es6.js +74 -0
- package/dist/__external/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.7.0_typescript@5.6.3/__external/tslib/tslib.es6.js.map +1 -0
- package/dist/data_info_helpers.cjs +21 -0
- package/dist/data_info_helpers.cjs.map +1 -0
- package/dist/data_info_helpers.d.ts +3 -0
- package/dist/data_info_helpers.d.ts.map +1 -0
- package/dist/data_info_helpers.js +19 -0
- package/dist/data_info_helpers.js.map +1 -0
- package/dist/driver_decl.d.ts +38 -0
- package/dist/driver_decl.d.ts.map +1 -0
- package/dist/driver_double.cjs +98 -0
- package/dist/driver_double.cjs.map +1 -0
- package/dist/driver_double.d.ts +12 -0
- package/dist/driver_double.d.ts.map +1 -0
- package/dist/driver_double.js +95 -0
- package/dist/driver_double.js.map +1 -0
- package/dist/driver_impl.cjs +378 -0
- package/dist/driver_impl.cjs.map +1 -0
- package/dist/driver_impl.d.ts +54 -0
- package/dist/driver_impl.d.ts.map +1 -0
- package/dist/driver_impl.js +375 -0
- package/dist/driver_impl.js.map +1 -0
- package/dist/index.cjs +14 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/logging.cjs +9 -0
- package/dist/logging.cjs.map +1 -0
- package/dist/logging.d.ts +2 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +7 -0
- package/dist/logging.js.map +1 -0
- package/dist/pframe_pool.cjs +196 -0
- package/dist/pframe_pool.cjs.map +1 -0
- package/dist/pframe_pool.d.ts +35 -0
- package/dist/pframe_pool.d.ts.map +1 -0
- package/dist/pframe_pool.js +193 -0
- package/dist/pframe_pool.js.map +1 -0
- package/dist/ptable_cache_per_frame.cjs +69 -0
- package/dist/ptable_cache_per_frame.cjs.map +1 -0
- package/dist/ptable_cache_per_frame.d.ts +25 -0
- package/dist/ptable_cache_per_frame.d.ts.map +1 -0
- package/dist/ptable_cache_per_frame.js +66 -0
- package/dist/ptable_cache_per_frame.js.map +1 -0
- package/dist/ptable_cache_plain.cjs +54 -0
- package/dist/ptable_cache_plain.cjs.map +1 -0
- package/dist/ptable_cache_plain.d.ts +21 -0
- package/dist/ptable_cache_plain.d.ts.map +1 -0
- package/dist/ptable_cache_plain.js +51 -0
- package/dist/ptable_cache_plain.js.map +1 -0
- package/dist/ptable_def_pool.cjs +53 -0
- package/dist/ptable_def_pool.cjs.map +1 -0
- package/dist/ptable_def_pool.d.ts +21 -0
- package/dist/ptable_def_pool.d.ts.map +1 -0
- package/dist/ptable_def_pool.js +50 -0
- package/dist/ptable_def_pool.js.map +1 -0
- package/dist/ptable_pool.cjs +167 -0
- package/dist/ptable_pool.cjs.map +1 -0
- package/dist/ptable_pool.d.ts +26 -0
- package/dist/ptable_pool.d.ts.map +1 -0
- package/dist/ptable_pool.js +164 -0
- package/dist/ptable_pool.js.map +1 -0
- package/dist/ptable_shared.cjs +10 -0
- package/dist/ptable_shared.cjs.map +1 -0
- package/dist/ptable_shared.d.ts +7 -0
- package/dist/ptable_shared.d.ts.map +1 -0
- package/dist/ptable_shared.js +8 -0
- package/dist/ptable_shared.js.map +1 -0
- package/package.json +54 -0
- package/src/data_info_helpers.ts +26 -0
- package/src/driver_decl.ts +82 -0
- package/src/driver_double.test.ts +135 -0
- package/src/driver_double.ts +134 -0
- package/src/driver_impl.ts +535 -0
- package/src/index.ts +4 -0
- package/src/logging.ts +5 -0
- package/src/pframe_pool.ts +257 -0
- package/src/ptable_cache_per_frame.ts +86 -0
- package/src/ptable_cache_plain.ts +67 -0
- package/src/ptable_def_pool.ts +50 -0
- package/src/ptable_pool.ts +187 -0
- package/src/ptable_shared.ts +11 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mapPObjectData,
|
|
3
|
+
mapPTableDef,
|
|
4
|
+
extractAllColumns,
|
|
5
|
+
uniqueBy,
|
|
6
|
+
getAxisId,
|
|
7
|
+
canonicalizeJson,
|
|
8
|
+
bigintReplacer,
|
|
9
|
+
ValueType,
|
|
10
|
+
type CalculateTableDataRequest,
|
|
11
|
+
type CalculateTableDataResponse,
|
|
12
|
+
type FindColumnsRequest,
|
|
13
|
+
type FindColumnsResponse,
|
|
14
|
+
type PColumnIdAndSpec,
|
|
15
|
+
type PColumnSpec,
|
|
16
|
+
type PFrameHandle,
|
|
17
|
+
type PObjectId,
|
|
18
|
+
type PTableColumnSpec,
|
|
19
|
+
type PTableHandle,
|
|
20
|
+
type PTableShape,
|
|
21
|
+
type PTableVector,
|
|
22
|
+
type TableRange,
|
|
23
|
+
type UniqueValuesRequest,
|
|
24
|
+
type UniqueValuesResponse,
|
|
25
|
+
type PColumn,
|
|
26
|
+
type PFrameDef,
|
|
27
|
+
type JoinEntry,
|
|
28
|
+
type PTableDef,
|
|
29
|
+
type PTableRecordSingleValueFilterV2,
|
|
30
|
+
type PTableRecordFilter,
|
|
31
|
+
type JsonSerializable,
|
|
32
|
+
} from '@platforma-sdk/model';
|
|
33
|
+
import type { PFrameInternal } from '@milaboratories/pl-model-middle-layer';
|
|
34
|
+
import {
|
|
35
|
+
assertNever,
|
|
36
|
+
ConcurrencyLimitingExecutor,
|
|
37
|
+
type PoolEntry,
|
|
38
|
+
} from '@milaboratories/ts-helpers';
|
|
39
|
+
import { PFrameFactory } from '@milaboratories/pframes-rs-node';
|
|
40
|
+
import { tmpdir } from 'node:os';
|
|
41
|
+
import type {
|
|
42
|
+
AbstractInternalPFrameDriver,
|
|
43
|
+
} from './driver_decl';
|
|
44
|
+
import { logPFrames } from './logging';
|
|
45
|
+
import {
|
|
46
|
+
PFramePool,
|
|
47
|
+
type LocalBlobProvider as PoolLocalBlobProvider,
|
|
48
|
+
type RemoteBlobProvider as PoolRemoteBlobProvider,
|
|
49
|
+
} from './pframe_pool';
|
|
50
|
+
import { PTableDefPool } from './ptable_def_pool';
|
|
51
|
+
import { PTablePool } from './ptable_pool';
|
|
52
|
+
import {
|
|
53
|
+
PTableCachePerFrame,
|
|
54
|
+
PTableCachePerFrameOpsDefaults,
|
|
55
|
+
type PTableCachePerFrameOps,
|
|
56
|
+
} from './ptable_cache_per_frame';
|
|
57
|
+
import {
|
|
58
|
+
PTableCachePlain,
|
|
59
|
+
PTableCachePlainOpsDefaults,
|
|
60
|
+
type PTableCachePlainOps,
|
|
61
|
+
} from './ptable_cache_plain';
|
|
62
|
+
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
64
|
+
export interface LocalBlobProvider<TreeEntry extends JsonSerializable>
|
|
65
|
+
extends PoolLocalBlobProvider<TreeEntry> { }
|
|
66
|
+
|
|
67
|
+
export interface RemoteBlobProvider<TreeEntry extends JsonSerializable>
|
|
68
|
+
extends PoolRemoteBlobProvider<TreeEntry>, AsyncDisposable {}
|
|
69
|
+
|
|
70
|
+
export type AbstractPFrameDriverOps = PTableCachePerFrameOps & PTableCachePlainOps & {
|
|
71
|
+
/** Concurrency limits for `getUniqueValues` and `calculateTableData` requests */
|
|
72
|
+
pFrameConcurrency: number;
|
|
73
|
+
/** Concurrency limits for `getShape` and `getData` requests */
|
|
74
|
+
pTableConcurrency: number;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const AbstractPFrameDriverOpsDefaults: AbstractPFrameDriverOps = {
|
|
78
|
+
...PTableCachePerFrameOpsDefaults,
|
|
79
|
+
...PTableCachePlainOpsDefaults,
|
|
80
|
+
pFrameConcurrency: 1, // 1 join is executed in parallel and utilize all RAM and CPU cores
|
|
81
|
+
pTableConcurrency: 1, // 1 joined table is read from disk at a time, which matches 1 table the user can view in the UI
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export type DataInfoResolver<PColumnData, TreeEntry extends JsonSerializable> = (
|
|
85
|
+
spec: PColumnSpec,
|
|
86
|
+
data: PColumnData,
|
|
87
|
+
) => PFrameInternal.DataInfo<TreeEntry>;
|
|
88
|
+
|
|
89
|
+
export class AbstractPFrameDriver<PColumnData, TreeEntry extends JsonSerializable>
|
|
90
|
+
implements AbstractInternalPFrameDriver<PColumnData> {
|
|
91
|
+
private readonly logger: PFrameInternal.Logger;
|
|
92
|
+
|
|
93
|
+
private readonly localBlobProvider: LocalBlobProvider<TreeEntry>;
|
|
94
|
+
private readonly remoteBlobProvider: RemoteBlobProvider<TreeEntry>;
|
|
95
|
+
|
|
96
|
+
private readonly resolveDataInfo: DataInfoResolver<PColumnData, TreeEntry>;
|
|
97
|
+
|
|
98
|
+
private readonly pFrames: PFramePool<TreeEntry>;
|
|
99
|
+
private readonly pTableDefs: PTableDefPool;
|
|
100
|
+
private readonly pTables: PTablePool<TreeEntry>;
|
|
101
|
+
|
|
102
|
+
private readonly pTableCachePerFrame: PTableCachePerFrame;
|
|
103
|
+
private readonly pTableCachePlain: PTableCachePlain;
|
|
104
|
+
|
|
105
|
+
private readonly frameConcurrencyLimiter: ConcurrencyLimitingExecutor;
|
|
106
|
+
private readonly tableConcurrencyLimiter: ConcurrencyLimitingExecutor;
|
|
107
|
+
|
|
108
|
+
public async pprofDump(): Promise<Uint8Array> {
|
|
109
|
+
return await PFrameFactory.pprofDump();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public constructor({
|
|
113
|
+
logger = () => {},
|
|
114
|
+
localBlobProvider,
|
|
115
|
+
remoteBlobProvider,
|
|
116
|
+
spillPath = tmpdir(),
|
|
117
|
+
options = AbstractPFrameDriverOpsDefaults,
|
|
118
|
+
resolveDataInfo,
|
|
119
|
+
}: {
|
|
120
|
+
logger?: PFrameInternal.Logger;
|
|
121
|
+
localBlobProvider: LocalBlobProvider<TreeEntry>;
|
|
122
|
+
remoteBlobProvider: RemoteBlobProvider<TreeEntry>;
|
|
123
|
+
spillPath?: string;
|
|
124
|
+
options?: AbstractPFrameDriverOps;
|
|
125
|
+
resolveDataInfo: DataInfoResolver<PColumnData, TreeEntry>;
|
|
126
|
+
}) {
|
|
127
|
+
this.logger = logger;
|
|
128
|
+
|
|
129
|
+
this.localBlobProvider = localBlobProvider;
|
|
130
|
+
this.remoteBlobProvider = remoteBlobProvider;
|
|
131
|
+
|
|
132
|
+
this.resolveDataInfo = resolveDataInfo;
|
|
133
|
+
|
|
134
|
+
this.frameConcurrencyLimiter = new ConcurrencyLimitingExecutor(options.pFrameConcurrency);
|
|
135
|
+
this.tableConcurrencyLimiter = new ConcurrencyLimitingExecutor(options.pTableConcurrency);
|
|
136
|
+
|
|
137
|
+
this.pFrames = new PFramePool(this.localBlobProvider, this.remoteBlobProvider, this.logger, spillPath);
|
|
138
|
+
this.pTableDefs = new PTableDefPool(this.logger);
|
|
139
|
+
this.pTables = new PTablePool(this.pFrames, this.pTableDefs, this.logger);
|
|
140
|
+
|
|
141
|
+
this.pTableCachePerFrame = new PTableCachePerFrame(this.logger, options);
|
|
142
|
+
this.pTableCachePlain = new PTableCachePlain(this.logger, options);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async dispose(): Promise<void> {
|
|
146
|
+
return await this.remoteBlobProvider[Symbol.asyncDispose]();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async [Symbol.asyncDispose](): Promise<void> {
|
|
150
|
+
return await this.dispose();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
//
|
|
154
|
+
// Internal / Config API Methods
|
|
155
|
+
//
|
|
156
|
+
|
|
157
|
+
public createPFrame(
|
|
158
|
+
def: PFrameDef<PColumn<PColumnData>>,
|
|
159
|
+
): PoolEntry<PFrameHandle> {
|
|
160
|
+
const ValueTypes = new Set(Object.values(ValueType));
|
|
161
|
+
|
|
162
|
+
const supportedColumns = def.filter((column) => ValueTypes.has(column.spec.valueType));
|
|
163
|
+
const uniqueColumns = uniqueBy(supportedColumns, (column) => column.id);
|
|
164
|
+
const columns = uniqueColumns.map((c) => mapPObjectData(c, (d) => this.resolveDataInfo(c.spec, d)));
|
|
165
|
+
|
|
166
|
+
return this.pFrames.acquire(columns);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public createPTable(
|
|
170
|
+
rawDef: PTableDef<PColumn<PColumnData>>,
|
|
171
|
+
): PoolEntry<PTableHandle> {
|
|
172
|
+
const pFrameEntry = this.createPFrame(extractAllColumns(rawDef.src));
|
|
173
|
+
const sortedDef = sortPTableDef(migratePTableFilters(mapPTableDef(rawDef, (c) => c.id), this.logger));
|
|
174
|
+
|
|
175
|
+
const pTableEntry = this.pTableDefs.acquire({ def: sortedDef, pFrameHandle: pFrameEntry.key });
|
|
176
|
+
if (logPFrames()) {
|
|
177
|
+
this.logger('info', `Create PTable call (pFrameHandle = ${pFrameEntry.key}; pTableHandle = ${pTableEntry.key})`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const unref = () => {
|
|
181
|
+
pTableEntry.unref();
|
|
182
|
+
pFrameEntry.unref();
|
|
183
|
+
};
|
|
184
|
+
return {
|
|
185
|
+
key: pTableEntry.key,
|
|
186
|
+
resource: pTableEntry.resource,
|
|
187
|
+
unref,
|
|
188
|
+
[Symbol.dispose]: unref,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
//
|
|
193
|
+
// PFrame istance methods
|
|
194
|
+
//
|
|
195
|
+
|
|
196
|
+
public async findColumns(
|
|
197
|
+
handle: PFrameHandle,
|
|
198
|
+
request: FindColumnsRequest,
|
|
199
|
+
): Promise<FindColumnsResponse> {
|
|
200
|
+
const iRequest: PFrameInternal.FindColumnsRequest = {
|
|
201
|
+
...request,
|
|
202
|
+
compatibleWith:
|
|
203
|
+
request.compatibleWith.length !== 0
|
|
204
|
+
? [{
|
|
205
|
+
axesSpec: [
|
|
206
|
+
...new Map(request.compatibleWith.map(
|
|
207
|
+
(item) => [canonicalizeJson(item), item] as const,
|
|
208
|
+
)).values(),
|
|
209
|
+
],
|
|
210
|
+
qualifications: [],
|
|
211
|
+
}]
|
|
212
|
+
: [],
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const { pFramePromise } = this.pFrames.getByKey(handle);
|
|
216
|
+
const pFrame = await pFramePromise;
|
|
217
|
+
|
|
218
|
+
const responce = await pFrame.findColumns(iRequest);
|
|
219
|
+
return {
|
|
220
|
+
hits: responce.hits
|
|
221
|
+
.filter((h) => // only exactly matching columns
|
|
222
|
+
h.mappingVariants.length === 0
|
|
223
|
+
|| h.mappingVariants.some((v) =>
|
|
224
|
+
v.qualifications.forHit.length === 0
|
|
225
|
+
&& v.qualifications.forQueries.every((q) => q.length === 0)))
|
|
226
|
+
.map((h) => h.hit),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
public async getColumnSpec(handle: PFrameHandle, columnId: PObjectId): Promise<PColumnSpec> {
|
|
231
|
+
const { pFramePromise } = this.pFrames.getByKey(handle);
|
|
232
|
+
const pFrame = await pFramePromise;
|
|
233
|
+
return await pFrame.getColumnSpec(columnId);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
public async listColumns(handle: PFrameHandle): Promise<PColumnIdAndSpec[]> {
|
|
237
|
+
const { pFramePromise } = this.pFrames.getByKey(handle);
|
|
238
|
+
const pFrame = await pFramePromise;
|
|
239
|
+
return await pFrame.listColumns();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
public async calculateTableData(
|
|
243
|
+
handle: PFrameHandle,
|
|
244
|
+
request: CalculateTableDataRequest<PObjectId>,
|
|
245
|
+
range: TableRange | undefined,
|
|
246
|
+
signal?: AbortSignal,
|
|
247
|
+
): Promise<CalculateTableDataResponse> {
|
|
248
|
+
if (logPFrames()) {
|
|
249
|
+
this.logger('info',
|
|
250
|
+
`Call calculateTableData, handle = ${handle}, request = ${JSON.stringify(request, bigintReplacer)}`,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const table = this.pTables.acquire({
|
|
255
|
+
pFrameHandle: handle,
|
|
256
|
+
def: sortPTableDef(migratePTableFilters(request, this.logger)),
|
|
257
|
+
});
|
|
258
|
+
const { pTablePromise, disposeSignal } = table.resource;
|
|
259
|
+
const pTable = await pTablePromise;
|
|
260
|
+
|
|
261
|
+
const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));
|
|
262
|
+
return await this.frameConcurrencyLimiter.run(async () => {
|
|
263
|
+
try {
|
|
264
|
+
// TODO: throw error when more then 150k rows is requested
|
|
265
|
+
// after pf-plots migration to stream API
|
|
266
|
+
|
|
267
|
+
const spec = pTable.getSpec();
|
|
268
|
+
const data = await pTable.getData([...spec.keys()], {
|
|
269
|
+
range,
|
|
270
|
+
signal: combinedSignal,
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const overallSize = await pTable.getFootprint({
|
|
274
|
+
withPredecessors: true,
|
|
275
|
+
signal: combinedSignal,
|
|
276
|
+
});
|
|
277
|
+
this.pTableCachePerFrame.cache(table, overallSize);
|
|
278
|
+
|
|
279
|
+
return spec.map((spec, i) => ({
|
|
280
|
+
spec: spec,
|
|
281
|
+
data: data[i],
|
|
282
|
+
}));
|
|
283
|
+
} catch (err: unknown) {
|
|
284
|
+
table.unref();
|
|
285
|
+
throw err;
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
public async getUniqueValues(
|
|
291
|
+
handle: PFrameHandle,
|
|
292
|
+
request: UniqueValuesRequest,
|
|
293
|
+
signal?: AbortSignal,
|
|
294
|
+
): Promise<UniqueValuesResponse> {
|
|
295
|
+
if (logPFrames()) {
|
|
296
|
+
this.logger('info',
|
|
297
|
+
`Call getUniqueValues, handle = ${handle}, request = ${JSON.stringify(request, bigintReplacer)}`,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const { pFramePromise, disposeSignal } = this.pFrames.getByKey(handle);
|
|
302
|
+
const pFrame = await pFramePromise;
|
|
303
|
+
|
|
304
|
+
const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));
|
|
305
|
+
return await this.frameConcurrencyLimiter.run(async () => {
|
|
306
|
+
return await pFrame.getUniqueValues({
|
|
307
|
+
...request,
|
|
308
|
+
filters: migrateFilters(request.filters, this.logger),
|
|
309
|
+
}, {
|
|
310
|
+
signal: combinedSignal,
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
//
|
|
316
|
+
// PTable istance methods
|
|
317
|
+
//
|
|
318
|
+
|
|
319
|
+
public async getSpec(handle: PTableHandle): Promise<PTableColumnSpec[]> {
|
|
320
|
+
const { def } = this.pTableDefs.getByKey(handle);
|
|
321
|
+
using table = this.pTables.acquire(def);
|
|
322
|
+
|
|
323
|
+
const { pTablePromise } = table.resource;
|
|
324
|
+
const pTable = await pTablePromise;
|
|
325
|
+
|
|
326
|
+
return pTable.getSpec();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
public async getShape(handle: PTableHandle, signal?: AbortSignal): Promise<PTableShape> {
|
|
330
|
+
const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);
|
|
331
|
+
const table = this.pTables.acquire(def);
|
|
332
|
+
|
|
333
|
+
const { pTablePromise, disposeSignal } = table.resource;
|
|
334
|
+
const pTable = await pTablePromise;
|
|
335
|
+
|
|
336
|
+
const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));
|
|
337
|
+
const { shape, overallSize } = await this.tableConcurrencyLimiter.run(async () => {
|
|
338
|
+
const shape = await pTable.getShape({
|
|
339
|
+
signal: combinedSignal,
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const overallSize = await pTable.getFootprint({
|
|
343
|
+
withPredecessors: true,
|
|
344
|
+
signal: combinedSignal,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
return { shape, overallSize };
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
this.pTableCachePlain.cache(table, overallSize, defDisposeSignal);
|
|
351
|
+
return shape;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
public async getData(
|
|
355
|
+
handle: PTableHandle,
|
|
356
|
+
columnIndices: number[],
|
|
357
|
+
range: TableRange | undefined,
|
|
358
|
+
signal?: AbortSignal,
|
|
359
|
+
): Promise<PTableVector[]> {
|
|
360
|
+
const { def, disposeSignal: defDisposeSignal } = this.pTableDefs.getByKey(handle);
|
|
361
|
+
const table = this.pTables.acquire(def);
|
|
362
|
+
|
|
363
|
+
const { pTablePromise, disposeSignal } = table.resource;
|
|
364
|
+
const pTable = await pTablePromise;
|
|
365
|
+
|
|
366
|
+
const combinedSignal = AbortSignal.any([signal, disposeSignal].filter((s) => !!s));
|
|
367
|
+
const { data, overallSize } = await this.tableConcurrencyLimiter.run(async () => {
|
|
368
|
+
const data = await pTable.getData(columnIndices, {
|
|
369
|
+
range,
|
|
370
|
+
signal: combinedSignal,
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
const overallSize = await pTable.getFootprint({
|
|
374
|
+
withPredecessors: true,
|
|
375
|
+
signal: combinedSignal,
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
return { data, overallSize };
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
this.pTableCachePlain.cache(table, overallSize, defDisposeSignal);
|
|
382
|
+
return data;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function sortPTableDef(def: PTableDef<PObjectId>): PTableDef<PObjectId> {
|
|
387
|
+
function cmpJoinEntries(lhs: JoinEntry<PObjectId>, rhs: JoinEntry<PObjectId>): number {
|
|
388
|
+
if (lhs.type !== rhs.type) {
|
|
389
|
+
return lhs.type < rhs.type ? -1 : 1;
|
|
390
|
+
}
|
|
391
|
+
const type = lhs.type;
|
|
392
|
+
switch (type) {
|
|
393
|
+
case 'column':
|
|
394
|
+
return lhs.column < (rhs as typeof lhs).column ? -1 : 1;
|
|
395
|
+
case 'slicedColumn':
|
|
396
|
+
case 'artificialColumn':
|
|
397
|
+
return lhs.newId < (rhs as typeof lhs).newId ? -1 : 1;
|
|
398
|
+
case 'inlineColumn': {
|
|
399
|
+
return lhs.column.id < (rhs as typeof lhs).column.id ? -1 : 1;
|
|
400
|
+
}
|
|
401
|
+
case 'inner':
|
|
402
|
+
case 'full': {
|
|
403
|
+
const rhsInner = rhs as typeof lhs;
|
|
404
|
+
if (lhs.entries.length !== rhsInner.entries.length) {
|
|
405
|
+
return lhs.entries.length - rhsInner.entries.length;
|
|
406
|
+
}
|
|
407
|
+
for (let i = 0; i < lhs.entries.length; i++) {
|
|
408
|
+
const cmp = cmpJoinEntries(lhs.entries[i], rhsInner.entries[i]);
|
|
409
|
+
if (cmp !== 0) {
|
|
410
|
+
return cmp;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return 0;
|
|
414
|
+
}
|
|
415
|
+
case 'outer': {
|
|
416
|
+
const rhsOuter = rhs as typeof lhs;
|
|
417
|
+
const cmp = cmpJoinEntries(lhs.primary, rhsOuter.primary);
|
|
418
|
+
if (cmp !== 0) {
|
|
419
|
+
return cmp;
|
|
420
|
+
}
|
|
421
|
+
if (lhs.secondary.length !== rhsOuter.secondary.length) {
|
|
422
|
+
return lhs.secondary.length - rhsOuter.secondary.length;
|
|
423
|
+
}
|
|
424
|
+
for (let i = 0; i < lhs.secondary.length; i++) {
|
|
425
|
+
const cmp = cmpJoinEntries(lhs.secondary[i], rhsOuter.secondary[i]);
|
|
426
|
+
if (cmp !== 0) {
|
|
427
|
+
return cmp;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return 0;
|
|
431
|
+
}
|
|
432
|
+
default:
|
|
433
|
+
assertNever(type);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
function sortJoinEntry(entry: JoinEntry<PObjectId>): JoinEntry<PObjectId> {
|
|
437
|
+
switch (entry.type) {
|
|
438
|
+
case 'column':
|
|
439
|
+
case 'slicedColumn':
|
|
440
|
+
case 'inlineColumn':
|
|
441
|
+
return entry;
|
|
442
|
+
case 'artificialColumn': {
|
|
443
|
+
const sortedAxesIndices = entry.axesIndices.toSorted((lhs, rhs) => lhs - rhs);
|
|
444
|
+
return {
|
|
445
|
+
...entry,
|
|
446
|
+
axesIndices: sortedAxesIndices,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
case 'inner':
|
|
450
|
+
case 'full': {
|
|
451
|
+
const sortedEntries = entry.entries.map(sortJoinEntry);
|
|
452
|
+
sortedEntries.sort(cmpJoinEntries);
|
|
453
|
+
return {
|
|
454
|
+
...entry,
|
|
455
|
+
entries: sortedEntries,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
case 'outer': {
|
|
459
|
+
const sortedSecondary = entry.secondary.map(sortJoinEntry);
|
|
460
|
+
sortedSecondary.sort(cmpJoinEntries);
|
|
461
|
+
return {
|
|
462
|
+
...entry,
|
|
463
|
+
primary: sortJoinEntry(entry.primary),
|
|
464
|
+
secondary: sortedSecondary,
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
default:
|
|
468
|
+
assertNever(entry);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
function sortFilters(filters: PTableRecordFilter[]): PTableRecordFilter[] {
|
|
472
|
+
return filters.toSorted((lhs, rhs) => {
|
|
473
|
+
if (lhs.column.type === 'axis' && rhs.column.type === 'axis') {
|
|
474
|
+
const lhsId = canonicalizeJson(getAxisId(lhs.column.id));
|
|
475
|
+
const rhsId = canonicalizeJson(getAxisId(rhs.column.id));
|
|
476
|
+
return lhsId < rhsId ? -1 : 1;
|
|
477
|
+
} else if (lhs.column.type === 'column' && rhs.column.type === 'column') {
|
|
478
|
+
return lhs.column.id < rhs.column.id ? -1 : 1;
|
|
479
|
+
} else {
|
|
480
|
+
return lhs.column.type === 'axis' ? -1 : 1;
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
return {
|
|
485
|
+
src: sortJoinEntry(def.src),
|
|
486
|
+
partitionFilters: sortFilters(def.partitionFilters),
|
|
487
|
+
filters: sortFilters(def.filters),
|
|
488
|
+
sorting: def.sorting,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function migrateFilters(
|
|
493
|
+
filters: PTableRecordFilter[],
|
|
494
|
+
logger: PFrameInternal.Logger,
|
|
495
|
+
): PTableRecordFilter[] {
|
|
496
|
+
const filtersV1 = [];
|
|
497
|
+
const filtersV2: PTableRecordSingleValueFilterV2[] = [];
|
|
498
|
+
for (const filter of filters) {
|
|
499
|
+
if ((filter.type as unknown) === 'bySingleColumn') {
|
|
500
|
+
filtersV1.push(filter);
|
|
501
|
+
filtersV2.push({
|
|
502
|
+
...filter,
|
|
503
|
+
type: 'bySingleColumnV2',
|
|
504
|
+
});
|
|
505
|
+
} else {
|
|
506
|
+
filtersV2.push(filter);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
if (filtersV1.length > 0) {
|
|
510
|
+
const filtersV1Json = JSON.stringify(filtersV1);
|
|
511
|
+
logger('warn',
|
|
512
|
+
`type overriten from 'bySingleColumn' to 'bySingleColumnV2' for filters: ${filtersV1Json}`,
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
return filtersV2;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function migratePTableFilters<T>(
|
|
519
|
+
def: Omit<PTableDef<T>, 'partitionFilters'> | PTableDef<T>,
|
|
520
|
+
logger: PFrameInternal.Logger,
|
|
521
|
+
): PTableDef<T> {
|
|
522
|
+
if (!('partitionFilters' in def)) {
|
|
523
|
+
// For old blocks assume all axes filters to be partition filters
|
|
524
|
+
return {
|
|
525
|
+
...def,
|
|
526
|
+
partitionFilters: migrateFilters(def.filters.filter((f) => f.column.type === 'axis'), logger),
|
|
527
|
+
filters: migrateFilters(def.filters.filter((f) => f.column.type === 'column'), logger),
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
return {
|
|
531
|
+
...def,
|
|
532
|
+
partitionFilters: migrateFilters(def.partitionFilters, logger),
|
|
533
|
+
filters: migrateFilters(def.filters, logger),
|
|
534
|
+
};
|
|
535
|
+
}
|
package/src/index.ts
ADDED